]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ui/ui_lib.c
In OpenSSL builds, declare STACK for datatypes ...
[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
RL
358
359char *UI_construct_prompt(UI *ui, const char *object_desc,
0f113f3e
MC
360 const char *object_name)
361{
362 char *prompt = NULL;
363
120fb9e4 364 if (ui->meth->ui_construct_prompt != NULL)
0f113f3e
MC
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);
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
RS
383 OPENSSL_strlcpy(prompt, prompt1, len + 1);
384 OPENSSL_strlcat(prompt, object_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,
693 const char
694 *object_desc,
695 const char
696 *object_name))
697{
120fb9e4 698 if (method != NULL) {
0f113f3e
MC
699 method->ui_construct_prompt = prompt_constructor;
700 return 0;
120fb9e4
RL
701 }
702 return -1;
0f113f3e
MC
703}
704
18cfc668
RL
705int 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
a223ffe6 710int (*UI_method_get_opener(const UI_METHOD *method)) (UI *)
120fb9e4
RL
711{
712 if (method != NULL)
0f113f3e 713 return method->ui_open_session;
120fb9e4 714 return NULL;
0f113f3e
MC
715}
716
a223ffe6 717int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *)
120fb9e4
RL
718{
719 if (method != NULL)
0f113f3e 720 return method->ui_write_string;
120fb9e4 721 return NULL;
0f113f3e
MC
722}
723
a223ffe6 724int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *)
120fb9e4
RL
725{
726 if (method != NULL)
0f113f3e 727 return method->ui_flush;
120fb9e4 728 return NULL;
0f113f3e
MC
729}
730
a223ffe6 731int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *)
120fb9e4
RL
732{
733 if (method != NULL)
0f113f3e 734 return method->ui_read_string;
120fb9e4 735 return NULL;
0f113f3e
MC
736}
737
a223ffe6 738int (*UI_method_get_closer(const UI_METHOD *method)) (UI *)
120fb9e4
RL
739{
740 if (method != NULL)
0f113f3e 741 return method->ui_close_session;
120fb9e4 742 return NULL;
0f113f3e
MC
743}
744
a223ffe6
RL
745char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
746 (UI *, const char *, const char *)
120fb9e4
RL
747{
748 if (method != NULL)
0f113f3e 749 return method->ui_construct_prompt;
120fb9e4 750 return NULL;
0f113f3e 751}
a63d5eaa 752
545360c4
RL
753void *(*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
760void (*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
18cfc668
RL
767const 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
a63d5eaa 772enum UI_string_types UI_get_string_type(UI_STRING *uis)
0f113f3e 773{
0f113f3e
MC
774 return uis->type;
775}
a63d5eaa 776
9ad0f681 777int UI_get_input_flags(UI_STRING *uis)
0f113f3e 778{
0f113f3e
MC
779 return uis->input_flags;
780}
9ad0f681 781
a63d5eaa 782const char *UI_get0_output_string(UI_STRING *uis)
0f113f3e 783{
0f113f3e
MC
784 return uis->out_string;
785}
a63d5eaa 786
2d2ed9df 787const char *UI_get0_action_string(UI_STRING *uis)
0f113f3e 788{
0f113f3e 789 switch (uis->type) {
0f113f3e
MC
790 case UIT_BOOLEAN:
791 return uis->_.boolean_data.action_desc;
6e470e19 792 case UIT_PROMPT:
f3b3d7f0
RS
793 case UIT_NONE:
794 case UIT_VERIFY:
795 case UIT_INFO:
796 case UIT_ERROR:
797 break;
0f113f3e 798 }
f3b3d7f0 799 return NULL;
0f113f3e 800}
2d2ed9df 801
a63d5eaa 802const char *UI_get0_result_string(UI_STRING *uis)
0f113f3e 803{
0f113f3e
MC
804 switch (uis->type) {
805 case UIT_PROMPT:
806 case UIT_VERIFY:
807 return uis->result_buf;
f3b3d7f0
RS
808 case UIT_NONE:
809 case UIT_BOOLEAN:
810 case UIT_INFO:
811 case UIT_ERROR:
812 break;
0f113f3e 813 }
f3b3d7f0 814 return NULL;
0f113f3e 815}
a63d5eaa 816
4e049e2c
RL
817int 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
a63d5eaa 832const char *UI_get0_test_string(UI_STRING *uis)
0f113f3e 833{
0f113f3e
MC
834 switch (uis->type) {
835 case UIT_VERIFY:
836 return uis->_.string_data.test_buf;
f3b3d7f0
RS
837 case UIT_NONE:
838 case UIT_BOOLEAN:
839 case UIT_INFO:
840 case UIT_ERROR:
841 case UIT_PROMPT:
842 break;
0f113f3e 843 }
f3b3d7f0 844 return NULL;
0f113f3e 845}
a63d5eaa
RL
846
847int UI_get_result_minsize(UI_STRING *uis)
0f113f3e 848{
0f113f3e
MC
849 switch (uis->type) {
850 case UIT_PROMPT:
851 case UIT_VERIFY:
852 return uis->_.string_data.result_minsize;
f3b3d7f0
RS
853 case UIT_NONE:
854 case UIT_INFO:
855 case UIT_ERROR:
856 case UIT_BOOLEAN:
857 break;
0f113f3e 858 }
f3b3d7f0 859 return -1;
0f113f3e 860}
a63d5eaa
RL
861
862int UI_get_result_maxsize(UI_STRING *uis)
0f113f3e 863{
0f113f3e
MC
864 switch (uis->type) {
865 case UIT_PROMPT:
866 case UIT_VERIFY:
867 return uis->_.string_data.result_maxsize;
f3b3d7f0
RS
868 case UIT_NONE:
869 case UIT_INFO:
870 case UIT_ERROR:
871 case UIT_BOOLEAN:
872 break;
0f113f3e 873 }
f3b3d7f0 874 return -1;
0f113f3e 875}
a63d5eaa 876
2d2ed9df 877int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
0f113f3e 878{
4e049e2c
RL
879 return UI_set_result_ex(ui, uis, result, strlen(result));
880}
0f113f3e 881
4e049e2c
RL
882int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
883{
0f113f3e
MC
884 ui->flags &= ~UI_FLAG_REDOABLE;
885
0f113f3e
MC
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
4e049e2c 898 if (len < uis->_.string_data.result_minsize) {
0f113f3e 899 ui->flags |= UI_FLAG_REDOABLE;
4e049e2c 900 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL);
0f113f3e
MC
901 ERR_add_error_data(5, "You must type in ",
902 number1, " to ", number2, " characters");
903 return -1;
904 }
4e049e2c 905 if (len > uis->_.string_data.result_maxsize) {
0f113f3e 906 ui->flags |= UI_FLAG_REDOABLE;
4e049e2c 907 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE);
0f113f3e
MC
908 ERR_add_error_data(5, "You must type in ",
909 number1, " to ", number2, " characters");
910 return -1;
911 }
912 }
913
bde588df 914 if (uis->result_buf == NULL) {
4e049e2c 915 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
0f113f3e
MC
916 return -1;
917 }
918
4e049e2c
RL
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;
0f113f3e
MC
923 break;
924 case UIT_BOOLEAN:
925 {
926 const char *p;
927
bde588df 928 if (uis->result_buf == NULL) {
4e049e2c 929 UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
0f113f3e
MC
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 }
f3b3d7f0
RS
945 case UIT_NONE:
946 case UIT_INFO:
947 case UIT_ERROR:
0f113f3e
MC
948 break;
949 }
950 return 0;
951}