]>
Commit | Line | Data |
---|---|---|
a63d5eaa | 1 | /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ |
0f113f3e MC |
2 | /* |
3 | * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project | |
4 | * 2001. | |
a63d5eaa RL |
5 | */ |
6 | /* ==================================================================== | |
219a3580 | 7 | * Copyright (c) 2001 The OpenSSL Project. All rights reserved. |
a63d5eaa RL |
8 | * |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * | |
13 | * 1. Redistributions of source code must retain the above copyright | |
0f113f3e | 14 | * notice, this list of conditions and the following disclaimer. |
a63d5eaa RL |
15 | * |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in | |
18 | * the documentation and/or other materials provided with the | |
19 | * distribution. | |
20 | * | |
21 | * 3. All advertising materials mentioning features or use of this | |
22 | * software must display the following acknowledgment: | |
23 | * "This product includes software developed by the OpenSSL Project | |
24 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
25 | * | |
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
27 | * endorse or promote products derived from this software without | |
28 | * prior written permission. For written permission, please contact | |
29 | * openssl-core@openssl.org. | |
30 | * | |
31 | * 5. Products derived from this software may not be called "OpenSSL" | |
32 | * nor may "OpenSSL" appear in their names without prior written | |
33 | * permission of the OpenSSL Project. | |
34 | * | |
35 | * 6. Redistributions of any form whatsoever must retain the following | |
36 | * acknowledgment: | |
37 | * "This product includes software developed by the OpenSSL Project | |
38 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
39 | * | |
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
52 | * ==================================================================== | |
53 | * | |
54 | * This product includes cryptographic software written by Eric Young | |
55 | * (eay@cryptsoft.com). This product includes software written by Tim | |
56 | * Hudson (tjh@cryptsoft.com). | |
57 | * | |
58 | */ | |
59 | ||
60 | #include <string.h> | |
b39fc560 | 61 | #include "internal/cryptlib.h" |
eb929eef RL |
62 | #include <openssl/e_os2.h> |
63 | #include <openssl/buffer.h> | |
a63d5eaa RL |
64 | #include <openssl/ui.h> |
65 | #include <openssl/err.h> | |
66 | #include "ui_locl.h" | |
67 | ||
0f113f3e | 68 | static const UI_METHOD *default_UI_meth = NULL; |
a63d5eaa RL |
69 | |
70 | UI *UI_new(void) | |
0f113f3e MC |
71 | { |
72 | return (UI_new_method(NULL)); | |
73 | } | |
a63d5eaa RL |
74 | |
75 | UI *UI_new_method(const UI_METHOD *method) | |
0f113f3e | 76 | { |
64b25758 | 77 | UI *ret = OPENSSL_zalloc(sizeof(*ret)); |
0f113f3e | 78 | |
0f113f3e MC |
79 | if (ret == NULL) { |
80 | UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); | |
81 | return NULL; | |
82 | } | |
83 | if (method == NULL) | |
84 | ret->meth = UI_get_default_method(); | |
85 | else | |
86 | ret->meth = method; | |
87 | ||
0f113f3e MC |
88 | CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); |
89 | return ret; | |
90 | } | |
a63d5eaa | 91 | |
d6f188be | 92 | static void free_string(UI_STRING *uis) |
0f113f3e MC |
93 | { |
94 | if (uis->flags & OUT_STRING_FREEABLE) { | |
95 | OPENSSL_free((char *)uis->out_string); | |
96 | switch (uis->type) { | |
97 | case UIT_BOOLEAN: | |
98 | OPENSSL_free((char *)uis->_.boolean_data.action_desc); | |
99 | OPENSSL_free((char *)uis->_.boolean_data.ok_chars); | |
100 | OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); | |
101 | break; | |
102 | default: | |
103 | break; | |
104 | } | |
105 | } | |
106 | OPENSSL_free(uis); | |
107 | } | |
a63d5eaa RL |
108 | |
109 | void UI_free(UI *ui) | |
0f113f3e MC |
110 | { |
111 | if (ui == NULL) | |
112 | return; | |
113 | sk_UI_STRING_pop_free(ui->strings, free_string); | |
114 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); | |
115 | OPENSSL_free(ui); | |
116 | } | |
a63d5eaa RL |
117 | |
118 | static int allocate_string_stack(UI *ui) | |
0f113f3e MC |
119 | { |
120 | if (ui->strings == NULL) { | |
121 | ui->strings = sk_UI_STRING_new_null(); | |
122 | if (ui->strings == NULL) { | |
123 | return -1; | |
124 | } | |
125 | } | |
126 | return 0; | |
127 | } | |
a63d5eaa | 128 | |
2d2ed9df | 129 | static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, |
0f113f3e MC |
130 | int prompt_freeable, |
131 | enum UI_string_types type, | |
132 | int input_flags, char *result_buf) | |
133 | { | |
134 | UI_STRING *ret = NULL; | |
135 | ||
136 | if (prompt == NULL) { | |
137 | UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER); | |
138 | } else if ((type == UIT_PROMPT || type == UIT_VERIFY | |
139 | || type == UIT_BOOLEAN) && result_buf == NULL) { | |
140 | UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER); | |
90945fa3 | 141 | } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) { |
0f113f3e MC |
142 | ret->out_string = prompt; |
143 | ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0; | |
144 | ret->input_flags = input_flags; | |
145 | ret->type = type; | |
146 | ret->result_buf = result_buf; | |
147 | } | |
148 | return ret; | |
149 | } | |
2d2ed9df | 150 | |
a63d5eaa | 151 | static int general_allocate_string(UI *ui, const char *prompt, |
0f113f3e MC |
152 | int prompt_freeable, |
153 | enum UI_string_types type, int input_flags, | |
154 | char *result_buf, int minsize, int maxsize, | |
155 | const char *test_buf) | |
156 | { | |
157 | int ret = -1; | |
158 | UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, | |
159 | type, input_flags, result_buf); | |
160 | ||
161 | if (s) { | |
162 | if (allocate_string_stack(ui) >= 0) { | |
163 | s->_.string_data.result_minsize = minsize; | |
164 | s->_.string_data.result_maxsize = maxsize; | |
165 | s->_.string_data.test_buf = test_buf; | |
166 | ret = sk_UI_STRING_push(ui->strings, s); | |
167 | /* sk_push() returns 0 on error. Let's addapt that */ | |
168 | if (ret <= 0) | |
169 | ret--; | |
170 | } else | |
171 | free_string(s); | |
172 | } | |
173 | return ret; | |
174 | } | |
2d2ed9df RL |
175 | |
176 | static int general_allocate_boolean(UI *ui, | |
0f113f3e MC |
177 | const char *prompt, |
178 | const char *action_desc, | |
179 | const char *ok_chars, | |
180 | const char *cancel_chars, | |
181 | int prompt_freeable, | |
182 | enum UI_string_types type, | |
183 | int input_flags, char *result_buf) | |
184 | { | |
185 | int ret = -1; | |
186 | UI_STRING *s; | |
187 | const char *p; | |
188 | ||
189 | if (ok_chars == NULL) { | |
190 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); | |
191 | } else if (cancel_chars == NULL) { | |
192 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); | |
193 | } else { | |
194 | for (p = ok_chars; *p; p++) { | |
195 | if (strchr(cancel_chars, *p)) { | |
196 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, | |
197 | UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); | |
198 | } | |
199 | } | |
200 | ||
201 | s = general_allocate_prompt(ui, prompt, prompt_freeable, | |
202 | type, input_flags, result_buf); | |
203 | ||
204 | if (s) { | |
205 | if (allocate_string_stack(ui) >= 0) { | |
206 | s->_.boolean_data.action_desc = action_desc; | |
207 | s->_.boolean_data.ok_chars = ok_chars; | |
208 | s->_.boolean_data.cancel_chars = cancel_chars; | |
209 | ret = sk_UI_STRING_push(ui->strings, s); | |
210 | /* | |
211 | * sk_push() returns 0 on error. Let's addapt that | |
212 | */ | |
213 | if (ret <= 0) | |
214 | ret--; | |
215 | } else | |
216 | free_string(s); | |
217 | } | |
218 | } | |
219 | return ret; | |
220 | } | |
221 | ||
222 | /* | |
223 | * Returns the index to the place in the stack or -1 for error. Uses a | |
224 | * direct reference to the prompt. | |
225 | */ | |
9ad0f681 | 226 | int UI_add_input_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
227 | char *result_buf, int minsize, int maxsize) |
228 | { | |
229 | return general_allocate_string(ui, prompt, 0, | |
230 | UIT_PROMPT, flags, result_buf, minsize, | |
231 | maxsize, NULL); | |
232 | } | |
a63d5eaa RL |
233 | |
234 | /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ | |
9ad0f681 | 235 | int UI_dup_input_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
236 | char *result_buf, int minsize, int maxsize) |
237 | { | |
238 | char *prompt_copy = NULL; | |
239 | ||
240 | if (prompt) { | |
7644a9ae | 241 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
242 | if (prompt_copy == NULL) { |
243 | UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE); | |
244 | return 0; | |
245 | } | |
246 | } | |
247 | ||
248 | return general_allocate_string(ui, prompt_copy, 1, | |
249 | UIT_PROMPT, flags, result_buf, minsize, | |
250 | maxsize, NULL); | |
251 | } | |
a63d5eaa | 252 | |
9ad0f681 | 253 | int UI_add_verify_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
254 | char *result_buf, int minsize, int maxsize, |
255 | const char *test_buf) | |
256 | { | |
257 | return general_allocate_string(ui, prompt, 0, | |
258 | UIT_VERIFY, flags, result_buf, minsize, | |
259 | maxsize, test_buf); | |
260 | } | |
a63d5eaa | 261 | |
9ad0f681 | 262 | int UI_dup_verify_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
263 | char *result_buf, int minsize, int maxsize, |
264 | const char *test_buf) | |
265 | { | |
266 | char *prompt_copy = NULL; | |
267 | ||
268 | if (prompt) { | |
7644a9ae | 269 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
270 | if (prompt_copy == NULL) { |
271 | UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE); | |
272 | return -1; | |
273 | } | |
274 | } | |
275 | ||
276 | return general_allocate_string(ui, prompt_copy, 1, | |
277 | UIT_VERIFY, flags, result_buf, minsize, | |
278 | maxsize, test_buf); | |
279 | } | |
a63d5eaa | 280 | |
2d2ed9df | 281 | int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, |
0f113f3e MC |
282 | const char *ok_chars, const char *cancel_chars, |
283 | int flags, char *result_buf) | |
284 | { | |
285 | return general_allocate_boolean(ui, prompt, action_desc, | |
286 | ok_chars, cancel_chars, 0, UIT_BOOLEAN, | |
287 | flags, result_buf); | |
288 | } | |
2d2ed9df RL |
289 | |
290 | int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, | |
0f113f3e MC |
291 | const char *ok_chars, const char *cancel_chars, |
292 | int flags, char *result_buf) | |
293 | { | |
294 | char *prompt_copy = NULL; | |
295 | char *action_desc_copy = NULL; | |
296 | char *ok_chars_copy = NULL; | |
297 | char *cancel_chars_copy = NULL; | |
298 | ||
299 | if (prompt) { | |
7644a9ae | 300 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
301 | if (prompt_copy == NULL) { |
302 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
303 | goto err; | |
304 | } | |
305 | } | |
306 | ||
307 | if (action_desc) { | |
7644a9ae | 308 | action_desc_copy = OPENSSL_strdup(action_desc); |
0f113f3e MC |
309 | if (action_desc_copy == NULL) { |
310 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
311 | goto err; | |
312 | } | |
313 | } | |
314 | ||
315 | if (ok_chars) { | |
7644a9ae | 316 | ok_chars_copy = OPENSSL_strdup(ok_chars); |
0f113f3e MC |
317 | if (ok_chars_copy == NULL) { |
318 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
319 | goto err; | |
320 | } | |
321 | } | |
322 | ||
323 | if (cancel_chars) { | |
7644a9ae | 324 | cancel_chars_copy = OPENSSL_strdup(cancel_chars); |
0f113f3e MC |
325 | if (cancel_chars_copy == NULL) { |
326 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
327 | goto err; | |
328 | } | |
329 | } | |
330 | ||
331 | return general_allocate_boolean(ui, prompt_copy, action_desc_copy, | |
332 | ok_chars_copy, cancel_chars_copy, 1, | |
333 | UIT_BOOLEAN, flags, result_buf); | |
2d2ed9df | 334 | err: |
b548a1f1 RS |
335 | OPENSSL_free(prompt_copy); |
336 | OPENSSL_free(action_desc_copy); | |
337 | OPENSSL_free(ok_chars_copy); | |
338 | OPENSSL_free(cancel_chars_copy); | |
0f113f3e MC |
339 | return -1; |
340 | } | |
2d2ed9df | 341 | |
a63d5eaa | 342 | int UI_add_info_string(UI *ui, const char *text) |
0f113f3e MC |
343 | { |
344 | return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, | |
345 | NULL); | |
346 | } | |
a63d5eaa RL |
347 | |
348 | int UI_dup_info_string(UI *ui, const char *text) | |
0f113f3e MC |
349 | { |
350 | char *text_copy = NULL; | |
351 | ||
352 | if (text) { | |
7644a9ae | 353 | text_copy = OPENSSL_strdup(text); |
0f113f3e MC |
354 | if (text_copy == NULL) { |
355 | UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE); | |
356 | return -1; | |
357 | } | |
358 | } | |
359 | ||
360 | return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, | |
361 | 0, 0, NULL); | |
362 | } | |
a63d5eaa RL |
363 | |
364 | int UI_add_error_string(UI *ui, const char *text) | |
0f113f3e MC |
365 | { |
366 | return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, | |
367 | NULL); | |
368 | } | |
a63d5eaa RL |
369 | |
370 | int UI_dup_error_string(UI *ui, const char *text) | |
0f113f3e MC |
371 | { |
372 | char *text_copy = NULL; | |
373 | ||
374 | if (text) { | |
7644a9ae | 375 | text_copy = OPENSSL_strdup(text); |
0f113f3e MC |
376 | if (text_copy == NULL) { |
377 | UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE); | |
378 | return -1; | |
379 | } | |
380 | } | |
381 | return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, | |
382 | 0, 0, NULL); | |
383 | } | |
9ad0f681 RL |
384 | |
385 | char *UI_construct_prompt(UI *ui, const char *object_desc, | |
0f113f3e MC |
386 | const char *object_name) |
387 | { | |
388 | char *prompt = NULL; | |
389 | ||
390 | if (ui->meth->ui_construct_prompt) | |
391 | prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name); | |
392 | else { | |
393 | char prompt1[] = "Enter "; | |
394 | char prompt2[] = " for "; | |
395 | char prompt3[] = ":"; | |
396 | int len = 0; | |
397 | ||
398 | if (object_desc == NULL) | |
399 | return NULL; | |
400 | len = sizeof(prompt1) - 1 + strlen(object_desc); | |
401 | if (object_name) | |
402 | len += sizeof(prompt2) - 1 + strlen(object_name); | |
403 | len += sizeof(prompt3) - 1; | |
404 | ||
b196e7d9 | 405 | prompt = OPENSSL_malloc(len + 1); |
0f113f3e MC |
406 | if (prompt == NULL) |
407 | return NULL; | |
7644a9ae RS |
408 | OPENSSL_strlcpy(prompt, prompt1, len + 1); |
409 | OPENSSL_strlcat(prompt, object_desc, len + 1); | |
0f113f3e | 410 | if (object_name) { |
7644a9ae RS |
411 | OPENSSL_strlcat(prompt, prompt2, len + 1); |
412 | OPENSSL_strlcat(prompt, object_name, len + 1); | |
0f113f3e | 413 | } |
7644a9ae | 414 | OPENSSL_strlcat(prompt, prompt3, len + 1); |
0f113f3e MC |
415 | } |
416 | return prompt; | |
417 | } | |
a63d5eaa | 418 | |
1e7e62f8 | 419 | void *UI_add_user_data(UI *ui, void *user_data) |
0f113f3e MC |
420 | { |
421 | void *old_data = ui->user_data; | |
422 | ui->user_data = user_data; | |
423 | return old_data; | |
424 | } | |
1e7e62f8 RL |
425 | |
426 | void *UI_get0_user_data(UI *ui) | |
0f113f3e MC |
427 | { |
428 | return ui->user_data; | |
429 | } | |
1e7e62f8 | 430 | |
a63d5eaa | 431 | const char *UI_get0_result(UI *ui, int i) |
0f113f3e MC |
432 | { |
433 | if (i < 0) { | |
434 | UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL); | |
435 | return NULL; | |
436 | } | |
437 | if (i >= sk_UI_STRING_num(ui->strings)) { | |
438 | UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE); | |
439 | return NULL; | |
440 | } | |
441 | return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); | |
442 | } | |
a63d5eaa | 443 | |
2d2ed9df | 444 | static int print_error(const char *str, size_t len, UI *ui) |
0f113f3e MC |
445 | { |
446 | UI_STRING uis; | |
2d2ed9df | 447 | |
0f113f3e MC |
448 | memset(&uis, 0, sizeof(uis)); |
449 | uis.type = UIT_ERROR; | |
450 | uis.out_string = str; | |
2d2ed9df | 451 | |
0f113f3e MC |
452 | if (ui->meth->ui_write_string && !ui->meth->ui_write_string(ui, &uis)) |
453 | return -1; | |
454 | return 0; | |
455 | } | |
2d2ed9df | 456 | |
a63d5eaa | 457 | int UI_process(UI *ui) |
0f113f3e MC |
458 | { |
459 | int i, ok = 0; | |
2d2ed9df | 460 | |
0f113f3e MC |
461 | if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) |
462 | return -1; | |
463 | ||
464 | if (ui->flags & UI_FLAG_PRINT_ERRORS) | |
465 | ERR_print_errors_cb((int (*)(const char *, size_t, void *)) | |
466 | print_error, (void *)ui); | |
467 | ||
468 | for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { | |
469 | if (ui->meth->ui_write_string | |
470 | && !ui->meth->ui_write_string(ui, | |
471 | sk_UI_STRING_value(ui->strings, i))) | |
472 | { | |
473 | ok = -1; | |
474 | goto err; | |
475 | } | |
476 | } | |
477 | ||
478 | if (ui->meth->ui_flush) | |
479 | switch (ui->meth->ui_flush(ui)) { | |
480 | case -1: /* Interrupt/Cancel/something... */ | |
481 | ok = -2; | |
482 | goto err; | |
483 | case 0: /* Errors */ | |
484 | ok = -1; | |
485 | goto err; | |
486 | default: /* Success */ | |
487 | ok = 0; | |
488 | break; | |
489 | } | |
490 | ||
491 | for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { | |
492 | if (ui->meth->ui_read_string) { | |
493 | switch (ui->meth->ui_read_string(ui, | |
494 | sk_UI_STRING_value(ui->strings, | |
495 | i))) { | |
496 | case -1: /* Interrupt/Cancel/something... */ | |
497 | ok = -2; | |
498 | goto err; | |
499 | case 0: /* Errors */ | |
500 | ok = -1; | |
501 | goto err; | |
502 | default: /* Success */ | |
503 | ok = 0; | |
504 | break; | |
505 | } | |
506 | } | |
507 | } | |
508 | err: | |
509 | if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) | |
510 | return -1; | |
511 | return ok; | |
512 | } | |
513 | ||
514 | int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) | |
515 | { | |
516 | if (ui == NULL) { | |
517 | UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); | |
518 | return -1; | |
519 | } | |
520 | switch (cmd) { | |
521 | case UI_CTRL_PRINT_ERRORS: | |
a63d5eaa | 522 | { |
0f113f3e MC |
523 | int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); |
524 | if (i) | |
525 | ui->flags |= UI_FLAG_PRINT_ERRORS; | |
526 | else | |
527 | ui->flags &= ~UI_FLAG_PRINT_ERRORS; | |
528 | return save_flag; | |
a63d5eaa | 529 | } |
0f113f3e MC |
530 | case UI_CTRL_IS_REDOABLE: |
531 | return ! !(ui->flags & UI_FLAG_REDOABLE); | |
532 | default: | |
533 | break; | |
534 | } | |
535 | UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); | |
536 | return -1; | |
537 | } | |
538 | ||
a63d5eaa | 539 | int UI_set_ex_data(UI *r, int idx, void *arg) |
0f113f3e MC |
540 | { |
541 | return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); | |
542 | } | |
a63d5eaa RL |
543 | |
544 | void *UI_get_ex_data(UI *r, int idx) | |
0f113f3e MC |
545 | { |
546 | return (CRYPTO_get_ex_data(&r->ex_data, idx)); | |
547 | } | |
a63d5eaa RL |
548 | |
549 | void UI_set_default_method(const UI_METHOD *meth) | |
0f113f3e MC |
550 | { |
551 | default_UI_meth = meth; | |
552 | } | |
a63d5eaa RL |
553 | |
554 | const UI_METHOD *UI_get_default_method(void) | |
0f113f3e MC |
555 | { |
556 | if (default_UI_meth == NULL) { | |
557 | default_UI_meth = UI_OpenSSL(); | |
558 | } | |
559 | return default_UI_meth; | |
560 | } | |
a63d5eaa RL |
561 | |
562 | const UI_METHOD *UI_get_method(UI *ui) | |
0f113f3e MC |
563 | { |
564 | return ui->meth; | |
565 | } | |
a63d5eaa RL |
566 | |
567 | const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) | |
0f113f3e MC |
568 | { |
569 | ui->meth = meth; | |
570 | return ui->meth; | |
571 | } | |
a63d5eaa | 572 | |
9ad0f681 | 573 | UI_METHOD *UI_create_method(char *name) |
0f113f3e | 574 | { |
b51bce94 | 575 | UI_METHOD *ui_method = OPENSSL_zalloc(sizeof(*ui_method)); |
0f113f3e | 576 | |
90945fa3 | 577 | if (ui_method != NULL) |
7644a9ae | 578 | ui_method->name = OPENSSL_strdup(name); |
0f113f3e MC |
579 | return ui_method; |
580 | } | |
581 | ||
582 | /* | |
583 | * BIG FSCKING WARNING!!!! If you use this on a statically allocated method | |
584 | * (that is, it hasn't been allocated using UI_create_method(), you deserve | |
585 | * anything Murphy can throw at you and more! You have been warned. | |
586 | */ | |
eb929eef | 587 | void UI_destroy_method(UI_METHOD *ui_method) |
0f113f3e MC |
588 | { |
589 | OPENSSL_free(ui_method->name); | |
590 | ui_method->name = NULL; | |
591 | OPENSSL_free(ui_method); | |
592 | } | |
593 | ||
594 | int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) | |
595 | { | |
596 | if (method) { | |
597 | method->ui_open_session = opener; | |
598 | return 0; | |
599 | } else | |
600 | return -1; | |
601 | } | |
602 | ||
603 | int UI_method_set_writer(UI_METHOD *method, | |
604 | int (*writer) (UI *ui, UI_STRING *uis)) | |
605 | { | |
606 | if (method) { | |
607 | method->ui_write_string = writer; | |
608 | return 0; | |
609 | } else | |
610 | return -1; | |
611 | } | |
612 | ||
613 | int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) | |
614 | { | |
615 | if (method) { | |
616 | method->ui_flush = flusher; | |
617 | return 0; | |
618 | } else | |
619 | return -1; | |
620 | } | |
621 | ||
622 | int UI_method_set_reader(UI_METHOD *method, | |
623 | int (*reader) (UI *ui, UI_STRING *uis)) | |
624 | { | |
625 | if (method) { | |
626 | method->ui_read_string = reader; | |
627 | return 0; | |
628 | } else | |
629 | return -1; | |
630 | } | |
631 | ||
632 | int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) | |
633 | { | |
634 | if (method) { | |
635 | method->ui_close_session = closer; | |
636 | return 0; | |
637 | } else | |
638 | return -1; | |
639 | } | |
640 | ||
641 | int UI_method_set_prompt_constructor(UI_METHOD *method, | |
642 | char *(*prompt_constructor) (UI *ui, | |
643 | const char | |
644 | *object_desc, | |
645 | const char | |
646 | *object_name)) | |
647 | { | |
648 | if (method) { | |
649 | method->ui_construct_prompt = prompt_constructor; | |
650 | return 0; | |
651 | } else | |
652 | return -1; | |
653 | } | |
654 | ||
655 | int (*UI_method_get_opener(UI_METHOD *method)) (UI *) { | |
656 | if (method) | |
657 | return method->ui_open_session; | |
658 | else | |
659 | return NULL; | |
660 | } | |
661 | ||
662 | int (*UI_method_get_writer(UI_METHOD *method)) (UI *, UI_STRING *) { | |
663 | if (method) | |
664 | return method->ui_write_string; | |
665 | else | |
666 | return NULL; | |
667 | } | |
668 | ||
669 | int (*UI_method_get_flusher(UI_METHOD *method)) (UI *) { | |
670 | if (method) | |
671 | return method->ui_flush; | |
672 | else | |
673 | return NULL; | |
674 | } | |
675 | ||
676 | int (*UI_method_get_reader(UI_METHOD *method)) (UI *, UI_STRING *) { | |
677 | if (method) | |
678 | return method->ui_read_string; | |
679 | else | |
680 | return NULL; | |
681 | } | |
682 | ||
683 | int (*UI_method_get_closer(UI_METHOD *method)) (UI *) { | |
684 | if (method) | |
685 | return method->ui_close_session; | |
686 | else | |
687 | return NULL; | |
688 | } | |
689 | ||
690 | char *(*UI_method_get_prompt_constructor(UI_METHOD *method)) (UI *, | |
691 | const char *, | |
692 | const char *) { | |
693 | if (method) | |
694 | return method->ui_construct_prompt; | |
695 | else | |
696 | return NULL; | |
697 | } | |
a63d5eaa RL |
698 | |
699 | enum UI_string_types UI_get_string_type(UI_STRING *uis) | |
0f113f3e MC |
700 | { |
701 | if (!uis) | |
702 | return UIT_NONE; | |
703 | return uis->type; | |
704 | } | |
a63d5eaa | 705 | |
9ad0f681 | 706 | int UI_get_input_flags(UI_STRING *uis) |
0f113f3e MC |
707 | { |
708 | if (!uis) | |
709 | return 0; | |
710 | return uis->input_flags; | |
711 | } | |
9ad0f681 | 712 | |
a63d5eaa | 713 | const char *UI_get0_output_string(UI_STRING *uis) |
0f113f3e MC |
714 | { |
715 | if (!uis) | |
716 | return NULL; | |
717 | return uis->out_string; | |
718 | } | |
a63d5eaa | 719 | |
2d2ed9df | 720 | const char *UI_get0_action_string(UI_STRING *uis) |
0f113f3e MC |
721 | { |
722 | if (!uis) | |
723 | return NULL; | |
724 | switch (uis->type) { | |
725 | case UIT_PROMPT: | |
726 | case UIT_BOOLEAN: | |
727 | return uis->_.boolean_data.action_desc; | |
728 | default: | |
729 | return NULL; | |
730 | } | |
731 | } | |
2d2ed9df | 732 | |
a63d5eaa | 733 | const char *UI_get0_result_string(UI_STRING *uis) |
0f113f3e MC |
734 | { |
735 | if (!uis) | |
736 | return NULL; | |
737 | switch (uis->type) { | |
738 | case UIT_PROMPT: | |
739 | case UIT_VERIFY: | |
740 | return uis->result_buf; | |
741 | default: | |
742 | return NULL; | |
743 | } | |
744 | } | |
a63d5eaa RL |
745 | |
746 | const char *UI_get0_test_string(UI_STRING *uis) | |
0f113f3e MC |
747 | { |
748 | if (!uis) | |
749 | return NULL; | |
750 | switch (uis->type) { | |
751 | case UIT_VERIFY: | |
752 | return uis->_.string_data.test_buf; | |
753 | default: | |
754 | return NULL; | |
755 | } | |
756 | } | |
a63d5eaa RL |
757 | |
758 | int UI_get_result_minsize(UI_STRING *uis) | |
0f113f3e MC |
759 | { |
760 | if (!uis) | |
761 | return -1; | |
762 | switch (uis->type) { | |
763 | case UIT_PROMPT: | |
764 | case UIT_VERIFY: | |
765 | return uis->_.string_data.result_minsize; | |
766 | default: | |
767 | return -1; | |
768 | } | |
769 | } | |
a63d5eaa RL |
770 | |
771 | int UI_get_result_maxsize(UI_STRING *uis) | |
0f113f3e MC |
772 | { |
773 | if (!uis) | |
774 | return -1; | |
775 | switch (uis->type) { | |
776 | case UIT_PROMPT: | |
777 | case UIT_VERIFY: | |
778 | return uis->_.string_data.result_maxsize; | |
779 | default: | |
780 | return -1; | |
781 | } | |
782 | } | |
a63d5eaa | 783 | |
2d2ed9df | 784 | int UI_set_result(UI *ui, UI_STRING *uis, const char *result) |
0f113f3e MC |
785 | { |
786 | int l = strlen(result); | |
787 | ||
788 | ui->flags &= ~UI_FLAG_REDOABLE; | |
789 | ||
790 | if (!uis) | |
791 | return -1; | |
792 | switch (uis->type) { | |
793 | case UIT_PROMPT: | |
794 | case UIT_VERIFY: | |
795 | { | |
796 | char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; | |
797 | char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; | |
798 | ||
799 | BIO_snprintf(number1, sizeof(number1), "%d", | |
800 | uis->_.string_data.result_minsize); | |
801 | BIO_snprintf(number2, sizeof(number2), "%d", | |
802 | uis->_.string_data.result_maxsize); | |
803 | ||
804 | if (l < uis->_.string_data.result_minsize) { | |
805 | ui->flags |= UI_FLAG_REDOABLE; | |
806 | UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL); | |
807 | ERR_add_error_data(5, "You must type in ", | |
808 | number1, " to ", number2, " characters"); | |
809 | return -1; | |
810 | } | |
811 | if (l > uis->_.string_data.result_maxsize) { | |
812 | ui->flags |= UI_FLAG_REDOABLE; | |
813 | UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE); | |
814 | ERR_add_error_data(5, "You must type in ", | |
815 | number1, " to ", number2, " characters"); | |
816 | return -1; | |
817 | } | |
818 | } | |
819 | ||
820 | if (!uis->result_buf) { | |
821 | UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); | |
822 | return -1; | |
823 | } | |
824 | ||
7644a9ae | 825 | OPENSSL_strlcpy(uis->result_buf, result, |
0f113f3e MC |
826 | uis->_.string_data.result_maxsize + 1); |
827 | break; | |
828 | case UIT_BOOLEAN: | |
829 | { | |
830 | const char *p; | |
831 | ||
832 | if (!uis->result_buf) { | |
833 | UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); | |
834 | return -1; | |
835 | } | |
836 | ||
837 | uis->result_buf[0] = '\0'; | |
838 | for (p = result; *p; p++) { | |
839 | if (strchr(uis->_.boolean_data.ok_chars, *p)) { | |
840 | uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; | |
841 | break; | |
842 | } | |
843 | if (strchr(uis->_.boolean_data.cancel_chars, *p)) { | |
844 | uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; | |
845 | break; | |
846 | } | |
847 | } | |
848 | } | |
849 | default: | |
850 | break; | |
851 | } | |
852 | return 0; | |
853 | } |