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