]>
Commit | Line | Data |
---|---|---|
a43ce58f SL |
1 | /* |
2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (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_fallback_method = NULL; | |
17 | ||
18 | ||
19 | static int ui_open(UI *ui) | |
20 | { | |
21 | int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); | |
22 | ||
23 | if (opener) | |
24 | return opener(ui); | |
25 | return 1; | |
26 | } | |
27 | ||
28 | static int ui_read(UI *ui, UI_STRING *uis) | |
29 | { | |
30 | int (*reader)(UI *ui, UI_STRING *uis) = NULL; | |
31 | ||
32 | if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD | |
33 | && UI_get0_user_data(ui)) { | |
34 | switch (UI_get_string_type(uis)) { | |
35 | case UIT_PROMPT: | |
36 | case UIT_VERIFY: | |
37 | { | |
38 | const char *password = | |
39 | ((PW_CB_DATA *)UI_get0_user_data(ui))->password; | |
40 | if (password && password[0] != '\0') { | |
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_fallback_method); | |
55 | if (reader) | |
56 | return reader(ui, uis); | |
57 | return 1; | |
58 | } | |
59 | ||
60 | static int ui_write(UI *ui, UI_STRING *uis) | |
61 | { | |
62 | int (*writer)(UI *ui, UI_STRING *uis) = NULL; | |
63 | ||
64 | if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD | |
65 | && UI_get0_user_data(ui)) { | |
66 | switch (UI_get_string_type(uis)) { | |
67 | case UIT_PROMPT: | |
68 | case UIT_VERIFY: | |
69 | { | |
70 | const char *password = | |
71 | ((PW_CB_DATA *)UI_get0_user_data(ui))->password; | |
72 | if (password && password[0] != '\0') | |
73 | return 1; | |
74 | } | |
75 | break; | |
76 | case UIT_NONE: | |
77 | case UIT_BOOLEAN: | |
78 | case UIT_INFO: | |
79 | case UIT_ERROR: | |
80 | break; | |
81 | } | |
82 | } | |
83 | ||
84 | writer = UI_method_get_writer(ui_fallback_method); | |
85 | if (writer) | |
86 | return writer(ui, uis); | |
87 | return 1; | |
88 | } | |
89 | ||
90 | static int ui_close(UI *ui) | |
91 | { | |
92 | int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); | |
93 | ||
94 | if (closer) | |
95 | return closer(ui); | |
96 | return 1; | |
97 | } | |
98 | ||
99 | int setup_ui_method(void) | |
100 | { | |
101 | ui_fallback_method = UI_null(); | |
102 | #ifndef OPENSSL_NO_UI_CONSOLE | |
103 | ui_fallback_method = UI_OpenSSL(); | |
104 | #endif | |
105 | ui_method = UI_create_method("OpenSSL application user interface"); | |
106 | UI_method_set_opener(ui_method, ui_open); | |
107 | UI_method_set_reader(ui_method, ui_read); | |
108 | UI_method_set_writer(ui_method, ui_write); | |
109 | UI_method_set_closer(ui_method, ui_close); | |
110 | return 0; | |
111 | } | |
112 | ||
113 | void destroy_ui_method(void) | |
114 | { | |
115 | if (ui_method) { | |
116 | UI_destroy_method(ui_method); | |
117 | ui_method = NULL; | |
118 | } | |
119 | } | |
120 | ||
121 | const UI_METHOD *get_ui_method(void) | |
122 | { | |
123 | return ui_method; | |
124 | } | |
125 | ||
126 | static void *ui_malloc(int sz, const char *what) | |
127 | { | |
128 | void *vp = OPENSSL_malloc(sz); | |
129 | ||
130 | if (vp == NULL) { | |
131 | BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what); | |
132 | ERR_print_errors(bio_err); | |
133 | exit(1); | |
134 | } | |
135 | return vp; | |
136 | } | |
137 | ||
138 | int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) | |
139 | { | |
140 | int res = 0; | |
141 | UI *ui; | |
142 | int ok = 0; | |
143 | char *buff = NULL; | |
144 | int ui_flags = 0; | |
145 | const char *prompt_info = NULL; | |
146 | char *prompt; | |
147 | ||
148 | if ((ui = UI_new_method(ui_method)) == NULL) | |
149 | return 0; | |
150 | ||
151 | if (cb_data != NULL && cb_data->prompt_info != NULL) | |
152 | prompt_info = cb_data->prompt_info; | |
153 | prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); | |
154 | if (prompt == NULL) { | |
155 | BIO_printf(bio_err, "Out of memory\n"); | |
156 | UI_free(ui); | |
157 | return 0; | |
158 | } | |
159 | ||
160 | ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; | |
161 | UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); | |
162 | ||
163 | /* We know that there is no previous user data to return to us */ | |
164 | (void)UI_add_user_data(ui, cb_data); | |
165 | ||
166 | ok = UI_add_input_string(ui, prompt, ui_flags, buf, | |
167 | PW_MIN_LENGTH, bufsiz - 1); | |
168 | ||
169 | if (ok >= 0 && verify) { | |
170 | buff = ui_malloc(bufsiz, "password buffer"); | |
171 | ok = UI_add_verify_string(ui, prompt, ui_flags, buff, | |
172 | PW_MIN_LENGTH, bufsiz - 1, buf); | |
173 | } | |
174 | if (ok >= 0) | |
175 | do { | |
176 | ok = UI_process(ui); | |
177 | } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); | |
178 | ||
179 | OPENSSL_clear_free(buff, (unsigned int)bufsiz); | |
180 | ||
181 | if (ok >= 0) | |
182 | res = strlen(buf); | |
183 | if (ok == -1) { | |
184 | BIO_printf(bio_err, "User interface error\n"); | |
185 | ERR_print_errors(bio_err); | |
186 | OPENSSL_cleanse(buf, (unsigned int)bufsiz); | |
187 | res = 0; | |
188 | } | |
189 | if (ok == -2) { | |
190 | BIO_printf(bio_err, "aborted!\n"); | |
191 | OPENSSL_cleanse(buf, (unsigned int)bufsiz); | |
192 | res = 0; | |
193 | } | |
194 | UI_free(ui); | |
195 | OPENSSL_free(prompt); | |
196 | return res; | |
197 | } |