1 /* 2 * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "e_os.h" 11 #include <openssl/e_os2.h> 12 #include <openssl/err.h> 13 #include <openssl/ui.h> 14 15 #ifndef OPENSSL_NO_UI_CONSOLE 16 /* 17 * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc 18 * [maybe others?], because it masks interfaces not discussed in standard, 19 * sigaction and fileno included. -pedantic would be more appropriate for the 20 * intended purposes, but we can't prevent users from adding -ansi. 21 */ 22 # if defined(OPENSSL_SYS_VXWORKS) 23 # include <sys/types.h> 24 # endif 25 26 # if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) 27 # ifndef _POSIX_C_SOURCE 28 # define _POSIX_C_SOURCE 2 29 # endif 30 # endif 31 # include <signal.h> 32 # include <stdio.h> 33 # include <string.h> 34 # include <errno.h> 35 36 # if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) 37 # ifdef OPENSSL_UNISTD 38 # include OPENSSL_UNISTD 39 # else 40 # include <unistd.h> 41 # endif 42 /* 43 * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX 44 * system and have sigaction and termios. 45 */ 46 # if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L 47 48 # define SIGACTION 49 # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) 50 # define TERMIOS 51 # endif 52 53 # endif 54 # endif 55 56 # include "ui_locl.h" 57 # include "internal/cryptlib.h" 58 59 # ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */ 60 # include <starlet.h> 61 # ifdef __DECC 62 # pragma message disable DOLLARID 63 # endif 64 # endif 65 66 # ifdef WIN_CONSOLE_BUG 67 # include <windows.h> 68 # ifndef OPENSSL_SYS_WINCE 69 # include <wincon.h> 70 # endif 71 # endif 72 73 /* 74 * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS, 75 * MSDOS, WIN32 Console and SGTTY. 76 * 77 * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will 78 * remain respected. Otherwise, we default to TERMIOS except for a few 79 * systems that require something different. 80 * 81 * Note: we do not use SGTTY unless it's defined by the configuration. We 82 * may eventually opt to remove it's use entirely. 83 */ 84 85 # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) 86 87 # if defined(_LIBC) 88 # undef TERMIOS 89 # define TERMIO 90 # undef SGTTY 91 /* 92 * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms. 93 */ 94 # elif !defined(OPENSSL_SYS_VMS) \ 95 && !defined(OPENSSL_SYS_MSDOS) \ 96 && !defined(OPENSSL_SYS_VXWORKS) 97 # define TERMIOS 98 # undef TERMIO 99 # undef SGTTY 100 # endif 101 102 # endif 103 104 # ifdef TERMIOS 105 # include <termios.h> 106 # define TTY_STRUCT struct termios 107 # define TTY_FLAGS c_lflag 108 # define TTY_get(tty,data) tcgetattr(tty,data) 109 # define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) 110 # endif 111 112 # ifdef TERMIO 113 # include <termio.h> 114 # define TTY_STRUCT struct termio 115 # define TTY_FLAGS c_lflag 116 # define TTY_get(tty,data) ioctl(tty,TCGETA,data) 117 # define TTY_set(tty,data) ioctl(tty,TCSETA,data) 118 # endif 119 120 # ifdef SGTTY 121 # include <sgtty.h> 122 # define TTY_STRUCT struct sgttyb 123 # define TTY_FLAGS sg_flags 124 # define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) 125 # define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) 126 # endif 127 128 # if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) 129 # include <sys/ioctl.h> 130 # endif 131 132 # ifdef OPENSSL_SYS_MSDOS 133 # include <conio.h> 134 # endif 135 136 # ifdef OPENSSL_SYS_VMS 137 # include <ssdef.h> 138 # include <iodef.h> 139 # include <ttdef.h> 140 # include <descrip.h> 141 struct IOSB { 142 short iosb$w_value; 143 short iosb$w_count; 144 long iosb$l_info; 145 }; 146 # endif 147 148 # ifndef NX509_SIG 149 # define NX509_SIG 32 150 # endif 151 152 /* Define globals. They are protected by a lock */ 153 # ifdef SIGACTION 154 static struct sigaction savsig[NX509_SIG]; 155 # else 156 static void (*savsig[NX509_SIG]) (int); 157 # endif 158 159 # ifdef OPENSSL_SYS_VMS 160 static struct IOSB iosb; 161 static $DESCRIPTOR(terminal, "TT"); 162 static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this 163 * will always suffice for the actual 164 * structures? */ 165 static long status; 166 static unsigned short channel = 0; 167 # elif defined(_WIN32) && !defined(_WIN32_WCE) 168 static DWORD tty_orig, tty_new; 169 # else 170 # if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) 171 static TTY_STRUCT tty_orig, tty_new; 172 # endif 173 # endif 174 static FILE *tty_in, *tty_out; 175 static int is_a_tty; 176 177 /* Declare static functions */ 178 # if !defined(OPENSSL_SYS_WINCE) 179 static int read_till_nl(FILE *); 180 static void recsig(int); 181 static void pushsig(void); 182 static void popsig(void); 183 # endif 184 # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) 185 static int noecho_fgets(char *buf, int size, FILE *tty); 186 # endif 187 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl); 188 189 static int read_string(UI *ui, UI_STRING *uis); 190 static int write_string(UI *ui, UI_STRING *uis); 191 192 static int open_console(UI *ui); 193 static int echo_console(UI *ui); 194 static int noecho_console(UI *ui); 195 static int close_console(UI *ui); 196 197 /* 198 * The following function makes sure that info and error strings are printed 199 * before any prompt. 200 */ 201 static int write_string(UI *ui, UI_STRING *uis) 202 { 203 switch (UI_get_string_type(uis)) { 204 case UIT_ERROR: 205 case UIT_INFO: 206 fputs(UI_get0_output_string(uis), tty_out); 207 fflush(tty_out); 208 break; 209 case UIT_NONE: 210 case UIT_PROMPT: 211 case UIT_VERIFY: 212 case UIT_BOOLEAN: 213 break; 214 } 215 return 1; 216 } 217 218 static int read_string(UI *ui, UI_STRING *uis) 219 { 220 int ok = 0; 221 222 switch (UI_get_string_type(uis)) { 223 case UIT_BOOLEAN: 224 fputs(UI_get0_output_string(uis), tty_out); 225 fputs(UI_get0_action_string(uis), tty_out); 226 fflush(tty_out); 227 return read_string_inner(ui, uis, 228 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 229 0); 230 case UIT_PROMPT: 231 fputs(UI_get0_output_string(uis), tty_out); 232 fflush(tty_out); 233 return read_string_inner(ui, uis, 234 UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 235 1); 236 case UIT_VERIFY: 237 fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis)); 238 fflush(tty_out); 239 if ((ok = read_string_inner(ui, uis, 240 UI_get_input_flags(uis) & 241 UI_INPUT_FLAG_ECHO, 1)) <= 0) 242 return ok; 243 if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) { 244 fprintf(tty_out, "Verify failure\n"); 245 fflush(tty_out); 246 return 0; 247 } 248 break; 249 case UIT_NONE: 250 case UIT_INFO: 251 case UIT_ERROR: 252 break; 253 } 254 return 1; 255 } 256 257 # if !defined(OPENSSL_SYS_WINCE) 258 /* Internal functions to read a string without echoing */ 259 static int read_till_nl(FILE *in) 260 { 261 # define SIZE 4 262 char buf[SIZE + 1]; 263 264 do { 265 if (!fgets(buf, SIZE, in)) 266 return 0; 267 } while (strchr(buf, '\n') == NULL); 268 return 1; 269 } 270 271 static volatile sig_atomic_t intr_signal; 272 # endif 273 274 static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) 275 { 276 static int ps; 277 int ok; 278 char result[BUFSIZ]; 279 int maxsize = BUFSIZ - 1; 280 # if !defined(OPENSSL_SYS_WINCE) 281 char *p = NULL; 282 int echo_eol = !echo; 283 284 intr_signal = 0; 285 ok = 0; 286 ps = 0; 287 288 pushsig(); 289 ps = 1; 290 291 if (!echo && !noecho_console(ui)) 292 goto error; 293 ps = 2; 294 295 result[0] = '\0'; 296 # if defined(_WIN32) 297 if (is_a_tty) { 298 DWORD numread; 299 # if defined(CP_UTF8) 300 if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) { 301 WCHAR wresult[BUFSIZ]; 302 303 if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), 304 wresult, maxsize, &numread, NULL)) { 305 if (numread >= 2 && 306 wresult[numread-2] == L'\r' && 307 wresult[numread-1] == L'\n') { 308 wresult[numread-2] = L'\n'; 309 numread--; 310 } 311 wresult[numread] = '\0'; 312 if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1, 313 result, sizeof(result), NULL, 0) > 0) 314 p = result; 315 316 OPENSSL_cleanse(wresult, sizeof(wresult)); 317 } 318 } else 319 # endif 320 if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), 321 result, maxsize, &numread, NULL)) { 322 if (numread >= 2 && 323 result[numread-2] == '\r' && result[numread-1] == '\n') { 324 result[numread-2] = '\n'; 325 numread--; 326 } 327 result[numread] = '\0'; 328 p = result; 329 } 330 } else 331 # elif defined(OPENSSL_SYS_MSDOS) 332 if (!echo) { 333 noecho_fgets(result, maxsize, tty_in); 334 p = result; /* FIXME: noecho_fgets doesn't return errors */ 335 } else 336 # endif 337 p = fgets(result, maxsize, tty_in); 338 if (p == NULL) 339 goto error; 340 if (feof(tty_in)) 341 goto error; 342 if (ferror(tty_in)) 343 goto error; 344 if ((p = (char *)strchr(result, '\n')) != NULL) { 345 if (strip_nl) 346 *p = '\0'; 347 } else if (!read_till_nl(tty_in)) 348 goto error; 349 if (UI_set_result(ui, uis, result) >= 0) 350 ok = 1; 351 352 error: 353 if (intr_signal == SIGINT) 354 ok = -1; 355 if (echo_eol) 356 fprintf(tty_out, "\n"); 357 if (ps >= 2 && !echo && !echo_console(ui)) 358 ok = 0; 359 360 if (ps >= 1) 361 popsig(); 362 # else 363 ok = 1; 364 # endif 365 366 OPENSSL_cleanse(result, BUFSIZ); 367 return ok; 368 } 369 370 /* Internal functions to open, handle and close a channel to the console. */ 371 static int open_console(UI *ui) 372 { 373 CRYPTO_THREAD_write_lock(ui->lock); 374 is_a_tty = 1; 375 376 # if defined(OPENSSL_SYS_VXWORKS) 377 tty_in = stdin; 378 tty_out = stderr; 379 # elif defined(_WIN32) && !defined(_WIN32_WCE) 380 if ((tty_out = fopen("conout$", "w")) == NULL) 381 tty_out = stderr; 382 383 if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) { 384 tty_in = stdin; 385 } else { 386 is_a_tty = 0; 387 if ((tty_in = fopen("conin$", "r")) == NULL) 388 tty_in = stdin; 389 } 390 # else 391 # ifdef OPENSSL_SYS_MSDOS 392 # define DEV_TTY "con" 393 # else 394 # define DEV_TTY "/dev/tty" 395 # endif 396 if ((tty_in = fopen(DEV_TTY, "r")) == NULL) 397 tty_in = stdin; 398 if ((tty_out = fopen(DEV_TTY, "w")) == NULL) 399 tty_out = stderr; 400 # endif 401 402 # if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) 403 if (TTY_get(fileno(tty_in), &tty_orig) == -1) { 404 # ifdef ENOTTY 405 if (errno == ENOTTY) 406 is_a_tty = 0; 407 else 408 # endif 409 # ifdef EINVAL 410 /* 411 * Ariel Glenn reports that solaris can return EINVAL instead. 412 * This should be ok 413 */ 414 if (errno == EINVAL) 415 is_a_tty = 0; 416 else 417 # endif 418 # ifdef ENXIO 419 /* 420 * Solaris can return ENXIO. 421 * This should be ok 422 */ 423 if (errno == ENXIO) 424 is_a_tty = 0; 425 else 426 # endif 427 # ifdef EIO 428 /* 429 * Linux can return EIO. 430 * This should be ok 431 */ 432 if (errno == EIO) 433 is_a_tty = 0; 434 else 435 # endif 436 # ifdef ENODEV 437 /* 438 * MacOS X returns ENODEV (Operation not supported by device), 439 * which seems appropriate. 440 */ 441 if (errno == ENODEV) 442 is_a_tty = 0; 443 else 444 # endif 445 { 446 char tmp_num[10]; 447 BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno); 448 UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE); 449 ERR_add_error_data(2, "errno=", tmp_num); 450 451 return 0; 452 } 453 } 454 # endif 455 # ifdef OPENSSL_SYS_VMS 456 status = sys$assign(&terminal, &channel, 0, 0); 457 458 /* if there isn't a TT device, something is very wrong */ 459 if (status != SS$_NORMAL) { 460 char tmp_num[12]; 461 462 BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); 463 UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR); 464 ERR_add_error_data(2, "status=", tmp_num); 465 return 0; 466 } 467 468 status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, 469 0, 0, 0, 0); 470 471 /* If IO$_SENSEMODE doesn't work, this is not a terminal device */ 472 if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) 473 is_a_tty = 0; 474 # endif 475 return 1; 476 } 477 478 static int noecho_console(UI *ui) 479 { 480 # ifdef TTY_FLAGS 481 memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); 482 tty_new.TTY_FLAGS &= ~ECHO; 483 # endif 484 485 # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) 486 if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) 487 return 0; 488 # endif 489 # ifdef OPENSSL_SYS_VMS 490 if (is_a_tty) { 491 tty_new[0] = tty_orig[0]; 492 tty_new[1] = tty_orig[1] | TT$M_NOECHO; 493 tty_new[2] = tty_orig[2]; 494 status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 495 0, 0, 0, 0); 496 if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { 497 char tmp_num[2][12]; 498 499 BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", 500 status); 501 BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", 502 iosb.iosb$w_value); 503 UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR); 504 ERR_add_error_data(5, "status=", tmp_num[0], 505 ",", "iosb.iosb$w_value=", tmp_num[1]); 506 return 0; 507 } 508 } 509 # endif 510 # if defined(_WIN32) && !defined(_WIN32_WCE) 511 if (is_a_tty) { 512 tty_new = tty_orig; 513 tty_new &= ~ENABLE_ECHO_INPUT; 514 SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); 515 } 516 # endif 517 return 1; 518 } 519 520 static int echo_console(UI *ui) 521 { 522 # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) 523 memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); 524 if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) 525 return 0; 526 # endif 527 # ifdef OPENSSL_SYS_VMS 528 if (is_a_tty) { 529 tty_new[0] = tty_orig[0]; 530 tty_new[1] = tty_orig[1]; 531 tty_new[2] = tty_orig[2]; 532 status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 533 0, 0, 0, 0); 534 if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { 535 char tmp_num[2][12]; 536 537 BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", 538 status); 539 BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", 540 iosb.iosb$w_value); 541 UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR); 542 ERR_add_error_data(5, "status=", tmp_num[0], 543 ",", "iosb.iosb$w_value=", tmp_num[1]); 544 return 0; 545 } 546 } 547 # endif 548 # if defined(_WIN32) && !defined(_WIN32_WCE) 549 if (is_a_tty) { 550 tty_new = tty_orig; 551 SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); 552 } 553 # endif 554 return 1; 555 } 556 557 static int close_console(UI *ui) 558 { 559 if (tty_in != stdin) 560 fclose(tty_in); 561 if (tty_out != stderr) 562 fclose(tty_out); 563 # ifdef OPENSSL_SYS_VMS 564 status = sys$dassgn(channel); 565 if (status != SS$_NORMAL) { 566 char tmp_num[12]; 567 568 BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); 569 UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR); 570 ERR_add_error_data(2, "status=", tmp_num); 571 return 0; 572 } 573 # endif 574 CRYPTO_THREAD_unlock(ui->lock); 575 576 return 1; 577 } 578 579 # if !defined(OPENSSL_SYS_WINCE) 580 /* Internal functions to handle signals and act on them */ 581 static void pushsig(void) 582 { 583 # ifndef OPENSSL_SYS_WIN32 584 int i; 585 # endif 586 # ifdef SIGACTION 587 struct sigaction sa; 588 589 memset(&sa, 0, sizeof(sa)); 590 sa.sa_handler = recsig; 591 # endif 592 593 # ifdef OPENSSL_SYS_WIN32 594 savsig[SIGABRT] = signal(SIGABRT, recsig); 595 savsig[SIGFPE] = signal(SIGFPE, recsig); 596 savsig[SIGILL] = signal(SIGILL, recsig); 597 savsig[SIGINT] = signal(SIGINT, recsig); 598 savsig[SIGSEGV] = signal(SIGSEGV, recsig); 599 savsig[SIGTERM] = signal(SIGTERM, recsig); 600 # else 601 for (i = 1; i < NX509_SIG; i++) { 602 # ifdef SIGUSR1 603 if (i == SIGUSR1) 604 continue; 605 # endif 606 # ifdef SIGUSR2 607 if (i == SIGUSR2) 608 continue; 609 # endif 610 # ifdef SIGKILL 611 if (i == SIGKILL) /* We can't make any action on that. */ 612 continue; 613 # endif 614 # ifdef SIGACTION 615 sigaction(i, &sa, &savsig[i]); 616 # else 617 savsig[i] = signal(i, recsig); 618 # endif 619 } 620 # endif 621 622 # ifdef SIGWINCH 623 signal(SIGWINCH, SIG_DFL); 624 # endif 625 } 626 627 static void popsig(void) 628 { 629 # ifdef OPENSSL_SYS_WIN32 630 signal(SIGABRT, savsig[SIGABRT]); 631 signal(SIGFPE, savsig[SIGFPE]); 632 signal(SIGILL, savsig[SIGILL]); 633 signal(SIGINT, savsig[SIGINT]); 634 signal(SIGSEGV, savsig[SIGSEGV]); 635 signal(SIGTERM, savsig[SIGTERM]); 636 # else 637 int i; 638 for (i = 1; i < NX509_SIG; i++) { 639 # ifdef SIGUSR1 640 if (i == SIGUSR1) 641 continue; 642 # endif 643 # ifdef SIGUSR2 644 if (i == SIGUSR2) 645 continue; 646 # endif 647 # ifdef SIGACTION 648 sigaction(i, &savsig[i], NULL); 649 # else 650 signal(i, savsig[i]); 651 # endif 652 } 653 # endif 654 } 655 656 static void recsig(int i) 657 { 658 intr_signal = i; 659 } 660 # endif 661 662 /* Internal functions specific for Windows */ 663 # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) 664 static int noecho_fgets(char *buf, int size, FILE *tty) 665 { 666 int i; 667 char *p; 668 669 p = buf; 670 for (;;) { 671 if (size == 0) { 672 *p = '\0'; 673 break; 674 } 675 size--; 676 # if defined(_WIN32) 677 i = _getch(); 678 # else 679 i = getch(); 680 # endif 681 if (i == '\r') 682 i = '\n'; 683 *(p++) = i; 684 if (i == '\n') { 685 *p = '\0'; 686 break; 687 } 688 } 689 # ifdef WIN_CONSOLE_BUG 690 /* 691 * Win95 has several evil console bugs: one of these is that the last 692 * character read using getch() is passed to the next read: this is 693 * usually a CR so this can be trouble. No STDIO fix seems to work but 694 * flushing the console appears to do the trick. 695 */ 696 { 697 HANDLE inh; 698 inh = GetStdHandle(STD_INPUT_HANDLE); 699 FlushConsoleInputBuffer(inh); 700 } 701 # endif 702 return strlen(buf); 703 } 704 # endif 705 706 static UI_METHOD ui_openssl = { 707 "OpenSSL default user interface", 708 open_console, 709 write_string, 710 NULL, /* No flusher is needed for command lines */ 711 read_string, 712 close_console, 713 NULL 714 }; 715 716 /* The method with all the built-in console thingies */ 717 UI_METHOD *UI_OpenSSL(void) 718 { 719 return &ui_openssl; 720 } 721 722 static const UI_METHOD *default_UI_meth = &ui_openssl; 723 724 #else 725 726 static const UI_METHOD *default_UI_meth = NULL; 727 728 #endif 729 730 void UI_set_default_method(const UI_METHOD *meth) 731 { 732 default_UI_meth = meth; 733 } 734 735 const UI_METHOD *UI_get_default_method(void) 736 { 737 return default_UI_meth; 738 } 739