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