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