]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ui/ui_lib.c
apps_ui.c: Correct password prompt for ui_method
[thirdparty/openssl.git] / crypto / ui / ui_lib.c
CommitLineData
0f113f3e 1/*
33388b44 2 * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
a63d5eaa 3 *
55e0593c 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
aa6bb135
RS
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
a63d5eaa
RL
8 */
9
10#include <string.h>
b39fc560 11#include "internal/cryptlib.h"
eb929eef
RL
12#include <openssl/e_os2.h>
13#include <openssl/buffer.h>
a63d5eaa
RL
14#include <openssl/ui.h>
15#include <openssl/err.h>
706457b7 16#include "ui_local.h"
a63d5eaa 17
852c2ed2
RS
18DEFINE_STACK_OF(UI_STRING)
19
a63d5eaa 20UI *UI_new(void)
0f113f3e 21{
26a7d938 22 return UI_new_method(NULL);
0f113f3e 23}
a63d5eaa
RL
24
25UI *UI_new_method(const UI_METHOD *method)
0f113f3e 26{
64b25758 27 UI *ret = OPENSSL_zalloc(sizeof(*ret));
0f113f3e 28
0f113f3e
MC
29 if (ret == NULL) {
30 UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
31 return NULL;
32 }
41cfbccc
AG
33
34 ret->lock = CRYPTO_THREAD_lock_new();
35 if (ret->lock == NULL) {
36 UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
37 OPENSSL_free(ret);
38 return NULL;
39 }
40
0f113f3e 41 if (method == NULL)
48feaceb
RL
42 method = UI_get_default_method();
43 if (method == NULL)
44 method = UI_null();
45 ret->meth = method;
0f113f3e 46
25a807bc
F
47 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) {
48 OPENSSL_free(ret);
49 return NULL;
50 }
0f113f3e
MC
51 return ret;
52}
a63d5eaa 53
d6f188be 54static void free_string(UI_STRING *uis)
0f113f3e
MC
55{
56 if (uis->flags & OUT_STRING_FREEABLE) {
57 OPENSSL_free((char *)uis->out_string);
58 switch (uis->type) {
59 case UIT_BOOLEAN:
60 OPENSSL_free((char *)uis->_.boolean_data.action_desc);
61 OPENSSL_free((char *)uis->_.boolean_data.ok_chars);
62 OPENSSL_free((char *)uis->_.boolean_data.cancel_chars);
63 break;
f3b3d7f0
RS
64 case UIT_NONE:
65 case UIT_PROMPT:
66 case UIT_VERIFY:
67 case UIT_ERROR:
68 case UIT_INFO:
0f113f3e
MC
69 break;
70 }
71 }
72 OPENSSL_free(uis);
73}
a63d5eaa
RL
74
75void UI_free(UI *ui)
0f113f3e
MC
76{
77 if (ui == NULL)
78 return;
545360c4
RL
79 if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
80 ui->meth->ui_destroy_data(ui, ui->user_data);
81 }
0f113f3e
MC
82 sk_UI_STRING_pop_free(ui->strings, free_string);
83 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
41cfbccc 84 CRYPTO_THREAD_lock_free(ui->lock);
0f113f3e
MC
85 OPENSSL_free(ui);
86}
a63d5eaa
RL
87
88static int allocate_string_stack(UI *ui)
0f113f3e
MC
89{
90 if (ui->strings == NULL) {
91 ui->strings = sk_UI_STRING_new_null();
92 if (ui->strings == NULL) {
93 return -1;
94 }
95 }
96 return 0;
97}
a63d5eaa 98
2d2ed9df 99static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
0f113f3e
MC
100 int prompt_freeable,
101 enum UI_string_types type,
102 int input_flags, char *result_buf)
103{
104 UI_STRING *ret = NULL;
105
106 if (prompt == NULL) {
107 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER);
108 } else if ((type == UIT_PROMPT || type == UIT_VERIFY
109 || type == UIT_BOOLEAN) && result_buf == NULL) {
110 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER);
90945fa3 111 } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) {
0f113f3e
MC
112 ret->out_string = prompt;
113 ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0;
114 ret->input_flags = input_flags;
115 ret->type = type;
116 ret->result_buf = result_buf;
117 }
118 return ret;
119}
2d2ed9df 120
a63d5eaa 121static int general_allocate_string(UI *ui, const char *prompt,
0f113f3e
MC
122 int prompt_freeable,
123 enum UI_string_types type, int input_flags,
124 char *result_buf, int minsize, int maxsize,
125 const char *test_buf)
126{
127 int ret = -1;
128 UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable,
129 type, input_flags, result_buf);
130
120fb9e4 131 if (s != NULL) {
0f113f3e
MC
132 if (allocate_string_stack(ui) >= 0) {
133 s->_.string_data.result_minsize = minsize;
134 s->_.string_data.result_maxsize = maxsize;
135 s->_.string_data.test_buf = test_buf;
136 ret = sk_UI_STRING_push(ui->strings, s);
0d4fb843 137 /* sk_push() returns 0 on error. Let's adapt that */
68efafc5 138 if (ret <= 0) {
0f113f3e 139 ret--;
68efafc5
F
140 free_string(s);
141 }
0f113f3e
MC
142 } else
143 free_string(s);
144 }
145 return ret;
146}
2d2ed9df
RL
147
148static int general_allocate_boolean(UI *ui,
0f113f3e
MC
149 const char *prompt,
150 const char *action_desc,
151 const char *ok_chars,
152 const char *cancel_chars,
153 int prompt_freeable,
154 enum UI_string_types type,
155 int input_flags, char *result_buf)
156{
157 int ret = -1;
158 UI_STRING *s;
159 const char *p;
160
161 if (ok_chars == NULL) {
162 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER);
163 } else if (cancel_chars == NULL) {
164 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER);
165 } else {
120fb9e4
RL
166 for (p = ok_chars; *p != '\0'; p++) {
167 if (strchr(cancel_chars, *p) != NULL) {
0f113f3e
MC
168 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,
169 UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
170 }
171 }
172
173 s = general_allocate_prompt(ui, prompt, prompt_freeable,
174 type, input_flags, result_buf);
175
120fb9e4 176 if (s != NULL) {
0f113f3e
MC
177 if (allocate_string_stack(ui) >= 0) {
178 s->_.boolean_data.action_desc = action_desc;
179 s->_.boolean_data.ok_chars = ok_chars;
180 s->_.boolean_data.cancel_chars = cancel_chars;
181 ret = sk_UI_STRING_push(ui->strings, s);
182 /*
0d4fb843 183 * sk_push() returns 0 on error. Let's adapt that
0f113f3e 184 */
68efafc5 185 if (ret <= 0) {
0f113f3e 186 ret--;
68efafc5
F
187 free_string(s);
188 }
0f113f3e
MC
189 } else
190 free_string(s);
191 }
192 }
193 return ret;
194}
195
196/*
197 * Returns the index to the place in the stack or -1 for error. Uses a
198 * direct reference to the prompt.
199 */
9ad0f681 200int UI_add_input_string(UI *ui, const char *prompt, int flags,
0f113f3e
MC
201 char *result_buf, int minsize, int maxsize)
202{
203 return general_allocate_string(ui, prompt, 0,
204 UIT_PROMPT, flags, result_buf, minsize,
205 maxsize, NULL);
206}
a63d5eaa
RL
207
208/* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
9ad0f681 209int UI_dup_input_string(UI *ui, const char *prompt, int flags,
0f113f3e
MC
210 char *result_buf, int minsize, int maxsize)
211{
212 char *prompt_copy = NULL;
213
120fb9e4 214 if (prompt != NULL) {
7644a9ae 215 prompt_copy = OPENSSL_strdup(prompt);
0f113f3e
MC
216 if (prompt_copy == NULL) {
217 UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE);
218 return 0;
219 }
220 }
221
222 return general_allocate_string(ui, prompt_copy, 1,
223 UIT_PROMPT, flags, result_buf, minsize,
224 maxsize, NULL);
225}
a63d5eaa 226
9ad0f681 227int UI_add_verify_string(UI *ui, const char *prompt, int flags,
0f113f3e
MC
228 char *result_buf, int minsize, int maxsize,
229 const char *test_buf)
230{
231 return general_allocate_string(ui, prompt, 0,
232 UIT_VERIFY, flags, result_buf, minsize,
233 maxsize, test_buf);
234}
a63d5eaa 235
9ad0f681 236int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
0f113f3e
MC
237 char *result_buf, int minsize, int maxsize,
238 const char *test_buf)
239{
240 char *prompt_copy = NULL;
241
120fb9e4 242 if (prompt != NULL) {
7644a9ae 243 prompt_copy = OPENSSL_strdup(prompt);
0f113f3e
MC
244 if (prompt_copy == NULL) {
245 UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE);
246 return -1;
247 }
248 }
249
250 return general_allocate_string(ui, prompt_copy, 1,
251 UIT_VERIFY, flags, result_buf, minsize,
252 maxsize, test_buf);
253}
a63d5eaa 254
2d2ed9df 255int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
0f113f3e
MC
256 const char *ok_chars, const char *cancel_chars,
257 int flags, char *result_buf)
258{
259 return general_allocate_boolean(ui, prompt, action_desc,
260 ok_chars, cancel_chars, 0, UIT_BOOLEAN,
261 flags, result_buf);
262}
2d2ed9df
RL
263
264int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
0f113f3e
MC
265 const char *ok_chars, const char *cancel_chars,
266 int flags, char *result_buf)
267{
268 char *prompt_copy = NULL;
269 char *action_desc_copy = NULL;
270 char *ok_chars_copy = NULL;
271 char *cancel_chars_copy = NULL;
272
120fb9e4 273 if (prompt != NULL) {
7644a9ae 274 prompt_copy = OPENSSL_strdup(prompt);
0f113f3e
MC
275 if (prompt_copy == NULL) {
276 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
277 goto err;
278 }
279 }
280
120fb9e4 281 if (action_desc != NULL) {
7644a9ae 282 action_desc_copy = OPENSSL_strdup(action_desc);
0f113f3e
MC
283 if (action_desc_copy == NULL) {
284 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
285 goto err;
286 }
287 }
288
120fb9e4 289 if (ok_chars != NULL) {
7644a9ae 290 ok_chars_copy = OPENSSL_strdup(ok_chars);
0f113f3e
MC
291 if (ok_chars_copy == NULL) {
292 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
295 }
296
120fb9e4 297 if (cancel_chars != NULL) {
7644a9ae 298 cancel_chars_copy = OPENSSL_strdup(cancel_chars);
0f113f3e
MC
299 if (cancel_chars_copy == NULL) {
300 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
301 goto err;
302 }
303 }
304
305 return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
306 ok_chars_copy, cancel_chars_copy, 1,
307 UIT_BOOLEAN, flags, result_buf);
2d2ed9df 308 err:
b548a1f1
RS
309 OPENSSL_free(prompt_copy);
310 OPENSSL_free(action_desc_copy);
311 OPENSSL_free(ok_chars_copy);
312 OPENSSL_free(cancel_chars_copy);
0f113f3e
MC
313 return -1;
314}
2d2ed9df 315
a63d5eaa 316int UI_add_info_string(UI *ui, const char *text)
0f113f3e
MC
317{
318 return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
319 NULL);
320}
a63d5eaa
RL
321
322int UI_dup_info_string(UI *ui, const char *text)
0f113f3e
MC
323{
324 char *text_copy = NULL;
325
120fb9e4 326 if (text != NULL) {
7644a9ae 327 text_copy = OPENSSL_strdup(text);
0f113f3e
MC
328 if (text_copy == NULL) {
329 UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE);
330 return -1;
331 }
332 }
333
334 return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
335 0, 0, NULL);
336}
a63d5eaa
RL
337
338int UI_add_error_string(UI *ui, const char *text)
0f113f3e
MC
339{
340 return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
341 NULL);
342}
a63d5eaa
RL
343
344int UI_dup_error_string(UI *ui, const char *text)
0f113f3e
MC
345{
346 char *text_copy = NULL;
347
120fb9e4 348 if (text != NULL) {
7644a9ae 349 text_copy = OPENSSL_strdup(text);
0f113f3e
MC
350 if (text_copy == NULL) {
351 UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE);
352 return -1;
353 }
354 }
355 return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
356 0, 0, NULL);
357}
9ad0f681 358
d3dbc9b5 359char *UI_construct_prompt(UI *ui, const char *phrase_desc,
0f113f3e
MC
360 const char *object_name)
361{
362 char *prompt = NULL;
363
d3dbc9b5
DDO
364 if (ui != NULL && ui->meth != NULL && ui->meth->ui_construct_prompt != NULL)
365 prompt = ui->meth->ui_construct_prompt(ui, phrase_desc, object_name);
0f113f3e
MC
366 else {
367 char prompt1[] = "Enter ";
368 char prompt2[] = " for ";
369 char prompt3[] = ":";
370 int len = 0;
371
d3dbc9b5 372 if (phrase_desc == NULL)
0f113f3e 373 return NULL;
d3dbc9b5 374 len = sizeof(prompt1) - 1 + strlen(phrase_desc);
120fb9e4 375 if (object_name != NULL)
0f113f3e
MC
376 len += sizeof(prompt2) - 1 + strlen(object_name);
377 len += sizeof(prompt3) - 1;
378
cdb10bae
RS
379 if ((prompt = OPENSSL_malloc(len + 1)) == NULL) {
380 UIerr(UI_F_UI_CONSTRUCT_PROMPT, ERR_R_MALLOC_FAILURE);
0f113f3e 381 return NULL;
cdb10bae 382 }
7644a9ae 383 OPENSSL_strlcpy(prompt, prompt1, len + 1);
d3dbc9b5 384 OPENSSL_strlcat(prompt, phrase_desc, len + 1);
120fb9e4 385 if (object_name != NULL) {
7644a9ae
RS
386 OPENSSL_strlcat(prompt, prompt2, len + 1);
387 OPENSSL_strlcat(prompt, object_name, len + 1);
0f113f3e 388 }
7644a9ae 389 OPENSSL_strlcat(prompt, prompt3, len + 1);
0f113f3e
MC
390 }
391 return prompt;
392}
a63d5eaa 393
1e7e62f8 394void *UI_add_user_data(UI *ui, void *user_data)
0f113f3e
MC
395{
396 void *old_data = ui->user_data;
545360c4
RL
397
398 if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
399 ui->meth->ui_destroy_data(ui, old_data);
400 old_data = NULL;
401 }
0f113f3e 402 ui->user_data = user_data;
545360c4 403 ui->flags &= ~UI_FLAG_DUPL_DATA;
0f113f3e
MC
404 return old_data;
405}
1e7e62f8 406
545360c4
RL
407int UI_dup_user_data(UI *ui, void *user_data)
408{
409 void *duplicate = NULL;
410
411 if (ui->meth->ui_duplicate_data == NULL
412 || ui->meth->ui_destroy_data == NULL) {
413 UIerr(UI_F_UI_DUP_USER_DATA, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED);
414 return -1;
415 }
416
417 duplicate = ui->meth->ui_duplicate_data(ui, user_data);
418 if (duplicate == NULL) {
419 UIerr(UI_F_UI_DUP_USER_DATA, ERR_R_MALLOC_FAILURE);
420 return -1;
421 }
422
423 (void)UI_add_user_data(ui, duplicate);
424 ui->flags |= UI_FLAG_DUPL_DATA;
425
426 return 0;
427}
428
1e7e62f8 429void *UI_get0_user_data(UI *ui)
0f113f3e
MC
430{
431 return ui->user_data;
432}
1e7e62f8 433
a63d5eaa 434const char *UI_get0_result(UI *ui, int i)
0f113f3e
MC
435{
436 if (i < 0) {
437 UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL);
438 return NULL;
439 }
440 if (i >= sk_UI_STRING_num(ui->strings)) {
441 UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE);
442 return NULL;
443 }
444 return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
445}
a63d5eaa 446
4e049e2c
RL
447int UI_get_result_length(UI *ui, int i)
448{
449 if (i < 0) {
450 UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_SMALL);
451 return -1;
452 }
453 if (i >= sk_UI_STRING_num(ui->strings)) {
454 UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_LARGE);
455 return -1;
456 }
457 return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i));
458}
459
2d2ed9df 460static int print_error(const char *str, size_t len, UI *ui)
0f113f3e
MC
461{
462 UI_STRING uis;
2d2ed9df 463
0f113f3e
MC
464 memset(&uis, 0, sizeof(uis));
465 uis.type = UIT_ERROR;
466 uis.out_string = str;
2d2ed9df 467
120fb9e4
RL
468 if (ui->meth->ui_write_string != NULL
469 && ui->meth->ui_write_string(ui, &uis) <= 0)
0f113f3e
MC
470 return -1;
471 return 0;
472}
2d2ed9df 473
a63d5eaa 474int UI_process(UI *ui)
0f113f3e
MC
475{
476 int i, ok = 0;
0a687ab0 477 const char *state = "processing";
2d2ed9df 478
120fb9e4
RL
479 if (ui->meth->ui_open_session != NULL
480 && ui->meth->ui_open_session(ui) <= 0) {
0a687ab0
RL
481 state = "opening session";
482 ok = -1;
483 goto err;
484 }
0f113f3e
MC
485
486 if (ui->flags & UI_FLAG_PRINT_ERRORS)
487 ERR_print_errors_cb((int (*)(const char *, size_t, void *))
488 print_error, (void *)ui);
489
490 for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
120fb9e4
RL
491 if (ui->meth->ui_write_string != NULL
492 && (ui->meth->ui_write_string(ui,
493 sk_UI_STRING_value(ui->strings, i))
494 <= 0))
0f113f3e 495 {
0a687ab0 496 state = "writing strings";
0f113f3e
MC
497 ok = -1;
498 goto err;
499 }
500 }
501
120fb9e4 502 if (ui->meth->ui_flush != NULL)
0f113f3e
MC
503 switch (ui->meth->ui_flush(ui)) {
504 case -1: /* Interrupt/Cancel/something... */
f8922b51 505 ui->flags &= ~UI_FLAG_REDOABLE;
0f113f3e
MC
506 ok = -2;
507 goto err;
508 case 0: /* Errors */
0a687ab0 509 state = "flushing";
0f113f3e
MC
510 ok = -1;
511 goto err;
512 default: /* Success */
513 ok = 0;
514 break;
515 }
516
517 for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
120fb9e4 518 if (ui->meth->ui_read_string != NULL) {
0f113f3e
MC
519 switch (ui->meth->ui_read_string(ui,
520 sk_UI_STRING_value(ui->strings,
521 i))) {
522 case -1: /* Interrupt/Cancel/something... */
f8922b51 523 ui->flags &= ~UI_FLAG_REDOABLE;
0f113f3e
MC
524 ok = -2;
525 goto err;
526 case 0: /* Errors */
0a687ab0 527 state = "reading strings";
0f113f3e
MC
528 ok = -1;
529 goto err;
530 default: /* Success */
531 ok = 0;
532 break;
533 }
534 }
535 }
b96dba9e
RL
536
537 state = NULL;
0f113f3e 538 err:
120fb9e4 539 if (ui->meth->ui_close_session != NULL
949320c5 540 && ui->meth->ui_close_session(ui) <= 0) {
0a687ab0
RL
541 if (state == NULL)
542 state = "closing session";
543 ok = -1;
544 }
545
546 if (ok == -1) {
547 UIerr(UI_F_UI_PROCESS, UI_R_PROCESSING_ERROR);
548 ERR_add_error_data(2, "while ", state);
549 }
0f113f3e
MC
550 return ok;
551}
552
553int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void))
554{
555 if (ui == NULL) {
556 UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER);
557 return -1;
558 }
559 switch (cmd) {
560 case UI_CTRL_PRINT_ERRORS:
a63d5eaa 561 {
0f113f3e
MC
562 int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS);
563 if (i)
564 ui->flags |= UI_FLAG_PRINT_ERRORS;
565 else
566 ui->flags &= ~UI_FLAG_PRINT_ERRORS;
567 return save_flag;
a63d5eaa 568 }
0f113f3e
MC
569 case UI_CTRL_IS_REDOABLE:
570 return ! !(ui->flags & UI_FLAG_REDOABLE);
571 default:
572 break;
573 }
574 UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND);
575 return -1;
576}
577
a63d5eaa 578int UI_set_ex_data(UI *r, int idx, void *arg)
0f113f3e 579{
26a7d938 580 return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
0f113f3e 581}
a63d5eaa 582
8cc86b81 583void *UI_get_ex_data(const UI *r, int idx)
0f113f3e 584{
26a7d938 585 return CRYPTO_get_ex_data(&r->ex_data, idx);
0f113f3e 586}
a63d5eaa 587
a63d5eaa 588const UI_METHOD *UI_get_method(UI *ui)
0f113f3e
MC
589{
590 return ui->meth;
591}
a63d5eaa
RL
592
593const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
0f113f3e
MC
594{
595 ui->meth = meth;
596 return ui->meth;
597}
a63d5eaa 598
472f727c 599UI_METHOD *UI_create_method(const char *name)
0f113f3e 600{
18cfc668
RL
601 UI_METHOD *ui_method = NULL;
602
603 if ((ui_method = OPENSSL_zalloc(sizeof(*ui_method))) == NULL
604 || (ui_method->name = OPENSSL_strdup(name)) == NULL
605 || !CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method,
606 &ui_method->ex_data)) {
607 if (ui_method)
608 OPENSSL_free(ui_method->name);
609 OPENSSL_free(ui_method);
610 UIerr(UI_F_UI_CREATE_METHOD, ERR_R_MALLOC_FAILURE);
611 return NULL;
6ef020c9 612 }
0f113f3e
MC
613 return ui_method;
614}
615
616/*
617 * BIG FSCKING WARNING!!!! If you use this on a statically allocated method
618 * (that is, it hasn't been allocated using UI_create_method(), you deserve
619 * anything Murphy can throw at you and more! You have been warned.
620 */
eb929eef 621void UI_destroy_method(UI_METHOD *ui_method)
0f113f3e 622{
18cfc668
RL
623 if (ui_method == NULL)
624 return;
625 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method,
626 &ui_method->ex_data);
0f113f3e
MC
627 OPENSSL_free(ui_method->name);
628 ui_method->name = NULL;
629 OPENSSL_free(ui_method);
630}
631
632int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui))
633{
120fb9e4 634 if (method != NULL) {
0f113f3e
MC
635 method->ui_open_session = opener;
636 return 0;
120fb9e4
RL
637 }
638 return -1;
0f113f3e
MC
639}
640
641int UI_method_set_writer(UI_METHOD *method,
642 int (*writer) (UI *ui, UI_STRING *uis))
643{
120fb9e4 644 if (method != NULL) {
0f113f3e
MC
645 method->ui_write_string = writer;
646 return 0;
120fb9e4
RL
647 }
648 return -1;
0f113f3e
MC
649}
650
651int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui))
652{
120fb9e4 653 if (method != NULL) {
0f113f3e
MC
654 method->ui_flush = flusher;
655 return 0;
120fb9e4
RL
656 }
657 return -1;
0f113f3e
MC
658}
659
660int UI_method_set_reader(UI_METHOD *method,
661 int (*reader) (UI *ui, UI_STRING *uis))
662{
120fb9e4 663 if (method != NULL) {
0f113f3e
MC
664 method->ui_read_string = reader;
665 return 0;
120fb9e4
RL
666 }
667 return -1;
0f113f3e
MC
668}
669
670int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui))
671{
120fb9e4 672 if (method != NULL) {
0f113f3e
MC
673 method->ui_close_session = closer;
674 return 0;
120fb9e4
RL
675 }
676 return -1;
0f113f3e
MC
677}
678
545360c4
RL
679int UI_method_set_data_duplicator(UI_METHOD *method,
680 void *(*duplicator) (UI *ui, void *ui_data),
681 void (*destructor)(UI *ui, void *ui_data))
682{
683 if (method != NULL) {
684 method->ui_duplicate_data = duplicator;
685 method->ui_destroy_data = destructor;
686 return 0;
687 }
688 return -1;
689}
690
0f113f3e
MC
691int UI_method_set_prompt_constructor(UI_METHOD *method,
692 char *(*prompt_constructor) (UI *ui,
d3dbc9b5
DDO
693 const char *,
694 const char *))
0f113f3e 695{
120fb9e4 696 if (method != NULL) {
0f113f3e
MC
697 method->ui_construct_prompt = prompt_constructor;
698 return 0;
120fb9e4
RL
699 }
700 return -1;
0f113f3e
MC
701}
702
18cfc668
RL
703int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data)
704{
705 return CRYPTO_set_ex_data(&method->ex_data, idx, data);
706}
707
a223ffe6 708int (*UI_method_get_opener(const UI_METHOD *method)) (UI *)
120fb9e4
RL
709{
710 if (method != NULL)
0f113f3e 711 return method->ui_open_session;
120fb9e4 712 return NULL;
0f113f3e
MC
713}
714
a223ffe6 715int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *)
120fb9e4
RL
716{
717 if (method != NULL)
0f113f3e 718 return method->ui_write_string;
120fb9e4 719 return NULL;
0f113f3e
MC
720}
721
a223ffe6 722int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *)
120fb9e4
RL
723{
724 if (method != NULL)
0f113f3e 725 return method->ui_flush;
120fb9e4 726 return NULL;
0f113f3e
MC
727}
728
a223ffe6 729int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *)
120fb9e4
RL
730{
731 if (method != NULL)
0f113f3e 732 return method->ui_read_string;
120fb9e4 733 return NULL;
0f113f3e
MC
734}
735
a223ffe6 736int (*UI_method_get_closer(const UI_METHOD *method)) (UI *)
120fb9e4
RL
737{
738 if (method != NULL)
0f113f3e 739 return method->ui_close_session;
120fb9e4 740 return NULL;
0f113f3e
MC
741}
742
a223ffe6
RL
743char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
744 (UI *, const char *, const char *)
120fb9e4
RL
745{
746 if (method != NULL)
0f113f3e 747 return method->ui_construct_prompt;
120fb9e4 748 return NULL;
0f113f3e 749}
a63d5eaa 750
545360c4
RL
751void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *)
752{
753 if (method != NULL)
754 return method->ui_duplicate_data;
755 return NULL;
756}
757
758void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *)
759{
760 if (method != NULL)
761 return method->ui_destroy_data;
762 return NULL;
763}
764
18cfc668
RL
765const void *UI_method_get_ex_data(const UI_METHOD *method, int idx)
766{
767 return CRYPTO_get_ex_data(&method->ex_data, idx);
768}
769
a63d5eaa 770enum UI_string_types UI_get_string_type(UI_STRING *uis)
0f113f3e 771{
0f113f3e
MC
772 return uis->type;
773}
a63d5eaa 774
9ad0f681 775int UI_get_input_flags(UI_STRING *uis)
0f113f3e 776{
0f113f3e
MC
777 return uis->input_flags;
778}
9ad0f681 779
a63d5eaa 780const char *UI_get0_output_string(UI_STRING *uis)
0f113f3e 781{
0f113f3e
MC
782 return uis->out_string;
783}
a63d5eaa 784
2d2ed9df 785const char *UI_get0_action_string(UI_STRING *uis)
0f113f3e 786{
0f113f3e 787 switch (uis->type) {
0f113f3e
MC
788 case UIT_BOOLEAN:
789 return uis->_.boolean_data.action_desc;
6e470e19 790 case UIT_PROMPT:
f3b3d7f0
RS
791 case UIT_NONE:
792 case UIT_VERIFY:
793 case UIT_INFO:
794 case UIT_ERROR:
795 break;
0f113f3e 796 }
f3b3d7f0 797 return NULL;
0f113f3e 798}
2d2ed9df 799
a63d5eaa 800const char *UI_get0_result_string(UI_STRING *uis)
0f113f3e 801{
0f113f3e
MC
802 switch (uis->type) {
803 case UIT_PROMPT:
804 case UIT_VERIFY:
805 return uis->result_buf;
f3b3d7f0
RS
806 case UIT_NONE:
807 case UIT_BOOLEAN:
808 case UIT_INFO:
809 case UIT_ERROR:
810 break;
0f113f3e 811 }
f3b3d7f0 812 return NULL;
0f113f3e 813}
a63d5eaa 814
4e049e2c
RL
815int UI_get_result_string_length(UI_STRING *uis)
816{
817 switch (uis->type) {
818 case UIT_PROMPT:
819 case UIT_VERIFY:
820 return uis->result_len;
821 case UIT_NONE:
822 case UIT_BOOLEAN:
823 case UIT_INFO:
824 case UIT_ERROR:
825 break;
826 }
827 return -1;
828}
829
a63d5eaa 830const char *UI_get0_test_string(UI_STRING *uis)
0f113f3e 831{
0f113f3e
MC
832 switch (uis->type) {
833 case UIT_VERIFY:
834 return uis->_.string_data.test_buf;
f3b3d7f0
RS
835 case UIT_NONE:
836 case UIT_BOOLEAN:
837 case UIT_INFO:
838 case UIT_ERROR:
839 case UIT_PROMPT:
840 break;
0f113f3e 841 }
f3b3d7f0 842 return NULL;
0f113f3e 843}
a63d5eaa
RL
844
845int UI_get_result_minsize(UI_STRING *uis)
0f113f3e 846{
0f113f3e
MC
847 switch (uis->type) {
848 case UIT_PROMPT:
849 case UIT_VERIFY:
850 return uis->_.string_data.result_minsize;
f3b3d7f0
RS
851 case UIT_NONE:
852 case UIT_INFO:
853 case UIT_ERROR:
854 case UIT_BOOLEAN:
855 break;
0f113f3e 856 }
f3b3d7f0 857 return -1;
0f113f3e 858}
a63d5eaa
RL
859
860int UI_get_result_maxsize(UI_STRING *uis)
0f113f3e 861{
0f113f3e
MC
862 switch (uis->type) {
863 case UIT_PROMPT:
864 case UIT_VERIFY:
865 return uis->_.string_data.result_maxsize;
f3b3d7f0
RS
866 case UIT_NONE:
867 case UIT_INFO:
868 case UIT_ERROR:
869 case UIT_BOOLEAN:
870 break;
0f113f3e 871 }
f3b3d7f0 872 return -1;
0f113f3e 873}
a63d5eaa 874
2d2ed9df 875int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
0f113f3e 876{
4e049e2c
RL
877 return UI_set_result_ex(ui, uis, result, strlen(result));
878}
0f113f3e 879
4e049e2c
RL
880int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
881{
0f113f3e
MC
882 ui->flags &= ~UI_FLAG_REDOABLE;
883
0f113f3e
MC
884 switch (uis->type) {
885 case UIT_PROMPT:
886 case UIT_VERIFY:
887 {
888 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1];
889 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1];
890
891 BIO_snprintf(number1, sizeof(number1), "%d",
892 uis->_.string_data.result_minsize);
893 BIO_snprintf(number2, sizeof(number2), "%d",
894 uis->_.string_data.result_maxsize);
895
4e049e2c 896 if (len < uis->_.string_data.result_minsize) {
0f113f3e 897 ui->flags |= UI_FLAG_REDOABLE;
4e049e2c 898 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL);
0f113f3e
MC
899 ERR_add_error_data(5, "You must type in ",
900 number1, " to ", number2, " characters");
901 return -1;
902 }
4e049e2c 903 if (len > uis->_.string_data.result_maxsize) {
0f113f3e 904 ui->flags |= UI_FLAG_REDOABLE;
4e049e2c 905 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE);
0f113f3e
MC
906 ERR_add_error_data(5, "You must type in ",
907 number1, " to ", number2, " characters");
908 return -1;
909 }
910 }
911
bde588df 912 if (uis->result_buf == NULL) {
4e049e2c 913 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
0f113f3e
MC
914 return -1;
915 }
916
4e049e2c
RL
917 memcpy(uis->result_buf, result, len);
918 if (len <= uis->_.string_data.result_maxsize)
919 uis->result_buf[len] = '\0';
920 uis->result_len = len;
0f113f3e
MC
921 break;
922 case UIT_BOOLEAN:
923 {
924 const char *p;
925
bde588df 926 if (uis->result_buf == NULL) {
4e049e2c 927 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
0f113f3e
MC
928 return -1;
929 }
930
931 uis->result_buf[0] = '\0';
932 for (p = result; *p; p++) {
933 if (strchr(uis->_.boolean_data.ok_chars, *p)) {
934 uis->result_buf[0] = uis->_.boolean_data.ok_chars[0];
935 break;
936 }
937 if (strchr(uis->_.boolean_data.cancel_chars, *p)) {
938 uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0];
939 break;
940 }
941 }
942 }
f3b3d7f0
RS
943 case UIT_NONE:
944 case UIT_INFO:
945 case UIT_ERROR:
0f113f3e
MC
946 break;
947 }
948 return 0;
949}