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