VirtualBox

source: vbox/trunk/src/libs/openssl-1.1.0g/crypto/ui/ui_openssl.c@ 69890

Last change on this file since 69890 was 69890, checked in by vboxsync, 7 years ago

Added OpenSSL 1.1.0g with unneeded files removed, otherwise unmodified.
bugref:8070: src/libs maintenance

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette