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