1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <string.h> 11e1051a39Sopenharmony_ci#include <openssl/err.h> 12e1051a39Sopenharmony_ci#include <openssl/ui.h> 13e1051a39Sopenharmony_ci#include "apps_ui.h" 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_cistatic UI_METHOD *ui_method = NULL; 16e1051a39Sopenharmony_cistatic const UI_METHOD *ui_base_method = NULL; 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_cistatic int ui_open(UI *ui) 19e1051a39Sopenharmony_ci{ 20e1051a39Sopenharmony_ci int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method); 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci if (opener != NULL) 23e1051a39Sopenharmony_ci return opener(ui); 24e1051a39Sopenharmony_ci return 1; 25e1051a39Sopenharmony_ci} 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_cistatic int ui_read(UI *ui, UI_STRING *uis) 28e1051a39Sopenharmony_ci{ 29e1051a39Sopenharmony_ci int (*reader)(UI *ui, UI_STRING *uis) = NULL; 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 32e1051a39Sopenharmony_ci && UI_get0_user_data(ui)) { 33e1051a39Sopenharmony_ci switch (UI_get_string_type(uis)) { 34e1051a39Sopenharmony_ci case UIT_PROMPT: 35e1051a39Sopenharmony_ci case UIT_VERIFY: 36e1051a39Sopenharmony_ci { 37e1051a39Sopenharmony_ci const char *password = 38e1051a39Sopenharmony_ci ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci if (password != NULL) { 41e1051a39Sopenharmony_ci UI_set_result(ui, uis, password); 42e1051a39Sopenharmony_ci return 1; 43e1051a39Sopenharmony_ci } 44e1051a39Sopenharmony_ci } 45e1051a39Sopenharmony_ci break; 46e1051a39Sopenharmony_ci case UIT_NONE: 47e1051a39Sopenharmony_ci case UIT_BOOLEAN: 48e1051a39Sopenharmony_ci case UIT_INFO: 49e1051a39Sopenharmony_ci case UIT_ERROR: 50e1051a39Sopenharmony_ci break; 51e1051a39Sopenharmony_ci } 52e1051a39Sopenharmony_ci } 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci reader = UI_method_get_reader(ui_base_method); 55e1051a39Sopenharmony_ci if (reader != NULL) 56e1051a39Sopenharmony_ci return reader(ui, uis); 57e1051a39Sopenharmony_ci /* Default to the empty password if we've got nothing better */ 58e1051a39Sopenharmony_ci UI_set_result(ui, uis, ""); 59e1051a39Sopenharmony_ci return 1; 60e1051a39Sopenharmony_ci} 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_cistatic int ui_write(UI *ui, UI_STRING *uis) 63e1051a39Sopenharmony_ci{ 64e1051a39Sopenharmony_ci int (*writer)(UI *ui, UI_STRING *uis) = NULL; 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 67e1051a39Sopenharmony_ci && UI_get0_user_data(ui)) { 68e1051a39Sopenharmony_ci switch (UI_get_string_type(uis)) { 69e1051a39Sopenharmony_ci case UIT_PROMPT: 70e1051a39Sopenharmony_ci case UIT_VERIFY: 71e1051a39Sopenharmony_ci { 72e1051a39Sopenharmony_ci const char *password = 73e1051a39Sopenharmony_ci ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci if (password != NULL) 76e1051a39Sopenharmony_ci return 1; 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci break; 79e1051a39Sopenharmony_ci case UIT_NONE: 80e1051a39Sopenharmony_ci case UIT_BOOLEAN: 81e1051a39Sopenharmony_ci case UIT_INFO: 82e1051a39Sopenharmony_ci case UIT_ERROR: 83e1051a39Sopenharmony_ci break; 84e1051a39Sopenharmony_ci } 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci writer = UI_method_get_writer(ui_base_method); 88e1051a39Sopenharmony_ci if (writer != NULL) 89e1051a39Sopenharmony_ci return writer(ui, uis); 90e1051a39Sopenharmony_ci return 1; 91e1051a39Sopenharmony_ci} 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_cistatic int ui_close(UI *ui) 94e1051a39Sopenharmony_ci{ 95e1051a39Sopenharmony_ci int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method); 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci if (closer != NULL) 98e1051a39Sopenharmony_ci return closer(ui); 99e1051a39Sopenharmony_ci return 1; 100e1051a39Sopenharmony_ci} 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci/* object_name defaults to prompt_info from ui user data if present */ 103e1051a39Sopenharmony_cistatic char *ui_prompt_construct(UI *ui, const char *phrase_desc, 104e1051a39Sopenharmony_ci const char *object_name) 105e1051a39Sopenharmony_ci{ 106e1051a39Sopenharmony_ci PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui); 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci if (phrase_desc == NULL) 109e1051a39Sopenharmony_ci phrase_desc = "pass phrase"; 110e1051a39Sopenharmony_ci if (object_name == NULL && cb_data != NULL) 111e1051a39Sopenharmony_ci object_name = cb_data->prompt_info; 112e1051a39Sopenharmony_ci return UI_construct_prompt(NULL, phrase_desc, object_name); 113e1051a39Sopenharmony_ci} 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ciint set_base_ui_method(const UI_METHOD *ui_meth) 116e1051a39Sopenharmony_ci{ 117e1051a39Sopenharmony_ci if (ui_meth == NULL) 118e1051a39Sopenharmony_ci ui_meth = UI_null(); 119e1051a39Sopenharmony_ci ui_base_method = ui_meth; 120e1051a39Sopenharmony_ci return 1; 121e1051a39Sopenharmony_ci} 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ciint setup_ui_method(void) 124e1051a39Sopenharmony_ci{ 125e1051a39Sopenharmony_ci ui_base_method = UI_null(); 126e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_UI_CONSOLE 127e1051a39Sopenharmony_ci ui_base_method = UI_OpenSSL(); 128e1051a39Sopenharmony_ci#endif 129e1051a39Sopenharmony_ci ui_method = UI_create_method("OpenSSL application user interface"); 130e1051a39Sopenharmony_ci return ui_method != NULL 131e1051a39Sopenharmony_ci && 0 == UI_method_set_opener(ui_method, ui_open) 132e1051a39Sopenharmony_ci && 0 == UI_method_set_reader(ui_method, ui_read) 133e1051a39Sopenharmony_ci && 0 == UI_method_set_writer(ui_method, ui_write) 134e1051a39Sopenharmony_ci && 0 == UI_method_set_closer(ui_method, ui_close) 135e1051a39Sopenharmony_ci && 0 == UI_method_set_prompt_constructor(ui_method, 136e1051a39Sopenharmony_ci ui_prompt_construct); 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_civoid destroy_ui_method(void) 140e1051a39Sopenharmony_ci{ 141e1051a39Sopenharmony_ci if (ui_method != NULL) { 142e1051a39Sopenharmony_ci UI_destroy_method(ui_method); 143e1051a39Sopenharmony_ci ui_method = NULL; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci} 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ciconst UI_METHOD *get_ui_method(void) 148e1051a39Sopenharmony_ci{ 149e1051a39Sopenharmony_ci return ui_method; 150e1051a39Sopenharmony_ci} 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_cistatic void *ui_malloc(int sz, const char *what) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci void *vp = OPENSSL_malloc(sz); 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci if (vp == NULL) { 157e1051a39Sopenharmony_ci BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what); 158e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 159e1051a39Sopenharmony_ci exit(1); 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci return vp; 162e1051a39Sopenharmony_ci} 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ciint password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) 165e1051a39Sopenharmony_ci{ 166e1051a39Sopenharmony_ci int res = 0; 167e1051a39Sopenharmony_ci UI *ui; 168e1051a39Sopenharmony_ci int ok = 0; 169e1051a39Sopenharmony_ci char *buff = NULL; 170e1051a39Sopenharmony_ci int ui_flags = 0; 171e1051a39Sopenharmony_ci const char *prompt_info = NULL; 172e1051a39Sopenharmony_ci char *prompt; 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ci if ((ui = UI_new_method(ui_method)) == NULL) 175e1051a39Sopenharmony_ci return 0; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci if (cb_data != NULL && cb_data->prompt_info != NULL) 178e1051a39Sopenharmony_ci prompt_info = cb_data->prompt_info; 179e1051a39Sopenharmony_ci prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); 180e1051a39Sopenharmony_ci if (prompt == NULL) { 181e1051a39Sopenharmony_ci BIO_printf(bio_err, "Out of memory\n"); 182e1051a39Sopenharmony_ci UI_free(ui); 183e1051a39Sopenharmony_ci return 0; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; 187e1051a39Sopenharmony_ci UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci /* We know that there is no previous user data to return to us */ 190e1051a39Sopenharmony_ci (void)UI_add_user_data(ui, cb_data); 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci ok = UI_add_input_string(ui, prompt, ui_flags, buf, 193e1051a39Sopenharmony_ci PW_MIN_LENGTH, bufsiz - 1); 194e1051a39Sopenharmony_ci 195e1051a39Sopenharmony_ci if (ok >= 0 && verify) { 196e1051a39Sopenharmony_ci buff = ui_malloc(bufsiz, "password buffer"); 197e1051a39Sopenharmony_ci ok = UI_add_verify_string(ui, prompt, ui_flags, buff, 198e1051a39Sopenharmony_ci PW_MIN_LENGTH, bufsiz - 1, buf); 199e1051a39Sopenharmony_ci } 200e1051a39Sopenharmony_ci if (ok >= 0) 201e1051a39Sopenharmony_ci do { 202e1051a39Sopenharmony_ci ok = UI_process(ui); 203e1051a39Sopenharmony_ci } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci OPENSSL_clear_free(buff, (unsigned int)bufsiz); 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci if (ok >= 0) 208e1051a39Sopenharmony_ci res = strlen(buf); 209e1051a39Sopenharmony_ci if (ok == -1) { 210e1051a39Sopenharmony_ci BIO_printf(bio_err, "User interface error\n"); 211e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 212e1051a39Sopenharmony_ci OPENSSL_cleanse(buf, (unsigned int)bufsiz); 213e1051a39Sopenharmony_ci res = 0; 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci if (ok == -2) { 216e1051a39Sopenharmony_ci BIO_printf(bio_err, "aborted!\n"); 217e1051a39Sopenharmony_ci OPENSSL_cleanse(buf, (unsigned int)bufsiz); 218e1051a39Sopenharmony_ci res = 0; 219e1051a39Sopenharmony_ci } 220e1051a39Sopenharmony_ci UI_free(ui); 221e1051a39Sopenharmony_ci OPENSSL_free(prompt); 222e1051a39Sopenharmony_ci return res; 223e1051a39Sopenharmony_ci} 224