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