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