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