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