]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ui/ui_lib.c
In OpenSSL builds, declare STACK for datatypes ...
[thirdparty/openssl.git] / crypto / ui / ui_lib.c
1 /*
2 * Copyright 2001-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 "internal/cryptlib.h"
12 #include <openssl/e_os2.h>
13 #include <openssl/buffer.h>
14 #include <openssl/ui.h>
15 #include <openssl/err.h>
16 #include "ui_local.h"
17
18 DEFINE_STACK_OF(UI_STRING)
19
20 UI *UI_new(void)
21 {
22 return UI_new_method(NULL);
23 }
24
25 UI *UI_new_method(const UI_METHOD *method)
26 {
27 UI *ret = OPENSSL_zalloc(sizeof(*ret));
28
29 if (ret == NULL) {
30 UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
31 return NULL;
32 }
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
41 if (method == NULL)
42 method = UI_get_default_method();
43 if (method == NULL)
44 method = UI_null();
45 ret->meth = method;
46
47 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) {
48 OPENSSL_free(ret);
49 return NULL;
50 }
51 return ret;
52 }
53
54 static void free_string(UI_STRING *uis)
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;
64 case UIT_NONE:
65 case UIT_PROMPT:
66 case UIT_VERIFY:
67 case UIT_ERROR:
68 case UIT_INFO:
69 break;
70 }
71 }
72 OPENSSL_free(uis);
73 }
74
75 void UI_free(UI *ui)
76 {
77 if (ui == NULL)
78 return;
79 if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
80 ui->meth->ui_destroy_data(ui, ui->user_data);
81 }
82 sk_UI_STRING_pop_free(ui->strings, free_string);
83 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
84 CRYPTO_THREAD_lock_free(ui->lock);
85 OPENSSL_free(ui);
86 }
87
88 static int allocate_string_stack(UI *ui)
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 }
98
99 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
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);
111 } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) {
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 }
120
121 static int general_allocate_string(UI *ui, const char *prompt,
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
131 if (s != NULL) {
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);
137 /* sk_push() returns 0 on error. Let's adapt that */
138 if (ret <= 0) {
139 ret--;
140 free_string(s);
141 }
142 } else
143 free_string(s);
144 }
145 return ret;
146 }
147
148 static int general_allocate_boolean(UI *ui,
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 {
166 for (p = ok_chars; *p != '\0'; p++) {
167 if (strchr(cancel_chars, *p) != NULL) {
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
176 if (s != NULL) {
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 /*
183 * sk_push() returns 0 on error. Let's adapt that
184 */
185 if (ret <= 0) {
186 ret--;
187 free_string(s);
188 }
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 */
200 int UI_add_input_string(UI *ui, const char *prompt, int flags,
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 }
207
208 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
209 int UI_dup_input_string(UI *ui, const char *prompt, int flags,
210 char *result_buf, int minsize, int maxsize)
211 {
212 char *prompt_copy = NULL;
213
214 if (prompt != NULL) {
215 prompt_copy = OPENSSL_strdup(prompt);
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 }
226
227 int UI_add_verify_string(UI *ui, const char *prompt, int flags,
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 }
235
236 int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
237 char *result_buf, int minsize, int maxsize,
238 const char *test_buf)
239 {
240 char *prompt_copy = NULL;
241
242 if (prompt != NULL) {
243 prompt_copy = OPENSSL_strdup(prompt);
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 }
254
255 int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
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 }
263
264 int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
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
273 if (prompt != NULL) {
274 prompt_copy = OPENSSL_strdup(prompt);
275 if (prompt_copy == NULL) {
276 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
277 goto err;
278 }
279 }
280
281 if (action_desc != NULL) {
282 action_desc_copy = OPENSSL_strdup(action_desc);
283 if (action_desc_copy == NULL) {
284 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
285 goto err;
286 }
287 }
288
289 if (ok_chars != NULL) {
290 ok_chars_copy = OPENSSL_strdup(ok_chars);
291 if (ok_chars_copy == NULL) {
292 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
295 }
296
297 if (cancel_chars != NULL) {
298 cancel_chars_copy = OPENSSL_strdup(cancel_chars);
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);
308 err:
309 OPENSSL_free(prompt_copy);
310 OPENSSL_free(action_desc_copy);
311 OPENSSL_free(ok_chars_copy);
312 OPENSSL_free(cancel_chars_copy);
313 return -1;
314 }
315
316 int UI_add_info_string(UI *ui, const char *text)
317 {
318 return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
319 NULL);
320 }
321
322 int UI_dup_info_string(UI *ui, const char *text)
323 {
324 char *text_copy = NULL;
325
326 if (text != NULL) {
327 text_copy = OPENSSL_strdup(text);
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 }
337
338 int UI_add_error_string(UI *ui, const char *text)
339 {
340 return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
341 NULL);
342 }
343
344 int UI_dup_error_string(UI *ui, const char *text)
345 {
346 char *text_copy = NULL;
347
348 if (text != NULL) {
349 text_copy = OPENSSL_strdup(text);
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 }
358
359 char *UI_construct_prompt(UI *ui, const char *object_desc,
360 const char *object_name)
361 {
362 char *prompt = NULL;
363
364 if (ui->meth->ui_construct_prompt != NULL)
365 prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name);
366 else {
367 char prompt1[] = "Enter ";
368 char prompt2[] = " for ";
369 char prompt3[] = ":";
370 int len = 0;
371
372 if (object_desc == NULL)
373 return NULL;
374 len = sizeof(prompt1) - 1 + strlen(object_desc);
375 if (object_name != NULL)
376 len += sizeof(prompt2) - 1 + strlen(object_name);
377 len += sizeof(prompt3) - 1;
378
379 if ((prompt = OPENSSL_malloc(len + 1)) == NULL) {
380 UIerr(UI_F_UI_CONSTRUCT_PROMPT, ERR_R_MALLOC_FAILURE);
381 return NULL;
382 }
383 OPENSSL_strlcpy(prompt, prompt1, len + 1);
384 OPENSSL_strlcat(prompt, object_desc, len + 1);
385 if (object_name != NULL) {
386 OPENSSL_strlcat(prompt, prompt2, len + 1);
387 OPENSSL_strlcat(prompt, object_name, len + 1);
388 }
389 OPENSSL_strlcat(prompt, prompt3, len + 1);
390 }
391 return prompt;
392 }
393
394 void *UI_add_user_data(UI *ui, void *user_data)
395 {
396 void *old_data = ui->user_data;
397
398 if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
399 ui->meth->ui_destroy_data(ui, old_data);
400 old_data = NULL;
401 }
402 ui->user_data = user_data;
403 ui->flags &= ~UI_FLAG_DUPL_DATA;
404 return old_data;
405 }
406
407 int 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
429 void *UI_get0_user_data(UI *ui)
430 {
431 return ui->user_data;
432 }
433
434 const char *UI_get0_result(UI *ui, int i)
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 }
446
447 int 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
460 static int print_error(const char *str, size_t len, UI *ui)
461 {
462 UI_STRING uis;
463
464 memset(&uis, 0, sizeof(uis));
465 uis.type = UIT_ERROR;
466 uis.out_string = str;
467
468 if (ui->meth->ui_write_string != NULL
469 && ui->meth->ui_write_string(ui, &uis) <= 0)
470 return -1;
471 return 0;
472 }
473
474 int UI_process(UI *ui)
475 {
476 int i, ok = 0;
477 const char *state = "processing";
478
479 if (ui->meth->ui_open_session != NULL
480 && ui->meth->ui_open_session(ui) <= 0) {
481 state = "opening session";
482 ok = -1;
483 goto err;
484 }
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++) {
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))
495 {
496 state = "writing strings";
497 ok = -1;
498 goto err;
499 }
500 }
501
502 if (ui->meth->ui_flush != NULL)
503 switch (ui->meth->ui_flush(ui)) {
504 case -1: /* Interrupt/Cancel/something... */
505 ui->flags &= ~UI_FLAG_REDOABLE;
506 ok = -2;
507 goto err;
508 case 0: /* Errors */
509 state = "flushing";
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++) {
518 if (ui->meth->ui_read_string != NULL) {
519 switch (ui->meth->ui_read_string(ui,
520 sk_UI_STRING_value(ui->strings,
521 i))) {
522 case -1: /* Interrupt/Cancel/something... */
523 ui->flags &= ~UI_FLAG_REDOABLE;
524 ok = -2;
525 goto err;
526 case 0: /* Errors */
527 state = "reading strings";
528 ok = -1;
529 goto err;
530 default: /* Success */
531 ok = 0;
532 break;
533 }
534 }
535 }
536
537 state = NULL;
538 err:
539 if (ui->meth->ui_close_session != NULL
540 && ui->meth->ui_close_session(ui) <= 0) {
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 }
550 return ok;
551 }
552
553 int 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:
561 {
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;
568 }
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
578 int UI_set_ex_data(UI *r, int idx, void *arg)
579 {
580 return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
581 }
582
583 void *UI_get_ex_data(const UI *r, int idx)
584 {
585 return CRYPTO_get_ex_data(&r->ex_data, idx);
586 }
587
588 const UI_METHOD *UI_get_method(UI *ui)
589 {
590 return ui->meth;
591 }
592
593 const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
594 {
595 ui->meth = meth;
596 return ui->meth;
597 }
598
599 UI_METHOD *UI_create_method(const char *name)
600 {
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;
612 }
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 */
621 void UI_destroy_method(UI_METHOD *ui_method)
622 {
623 if (ui_method == NULL)
624 return;
625 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method,
626 &ui_method->ex_data);
627 OPENSSL_free(ui_method->name);
628 ui_method->name = NULL;
629 OPENSSL_free(ui_method);
630 }
631
632 int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui))
633 {
634 if (method != NULL) {
635 method->ui_open_session = opener;
636 return 0;
637 }
638 return -1;
639 }
640
641 int UI_method_set_writer(UI_METHOD *method,
642 int (*writer) (UI *ui, UI_STRING *uis))
643 {
644 if (method != NULL) {
645 method->ui_write_string = writer;
646 return 0;
647 }
648 return -1;
649 }
650
651 int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui))
652 {
653 if (method != NULL) {
654 method->ui_flush = flusher;
655 return 0;
656 }
657 return -1;
658 }
659
660 int UI_method_set_reader(UI_METHOD *method,
661 int (*reader) (UI *ui, UI_STRING *uis))
662 {
663 if (method != NULL) {
664 method->ui_read_string = reader;
665 return 0;
666 }
667 return -1;
668 }
669
670 int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui))
671 {
672 if (method != NULL) {
673 method->ui_close_session = closer;
674 return 0;
675 }
676 return -1;
677 }
678
679 int 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
691 int UI_method_set_prompt_constructor(UI_METHOD *method,
692 char *(*prompt_constructor) (UI *ui,
693 const char
694 *object_desc,
695 const char
696 *object_name))
697 {
698 if (method != NULL) {
699 method->ui_construct_prompt = prompt_constructor;
700 return 0;
701 }
702 return -1;
703 }
704
705 int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data)
706 {
707 return CRYPTO_set_ex_data(&method->ex_data, idx, data);
708 }
709
710 int (*UI_method_get_opener(const UI_METHOD *method)) (UI *)
711 {
712 if (method != NULL)
713 return method->ui_open_session;
714 return NULL;
715 }
716
717 int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *)
718 {
719 if (method != NULL)
720 return method->ui_write_string;
721 return NULL;
722 }
723
724 int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *)
725 {
726 if (method != NULL)
727 return method->ui_flush;
728 return NULL;
729 }
730
731 int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *)
732 {
733 if (method != NULL)
734 return method->ui_read_string;
735 return NULL;
736 }
737
738 int (*UI_method_get_closer(const UI_METHOD *method)) (UI *)
739 {
740 if (method != NULL)
741 return method->ui_close_session;
742 return NULL;
743 }
744
745 char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
746 (UI *, const char *, const char *)
747 {
748 if (method != NULL)
749 return method->ui_construct_prompt;
750 return NULL;
751 }
752
753 void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *)
754 {
755 if (method != NULL)
756 return method->ui_duplicate_data;
757 return NULL;
758 }
759
760 void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *)
761 {
762 if (method != NULL)
763 return method->ui_destroy_data;
764 return NULL;
765 }
766
767 const void *UI_method_get_ex_data(const UI_METHOD *method, int idx)
768 {
769 return CRYPTO_get_ex_data(&method->ex_data, idx);
770 }
771
772 enum UI_string_types UI_get_string_type(UI_STRING *uis)
773 {
774 return uis->type;
775 }
776
777 int UI_get_input_flags(UI_STRING *uis)
778 {
779 return uis->input_flags;
780 }
781
782 const char *UI_get0_output_string(UI_STRING *uis)
783 {
784 return uis->out_string;
785 }
786
787 const char *UI_get0_action_string(UI_STRING *uis)
788 {
789 switch (uis->type) {
790 case UIT_BOOLEAN:
791 return uis->_.boolean_data.action_desc;
792 case UIT_PROMPT:
793 case UIT_NONE:
794 case UIT_VERIFY:
795 case UIT_INFO:
796 case UIT_ERROR:
797 break;
798 }
799 return NULL;
800 }
801
802 const char *UI_get0_result_string(UI_STRING *uis)
803 {
804 switch (uis->type) {
805 case UIT_PROMPT:
806 case UIT_VERIFY:
807 return uis->result_buf;
808 case UIT_NONE:
809 case UIT_BOOLEAN:
810 case UIT_INFO:
811 case UIT_ERROR:
812 break;
813 }
814 return NULL;
815 }
816
817 int UI_get_result_string_length(UI_STRING *uis)
818 {
819 switch (uis->type) {
820 case UIT_PROMPT:
821 case UIT_VERIFY:
822 return uis->result_len;
823 case UIT_NONE:
824 case UIT_BOOLEAN:
825 case UIT_INFO:
826 case UIT_ERROR:
827 break;
828 }
829 return -1;
830 }
831
832 const char *UI_get0_test_string(UI_STRING *uis)
833 {
834 switch (uis->type) {
835 case UIT_VERIFY:
836 return uis->_.string_data.test_buf;
837 case UIT_NONE:
838 case UIT_BOOLEAN:
839 case UIT_INFO:
840 case UIT_ERROR:
841 case UIT_PROMPT:
842 break;
843 }
844 return NULL;
845 }
846
847 int UI_get_result_minsize(UI_STRING *uis)
848 {
849 switch (uis->type) {
850 case UIT_PROMPT:
851 case UIT_VERIFY:
852 return uis->_.string_data.result_minsize;
853 case UIT_NONE:
854 case UIT_INFO:
855 case UIT_ERROR:
856 case UIT_BOOLEAN:
857 break;
858 }
859 return -1;
860 }
861
862 int UI_get_result_maxsize(UI_STRING *uis)
863 {
864 switch (uis->type) {
865 case UIT_PROMPT:
866 case UIT_VERIFY:
867 return uis->_.string_data.result_maxsize;
868 case UIT_NONE:
869 case UIT_INFO:
870 case UIT_ERROR:
871 case UIT_BOOLEAN:
872 break;
873 }
874 return -1;
875 }
876
877 int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
878 {
879 return UI_set_result_ex(ui, uis, result, strlen(result));
880 }
881
882 int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
883 {
884 ui->flags &= ~UI_FLAG_REDOABLE;
885
886 switch (uis->type) {
887 case UIT_PROMPT:
888 case UIT_VERIFY:
889 {
890 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1];
891 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1];
892
893 BIO_snprintf(number1, sizeof(number1), "%d",
894 uis->_.string_data.result_minsize);
895 BIO_snprintf(number2, sizeof(number2), "%d",
896 uis->_.string_data.result_maxsize);
897
898 if (len < uis->_.string_data.result_minsize) {
899 ui->flags |= UI_FLAG_REDOABLE;
900 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL);
901 ERR_add_error_data(5, "You must type in ",
902 number1, " to ", number2, " characters");
903 return -1;
904 }
905 if (len > uis->_.string_data.result_maxsize) {
906 ui->flags |= UI_FLAG_REDOABLE;
907 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE);
908 ERR_add_error_data(5, "You must type in ",
909 number1, " to ", number2, " characters");
910 return -1;
911 }
912 }
913
914 if (uis->result_buf == NULL) {
915 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
916 return -1;
917 }
918
919 memcpy(uis->result_buf, result, len);
920 if (len <= uis->_.string_data.result_maxsize)
921 uis->result_buf[len] = '\0';
922 uis->result_len = len;
923 break;
924 case UIT_BOOLEAN:
925 {
926 const char *p;
927
928 if (uis->result_buf == NULL) {
929 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
930 return -1;
931 }
932
933 uis->result_buf[0] = '\0';
934 for (p = result; *p; p++) {
935 if (strchr(uis->_.boolean_data.ok_chars, *p)) {
936 uis->result_buf[0] = uis->_.boolean_data.ok_chars[0];
937 break;
938 }
939 if (strchr(uis->_.boolean_data.cancel_chars, *p)) {
940 uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0];
941 break;
942 }
943 }
944 }
945 case UIT_NONE:
946 case UIT_INFO:
947 case UIT_ERROR:
948 break;
949 }
950 return 0;
951 }