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