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