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