1 /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ 2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL 3 * project 2001. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * openssl-core@openssl.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <string.h> 60 #include "cryptlib.h" 61 #include <openssl/e_os2.h> 62 #include <openssl/buffer.h> 63 #include <openssl/ui.h> 64 #include <openssl/err.h> 65 #include "ui_locl.h" 66 67 IMPLEMENT_STACK_OF(UI_STRING_ST) 68 69 static const UI_METHOD *default_UI_meth=NULL; 70 71 UI *UI_new(void) 72 { 73 return(UI_new_method(NULL)); 74 } 75 76 UI *UI_new_method(const UI_METHOD *method) 77 { 78 UI *ret; 79 80 ret=(UI *)OPENSSL_malloc(sizeof(UI)); 81 if (ret == NULL) 82 { 83 UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE); 84 return NULL; 85 } 86 if (method == NULL) 87 ret->meth=UI_get_default_method(); 88 else 89 ret->meth=method; 90 91 ret->strings=NULL; 92 ret->user_data=NULL; 93 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); 94 return ret; 95 } 96 97 static void free_string(UI_STRING *uis) 98 { 99 if (uis->flags & OUT_STRING_FREEABLE) 100 { 101 OPENSSL_free((char *)uis->out_string); 102 switch(uis->type) 103 { 104 case UIT_BOOLEAN: 105 OPENSSL_free((char *)uis->_.boolean_data.action_desc); 106 OPENSSL_free((char *)uis->_.boolean_data.ok_chars); 107 OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); 108 break; 109 default: 110 break; 111 } 112 } 113 OPENSSL_free(uis); 114 } 115 116 void UI_free(UI *ui) 117 { 118 if (ui == NULL) 119 return; 120 sk_UI_STRING_pop_free(ui->strings,free_string); 121 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); 122 OPENSSL_free(ui); 123 } 124 125 static int allocate_string_stack(UI *ui) 126 { 127 if (ui->strings == NULL) 128 { 129 ui->strings=sk_UI_STRING_new_null(); 130 if (ui->strings == NULL) 131 { 132 return -1; 133 } 134 } 135 return 0; 136 } 137 138 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, 139 int prompt_freeable, enum UI_string_types type, int input_flags, 140 char *result_buf) 141 { 142 UI_STRING *ret = NULL; 143 144 if (prompt == NULL) 145 { 146 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER); 147 } 148 else if ((type == UIT_PROMPT || type == UIT_VERIFY 149 || type == UIT_BOOLEAN) && result_buf == NULL) 150 { 151 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER); 152 } 153 else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING)))) 154 { 155 ret->out_string=prompt; 156 ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0; 157 ret->input_flags=input_flags; 158 ret->type=type; 159 ret->result_buf=result_buf; 160 } 161 return ret; 162 } 163 164 static int general_allocate_string(UI *ui, const char *prompt, 165 int prompt_freeable, enum UI_string_types type, int input_flags, 166 char *result_buf, int minsize, int maxsize, const char *test_buf) 167 { 168 int ret = -1; 169 UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, 170 type, input_flags, result_buf); 171 172 if (s) 173 { 174 if (allocate_string_stack(ui) >= 0) 175 { 176 s->_.string_data.result_minsize=minsize; 177 s->_.string_data.result_maxsize=maxsize; 178 s->_.string_data.test_buf=test_buf; 179 ret=sk_UI_STRING_push(ui->strings, s); 180 /* sk_push() returns 0 on error. Let's addapt that */ 181 if (ret <= 0) ret--; 182 } 183 else 184 free_string(s); 185 } 186 return ret; 187 } 188 189 static int general_allocate_boolean(UI *ui, 190 const char *prompt, const char *action_desc, 191 const char *ok_chars, const char *cancel_chars, 192 int prompt_freeable, enum UI_string_types type, int input_flags, 193 char *result_buf) 194 { 195 int ret = -1; 196 UI_STRING *s; 197 const char *p; 198 199 if (ok_chars == NULL) 200 { 201 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); 202 } 203 else if (cancel_chars == NULL) 204 { 205 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); 206 } 207 else 208 { 209 for(p = ok_chars; *p; p++) 210 { 211 if (strchr(cancel_chars, *p)) 212 { 213 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 214 UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); 215 } 216 } 217 218 s = general_allocate_prompt(ui, prompt, prompt_freeable, 219 type, input_flags, result_buf); 220 221 if (s) 222 { 223 if (allocate_string_stack(ui) >= 0) 224 { 225 s->_.boolean_data.action_desc = action_desc; 226 s->_.boolean_data.ok_chars = ok_chars; 227 s->_.boolean_data.cancel_chars = cancel_chars; 228 ret=sk_UI_STRING_push(ui->strings, s); 229 /* sk_push() returns 0 on error. 230 Let's addapt that */ 231 if (ret <= 0) ret--; 232 } 233 else 234 free_string(s); 235 } 236 } 237 return ret; 238 } 239 240 /* Returns the index to the place in the stack or -1 for error. Uses a 241 direct reference to the prompt. */ 242 int UI_add_input_string(UI *ui, const char *prompt, int flags, 243 char *result_buf, int minsize, int maxsize) 244 { 245 return general_allocate_string(ui, prompt, 0, 246 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); 247 } 248 249 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ 250 int UI_dup_input_string(UI *ui, const char *prompt, int flags, 251 char *result_buf, int minsize, int maxsize) 252 { 253 char *prompt_copy=NULL; 254 255 if (prompt) 256 { 257 prompt_copy=BUF_strdup(prompt); 258 if (prompt_copy == NULL) 259 { 260 UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE); 261 return 0; 262 } 263 } 264 265 return general_allocate_string(ui, prompt_copy, 1, 266 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); 267 } 268 269 int UI_add_verify_string(UI *ui, const char *prompt, int flags, 270 char *result_buf, int minsize, int maxsize, const char *test_buf) 271 { 272 return general_allocate_string(ui, prompt, 0, 273 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); 274 } 275 276 int UI_dup_verify_string(UI *ui, const char *prompt, int flags, 277 char *result_buf, int minsize, int maxsize, const char *test_buf) 278 { 279 char *prompt_copy=NULL; 280 281 if (prompt) 282 { 283 prompt_copy=BUF_strdup(prompt); 284 if (prompt_copy == NULL) 285 { 286 UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE); 287 return -1; 288 } 289 } 290 291 return general_allocate_string(ui, prompt_copy, 1, 292 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); 293 } 294 295 int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, 296 const char *ok_chars, const char *cancel_chars, 297 int flags, char *result_buf) 298 { 299 return general_allocate_boolean(ui, prompt, action_desc, 300 ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf); 301 } 302 303 int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, 304 const char *ok_chars, const char *cancel_chars, 305 int flags, char *result_buf) 306 { 307 char *prompt_copy = NULL; 308 char *action_desc_copy = NULL; 309 char *ok_chars_copy = NULL; 310 char *cancel_chars_copy = NULL; 311 312 if (prompt) 313 { 314 prompt_copy=BUF_strdup(prompt); 315 if (prompt_copy == NULL) 316 { 317 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 318 goto err; 319 } 320 } 321 322 if (action_desc) 323 { 324 action_desc_copy=BUF_strdup(action_desc); 325 if (action_desc_copy == NULL) 326 { 327 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 328 goto err; 329 } 330 } 331 332 if (ok_chars) 333 { 334 ok_chars_copy=BUF_strdup(ok_chars); 335 if (ok_chars_copy == NULL) 336 { 337 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 338 goto err; 339 } 340 } 341 342 if (cancel_chars) 343 { 344 cancel_chars_copy=BUF_strdup(cancel_chars); 345 if (cancel_chars_copy == NULL) 346 { 347 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 348 goto err; 349 } 350 } 351 352 return general_allocate_boolean(ui, prompt_copy, action_desc_copy, 353 ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags, 354 result_buf); 355 err: 356 if (prompt_copy) OPENSSL_free(prompt_copy); 357 if (action_desc_copy) OPENSSL_free(action_desc_copy); 358 if (ok_chars_copy) OPENSSL_free(ok_chars_copy); 359 if (cancel_chars_copy) OPENSSL_free(cancel_chars_copy); 360 return -1; 361 } 362 363 int UI_add_info_string(UI *ui, const char *text) 364 { 365 return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, 366 NULL); 367 } 368 369 int UI_dup_info_string(UI *ui, const char *text) 370 { 371 char *text_copy=NULL; 372 373 if (text) 374 { 375 text_copy=BUF_strdup(text); 376 if (text_copy == NULL) 377 { 378 UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE); 379 return -1; 380 } 381 } 382 383 return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, 384 0, 0, NULL); 385 } 386 387 int UI_add_error_string(UI *ui, const char *text) 388 { 389 return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, 390 NULL); 391 } 392 393 int UI_dup_error_string(UI *ui, const char *text) 394 { 395 char *text_copy=NULL; 396 397 if (text) 398 { 399 text_copy=BUF_strdup(text); 400 if (text_copy == NULL) 401 { 402 UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE); 403 return -1; 404 } 405 } 406 return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, 407 0, 0, NULL); 408 } 409 410 char *UI_construct_prompt(UI *ui, const char *object_desc, 411 const char *object_name) 412 { 413 char *prompt = NULL; 414 415 if (ui->meth->ui_construct_prompt) 416 prompt = ui->meth->ui_construct_prompt(ui, 417 object_desc, object_name); 418 else 419 { 420 char prompt1[] = "Enter "; 421 char prompt2[] = " for "; 422 char prompt3[] = ":"; 423 int len = 0; 424 425 if (object_desc == NULL) 426 return NULL; 427 len = sizeof(prompt1) - 1 + strlen(object_desc); 428 if (object_name) 429 len += sizeof(prompt2) - 1 + strlen(object_name); 430 len += sizeof(prompt3) - 1; 431 432 prompt = (char *)OPENSSL_malloc(len + 1); 433 BUF_strlcpy(prompt, prompt1, len + 1); 434 BUF_strlcat(prompt, object_desc, len + 1); 435 if (object_name) 436 { 437 BUF_strlcat(prompt, prompt2, len + 1); 438 BUF_strlcat(prompt, object_name, len + 1); 439 } 440 BUF_strlcat(prompt, prompt3, len + 1); 441 } 442 return prompt; 443 } 444 445 void *UI_add_user_data(UI *ui, void *user_data) 446 { 447 void *old_data = ui->user_data; 448 ui->user_data = user_data; 449 return old_data; 450 } 451 452 void *UI_get0_user_data(UI *ui) 453 { 454 return ui->user_data; 455 } 456 457 const char *UI_get0_result(UI *ui, int i) 458 { 459 if (i < 0) 460 { 461 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL); 462 return NULL; 463 } 464 if (i >= sk_UI_STRING_num(ui->strings)) 465 { 466 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE); 467 return NULL; 468 } 469 return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); 470 } 471 472 static int print_error(const char *str, size_t len, UI *ui) 473 { 474 UI_STRING uis; 475 476 memset(&uis, 0, sizeof(uis)); 477 uis.type = UIT_ERROR; 478 uis.out_string = str; 479 480 if (ui->meth->ui_write_string 481 && !ui->meth->ui_write_string(ui, &uis)) 482 return -1; 483 return 0; 484 } 485 486 int UI_process(UI *ui) 487 { 488 int i, ok=0; 489 490 if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) 491 return -1; 492 493 if (ui->flags & UI_FLAG_PRINT_ERRORS) 494 ERR_print_errors_cb( 495 (int (*)(const char *, size_t, void *))print_error, 496 (void *)ui); 497 498 for(i=0; i<sk_UI_STRING_num(ui->strings); i++) 499 { 500 if (ui->meth->ui_write_string 501 && !ui->meth->ui_write_string(ui, 502 sk_UI_STRING_value(ui->strings, i))) 503 { 504 ok=-1; 505 goto err; 506 } 507 } 508 509 if (ui->meth->ui_flush) 510 switch(ui->meth->ui_flush(ui)) 511 { 512 case -1: /* Interrupt/Cancel/something... */ 513 ok = -2; 514 goto err; 515 case 0: /* Errors */ 516 ok = -1; 517 goto err; 518 default: /* Success */ 519 ok = 0; 520 break; 521 } 522 523 for(i=0; i<sk_UI_STRING_num(ui->strings); i++) 524 { 525 if (ui->meth->ui_read_string) 526 { 527 switch(ui->meth->ui_read_string(ui, 528 sk_UI_STRING_value(ui->strings, i))) 529 { 530 case -1: /* Interrupt/Cancel/something... */ 531 ok = -2; 532 goto err; 533 case 0: /* Errors */ 534 ok = -1; 535 goto err; 536 default: /* Success */ 537 ok = 0; 538 break; 539 } 540 } 541 } 542 err: 543 if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) 544 return -1; 545 return ok; 546 } 547 548 int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void)) 549 { 550 if (ui == NULL) 551 { 552 UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER); 553 return -1; 554 } 555 switch(cmd) 556 { 557 case UI_CTRL_PRINT_ERRORS: 558 { 559 int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS); 560 if (i) 561 ui->flags |= UI_FLAG_PRINT_ERRORS; 562 else 563 ui->flags &= ~UI_FLAG_PRINT_ERRORS; 564 return save_flag; 565 } 566 case UI_CTRL_IS_REDOABLE: 567 return !!(ui->flags & UI_FLAG_REDOABLE); 568 default: 569 break; 570 } 571 UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND); 572 return -1; 573 } 574 575 int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 576 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 577 { 578 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, 579 new_func, dup_func, free_func); 580 } 581 582 int UI_set_ex_data(UI *r, int idx, void *arg) 583 { 584 return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); 585 } 586 587 void *UI_get_ex_data(UI *r, int idx) 588 { 589 return(CRYPTO_get_ex_data(&r->ex_data,idx)); 590 } 591 592 void UI_set_default_method(const UI_METHOD *meth) 593 { 594 default_UI_meth=meth; 595 } 596 597 const UI_METHOD *UI_get_default_method(void) 598 { 599 if (default_UI_meth == NULL) 600 { 601 default_UI_meth=UI_OpenSSL(); 602 } 603 return default_UI_meth; 604 } 605 606 const UI_METHOD *UI_get_method(UI *ui) 607 { 608 return ui->meth; 609 } 610 611 const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) 612 { 613 ui->meth=meth; 614 return ui->meth; 615 } 616 617 618 UI_METHOD *UI_create_method(char *name) 619 { 620 UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); 621 622 if (ui_method) 623 { 624 memset(ui_method, 0, sizeof(*ui_method)); 625 ui_method->name = BUF_strdup(name); 626 } 627 return ui_method; 628 } 629 630 /* BIG FSCKING WARNING!!!! If you use this on a statically allocated method 631 (that is, it hasn't been allocated using UI_create_method(), you deserve 632 anything Murphy can throw at you and more! You have been warned. */ 633 void UI_destroy_method(UI_METHOD *ui_method) 634 { 635 OPENSSL_free(ui_method->name); 636 ui_method->name = NULL; 637 OPENSSL_free(ui_method); 638 } 639 640 int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)) 641 { 642 if (method) 643 { 644 method->ui_open_session = opener; 645 return 0; 646 } 647 else 648 return -1; 649 } 650 651 int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)) 652 { 653 if (method) 654 { 655 method->ui_write_string = writer; 656 return 0; 657 } 658 else 659 return -1; 660 } 661 662 int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)) 663 { 664 if (method) 665 { 666 method->ui_flush = flusher; 667 return 0; 668 } 669 else 670 return -1; 671 } 672 673 int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)) 674 { 675 if (method) 676 { 677 method->ui_read_string = reader; 678 return 0; 679 } 680 else 681 return -1; 682 } 683 684 int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)) 685 { 686 if (method) 687 { 688 method->ui_close_session = closer; 689 return 0; 690 } 691 else 692 return -1; 693 } 694 695 int (*UI_method_get_opener(UI_METHOD *method))(UI*) 696 { 697 if (method) 698 return method->ui_open_session; 699 else 700 return NULL; 701 } 702 703 int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*) 704 { 705 if (method) 706 return method->ui_write_string; 707 else 708 return NULL; 709 } 710 711 int (*UI_method_get_flusher(UI_METHOD *method))(UI*) 712 { 713 if (method) 714 return method->ui_flush; 715 else 716 return NULL; 717 } 718 719 int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*) 720 { 721 if (method) 722 return method->ui_read_string; 723 else 724 return NULL; 725 } 726 727 int (*UI_method_get_closer(UI_METHOD *method))(UI*) 728 { 729 if (method) 730 return method->ui_close_session; 731 else 732 return NULL; 733 } 734 735 enum UI_string_types UI_get_string_type(UI_STRING *uis) 736 { 737 if (!uis) 738 return UIT_NONE; 739 return uis->type; 740 } 741 742 int UI_get_input_flags(UI_STRING *uis) 743 { 744 if (!uis) 745 return 0; 746 return uis->input_flags; 747 } 748 749 const char *UI_get0_output_string(UI_STRING *uis) 750 { 751 if (!uis) 752 return NULL; 753 return uis->out_string; 754 } 755 756 const char *UI_get0_action_string(UI_STRING *uis) 757 { 758 if (!uis) 759 return NULL; 760 switch(uis->type) 761 { 762 case UIT_PROMPT: 763 case UIT_BOOLEAN: 764 return uis->_.boolean_data.action_desc; 765 default: 766 return NULL; 767 } 768 } 769 770 const char *UI_get0_result_string(UI_STRING *uis) 771 { 772 if (!uis) 773 return NULL; 774 switch(uis->type) 775 { 776 case UIT_PROMPT: 777 case UIT_VERIFY: 778 return uis->result_buf; 779 default: 780 return NULL; 781 } 782 } 783 784 const char *UI_get0_test_string(UI_STRING *uis) 785 { 786 if (!uis) 787 return NULL; 788 switch(uis->type) 789 { 790 case UIT_VERIFY: 791 return uis->_.string_data.test_buf; 792 default: 793 return NULL; 794 } 795 } 796 797 int UI_get_result_minsize(UI_STRING *uis) 798 { 799 if (!uis) 800 return -1; 801 switch(uis->type) 802 { 803 case UIT_PROMPT: 804 case UIT_VERIFY: 805 return uis->_.string_data.result_minsize; 806 default: 807 return -1; 808 } 809 } 810 811 int UI_get_result_maxsize(UI_STRING *uis) 812 { 813 if (!uis) 814 return -1; 815 switch(uis->type) 816 { 817 case UIT_PROMPT: 818 case UIT_VERIFY: 819 return uis->_.string_data.result_maxsize; 820 default: 821 return -1; 822 } 823 } 824 825 int UI_set_result(UI *ui, UI_STRING *uis, const char *result) 826 { 827 int l = strlen(result); 828 829 ui->flags &= ~UI_FLAG_REDOABLE; 830 831 if (!uis) 832 return -1; 833 switch (uis->type) 834 { 835 case UIT_PROMPT: 836 case UIT_VERIFY: 837 { 838 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize)+1]; 839 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize)+1]; 840 841 BIO_snprintf(number1, sizeof(number1), "%d", 842 uis->_.string_data.result_minsize); 843 BIO_snprintf(number2, sizeof(number2), "%d", 844 uis->_.string_data.result_maxsize); 845 846 if (l < uis->_.string_data.result_minsize) 847 { 848 ui->flags |= UI_FLAG_REDOABLE; 849 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL); 850 ERR_add_error_data(5,"You must type in ", 851 number1," to ",number2," characters"); 852 return -1; 853 } 854 if (l > uis->_.string_data.result_maxsize) 855 { 856 ui->flags |= UI_FLAG_REDOABLE; 857 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE); 858 ERR_add_error_data(5,"You must type in ", 859 number1," to ",number2," characters"); 860 return -1; 861 } 862 } 863 864 if (!uis->result_buf) 865 { 866 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); 867 return -1; 868 } 869 870 BUF_strlcpy(uis->result_buf, result, 871 uis->_.string_data.result_maxsize + 1); 872 break; 873 case UIT_BOOLEAN: 874 { 875 const char *p; 876 877 if (!uis->result_buf) 878 { 879 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); 880 return -1; 881 } 882 883 uis->result_buf[0] = '\0'; 884 for(p = result; *p; p++) 885 { 886 if (strchr(uis->_.boolean_data.ok_chars, *p)) 887 { 888 uis->result_buf[0] = 889 uis->_.boolean_data.ok_chars[0]; 890 break; 891 } 892 if (strchr(uis->_.boolean_data.cancel_chars, *p)) 893 { 894 uis->result_buf[0] = 895 uis->_.boolean_data.cancel_chars[0]; 896 break; 897 } 898 } 899 default: 900 break; 901 } 902 } 903 return 0; 904 } 905