]>
Commit | Line | Data |
---|---|---|
a43ce58f | 1 | /* |
454afd98 | 2 | * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. |
a43ce58f | 3 | * |
a6ed19dc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
a43ce58f SL |
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; | |
a6a5dec6 | 16 | static const UI_METHOD *ui_base_method = NULL; |
a43ce58f | 17 | |
a43ce58f SL |
18 | static int ui_open(UI *ui) |
19 | { | |
a6a5dec6 | 20 | int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method); |
a43ce58f | 21 | |
ca3245a6 | 22 | if (opener != NULL) |
a43ce58f SL |
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; | |
ca3245a6 MC |
39 | |
40 | if (password != NULL) { | |
a43ce58f SL |
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 | ||
a6a5dec6 | 54 | reader = UI_method_get_reader(ui_base_method); |
ca3245a6 | 55 | if (reader != NULL) |
a43ce58f | 56 | return reader(ui, uis); |
ca3245a6 MC |
57 | /* Default to the empty password if we've got nothing better */ |
58 | UI_set_result(ui, uis, ""); | |
a43ce58f SL |
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; | |
591ceedd DDO |
74 | |
75 | if (password != NULL) | |
a43ce58f SL |
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 | ||
a6a5dec6 | 87 | writer = UI_method_get_writer(ui_base_method); |
ca3245a6 | 88 | if (writer != NULL) |
a43ce58f SL |
89 | return writer(ui, uis); |
90 | return 1; | |
91 | } | |
92 | ||
93 | static int ui_close(UI *ui) | |
94 | { | |
a6a5dec6 | 95 | int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method); |
a43ce58f | 96 | |
ca3245a6 | 97 | if (closer != NULL) |
a43ce58f SL |
98 | return closer(ui); |
99 | return 1; | |
100 | } | |
101 | ||
d3dbc9b5 DDO |
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 | ||
a6a5dec6 RL |
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 | ||
a43ce58f SL |
123 | int setup_ui_method(void) |
124 | { | |
a6a5dec6 | 125 | ui_base_method = UI_null(); |
a43ce58f | 126 | #ifndef OPENSSL_NO_UI_CONSOLE |
a6a5dec6 | 127 | ui_base_method = UI_OpenSSL(); |
a43ce58f SL |
128 | #endif |
129 | ui_method = UI_create_method("OpenSSL application user interface"); | |
f84de16f DDO |
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); | |
a43ce58f SL |
137 | } |
138 | ||
139 | void destroy_ui_method(void) | |
140 | { | |
ca3245a6 | 141 | if (ui_method != NULL) { |
a43ce58f SL |
142 | UI_destroy_method(ui_method); |
143 | ui_method = NULL; | |
144 | } | |
145 | } | |
146 | ||
a6a5dec6 | 147 | const UI_METHOD *get_ui_method(void) |
a43ce58f SL |
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 | } |