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