xref: /onnv-gate/usr/src/common/openssl/crypto/ui/ui_openssl.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */
2*0Sstevel@tonic-gate /* Written by Richard Levitte (richard@levitte.org) and others
3*0Sstevel@tonic-gate  * for the OpenSSL project 2001.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate /* ====================================================================
6*0Sstevel@tonic-gate  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
7*0Sstevel@tonic-gate  *
8*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
9*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
10*0Sstevel@tonic-gate  * are met:
11*0Sstevel@tonic-gate  *
12*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
13*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
14*0Sstevel@tonic-gate  *
15*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
16*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
17*0Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
18*0Sstevel@tonic-gate  *    distribution.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
21*0Sstevel@tonic-gate  *    software must display the following acknowledgment:
22*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
23*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26*0Sstevel@tonic-gate  *    endorse or promote products derived from this software without
27*0Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
28*0Sstevel@tonic-gate  *    openssl-core@openssl.org.
29*0Sstevel@tonic-gate  *
30*0Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
31*0Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
32*0Sstevel@tonic-gate  *    permission of the OpenSSL Project.
33*0Sstevel@tonic-gate  *
34*0Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
35*0Sstevel@tonic-gate  *    acknowledgment:
36*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
37*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38*0Sstevel@tonic-gate  *
39*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40*0Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42*0Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43*0Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44*0Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45*0Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46*0Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48*0Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49*0Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50*0Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
51*0Sstevel@tonic-gate  * ====================================================================
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
54*0Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
55*0Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /* The lowest level part of this file was previously in crypto/des/read_pwd.c,
60*0Sstevel@tonic-gate  * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
61*0Sstevel@tonic-gate  * All rights reserved.
62*0Sstevel@tonic-gate  *
63*0Sstevel@tonic-gate  * This package is an SSL implementation written
64*0Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
65*0Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
66*0Sstevel@tonic-gate  *
67*0Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
68*0Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
69*0Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
70*0Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
71*0Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
72*0Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
73*0Sstevel@tonic-gate  *
74*0Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
75*0Sstevel@tonic-gate  * the code are not to be removed.
76*0Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
77*0Sstevel@tonic-gate  * as the author of the parts of the library used.
78*0Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
79*0Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
80*0Sstevel@tonic-gate  *
81*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
82*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
83*0Sstevel@tonic-gate  * are met:
84*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
85*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
86*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
87*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
88*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
89*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
90*0Sstevel@tonic-gate  *    must display the following acknowledgement:
91*0Sstevel@tonic-gate  *    "This product includes cryptographic software written by
92*0Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
93*0Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
94*0Sstevel@tonic-gate  *    being used are not cryptographic related :-).
95*0Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
96*0Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
97*0Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
98*0Sstevel@tonic-gate  *
99*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
100*0Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
101*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
102*0Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
103*0Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
104*0Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
105*0Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
106*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
107*0Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
108*0Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
109*0Sstevel@tonic-gate  * SUCH DAMAGE.
110*0Sstevel@tonic-gate  *
111*0Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
112*0Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
113*0Sstevel@tonic-gate  * copied and put under another distribution licence
114*0Sstevel@tonic-gate  * [including the GNU Public Licence.]
115*0Sstevel@tonic-gate  */
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate #include <openssl/e_os2.h>
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS)
121*0Sstevel@tonic-gate # ifdef OPENSSL_UNISTD
122*0Sstevel@tonic-gate #  include OPENSSL_UNISTD
123*0Sstevel@tonic-gate # else
124*0Sstevel@tonic-gate #  include <unistd.h>
125*0Sstevel@tonic-gate # endif
126*0Sstevel@tonic-gate /* If unistd.h defines _POSIX_VERSION, we conclude that we
127*0Sstevel@tonic-gate  * are on a POSIX system and have sigaction and termios. */
128*0Sstevel@tonic-gate # if defined(_POSIX_VERSION)
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate #  define SIGACTION
131*0Sstevel@tonic-gate #  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
132*0Sstevel@tonic-gate #   define TERMIOS
133*0Sstevel@tonic-gate #  endif
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate # endif
136*0Sstevel@tonic-gate #endif
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate #ifdef WIN16TTY
139*0Sstevel@tonic-gate # undef OPENSSL_SYS_WIN16
140*0Sstevel@tonic-gate # undef WIN16
141*0Sstevel@tonic-gate # undef _WINDOWS
142*0Sstevel@tonic-gate # include <graph.h>
143*0Sstevel@tonic-gate #endif
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate /* 06-Apr-92 Luke Brennan    Support for VMS */
146*0Sstevel@tonic-gate #include "ui_locl.h"
147*0Sstevel@tonic-gate #include "cryptlib.h"
148*0Sstevel@tonic-gate #include <signal.h>
149*0Sstevel@tonic-gate #include <stdio.h>
150*0Sstevel@tonic-gate #include <string.h>
151*0Sstevel@tonic-gate #include <errno.h>
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS		/* prototypes for sys$whatever */
154*0Sstevel@tonic-gate # include <starlet.h>
155*0Sstevel@tonic-gate # ifdef __DECC
156*0Sstevel@tonic-gate #  pragma message disable DOLLARID
157*0Sstevel@tonic-gate # endif
158*0Sstevel@tonic-gate #endif
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate #ifdef WIN_CONSOLE_BUG
161*0Sstevel@tonic-gate # include <windows.h>
162*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINCE
163*0Sstevel@tonic-gate # include <wincon.h>
164*0Sstevel@tonic-gate #endif
165*0Sstevel@tonic-gate #endif
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate /* There are 5 types of terminal interface supported,
169*0Sstevel@tonic-gate  * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
170*0Sstevel@tonic-gate  */
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate #if defined(__sgi) && !defined(TERMIOS)
173*0Sstevel@tonic-gate # define TERMIOS
174*0Sstevel@tonic-gate # undef  TERMIO
175*0Sstevel@tonic-gate # undef  SGTTY
176*0Sstevel@tonic-gate #endif
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate #if defined(linux) && !defined(TERMIO)
179*0Sstevel@tonic-gate # undef  TERMIOS
180*0Sstevel@tonic-gate # define TERMIO
181*0Sstevel@tonic-gate # undef  SGTTY
182*0Sstevel@tonic-gate #endif
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate #ifdef _LIBC
185*0Sstevel@tonic-gate # undef  TERMIOS
186*0Sstevel@tonic-gate # define TERMIO
187*0Sstevel@tonic-gate # undef  SGTTY
188*0Sstevel@tonic-gate #endif
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate #if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(MAC_OS_GUSI_SOURCE)
191*0Sstevel@tonic-gate # undef  TERMIOS
192*0Sstevel@tonic-gate # undef  TERMIO
193*0Sstevel@tonic-gate # define SGTTY
194*0Sstevel@tonic-gate #endif
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_VXWORKS)
197*0Sstevel@tonic-gate #undef TERMIOS
198*0Sstevel@tonic-gate #undef TERMIO
199*0Sstevel@tonic-gate #undef SGTTY
200*0Sstevel@tonic-gate #endif
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate #ifdef TERMIOS
203*0Sstevel@tonic-gate # include <termios.h>
204*0Sstevel@tonic-gate # define TTY_STRUCT		struct termios
205*0Sstevel@tonic-gate # define TTY_FLAGS		c_lflag
206*0Sstevel@tonic-gate # define TTY_get(tty,data)	tcgetattr(tty,data)
207*0Sstevel@tonic-gate # define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
208*0Sstevel@tonic-gate #endif
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate #ifdef TERMIO
211*0Sstevel@tonic-gate # include <termio.h>
212*0Sstevel@tonic-gate # define TTY_STRUCT		struct termio
213*0Sstevel@tonic-gate # define TTY_FLAGS		c_lflag
214*0Sstevel@tonic-gate # define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
215*0Sstevel@tonic-gate # define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
216*0Sstevel@tonic-gate #endif
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate #ifdef SGTTY
219*0Sstevel@tonic-gate # include <sgtty.h>
220*0Sstevel@tonic-gate # define TTY_STRUCT		struct sgttyb
221*0Sstevel@tonic-gate # define TTY_FLAGS		sg_flags
222*0Sstevel@tonic-gate # define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
223*0Sstevel@tonic-gate # define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
224*0Sstevel@tonic-gate #endif
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate #if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(OPENSSL_SYS_SUNOS)
227*0Sstevel@tonic-gate # include <sys/ioctl.h>
228*0Sstevel@tonic-gate #endif
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_MSDOS
231*0Sstevel@tonic-gate # include <conio.h>
232*0Sstevel@tonic-gate #endif
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
235*0Sstevel@tonic-gate # include <ssdef.h>
236*0Sstevel@tonic-gate # include <iodef.h>
237*0Sstevel@tonic-gate # include <ttdef.h>
238*0Sstevel@tonic-gate # include <descrip.h>
239*0Sstevel@tonic-gate struct IOSB {
240*0Sstevel@tonic-gate 	short iosb$w_value;
241*0Sstevel@tonic-gate 	short iosb$w_count;
242*0Sstevel@tonic-gate 	long  iosb$l_info;
243*0Sstevel@tonic-gate 	};
244*0Sstevel@tonic-gate #endif
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_SUNOS
247*0Sstevel@tonic-gate 	typedef int sig_atomic_t;
248*0Sstevel@tonic-gate #endif
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE)
251*0Sstevel@tonic-gate /*
252*0Sstevel@tonic-gate  * This one needs work. As a matter of fact the code is unoperational
253*0Sstevel@tonic-gate  * and this is only a trick to get it compiled.
254*0Sstevel@tonic-gate  *					<appro@fy.chalmers.se>
255*0Sstevel@tonic-gate  */
256*0Sstevel@tonic-gate # define TTY_STRUCT int
257*0Sstevel@tonic-gate #endif
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate #ifndef NX509_SIG
260*0Sstevel@tonic-gate # define NX509_SIG 32
261*0Sstevel@tonic-gate #endif
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate /* Define globals.  They are protected by a lock */
265*0Sstevel@tonic-gate #ifdef SIGACTION
266*0Sstevel@tonic-gate static struct sigaction savsig[NX509_SIG];
267*0Sstevel@tonic-gate #else
268*0Sstevel@tonic-gate static void (*savsig[NX509_SIG])(int );
269*0Sstevel@tonic-gate #endif
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
272*0Sstevel@tonic-gate static struct IOSB iosb;
273*0Sstevel@tonic-gate static $DESCRIPTOR(terminal,"TT");
274*0Sstevel@tonic-gate static long tty_orig[3], tty_new[3]; /* XXX   Is there any guarantee that this will always suffice for the actual structures? */
275*0Sstevel@tonic-gate static long status;
276*0Sstevel@tonic-gate static unsigned short channel = 0;
277*0Sstevel@tonic-gate #else
278*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
279*0Sstevel@tonic-gate static TTY_STRUCT tty_orig,tty_new;
280*0Sstevel@tonic-gate #endif
281*0Sstevel@tonic-gate #endif
282*0Sstevel@tonic-gate static FILE *tty_in, *tty_out;
283*0Sstevel@tonic-gate static int is_a_tty;
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate /* Declare static functions */
286*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
287*0Sstevel@tonic-gate static void read_till_nl(FILE *);
288*0Sstevel@tonic-gate static void recsig(int);
289*0Sstevel@tonic-gate static void pushsig(void);
290*0Sstevel@tonic-gate static void popsig(void);
291*0Sstevel@tonic-gate #endif
292*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
293*0Sstevel@tonic-gate static int noecho_fgets(char *buf, int size, FILE *tty);
294*0Sstevel@tonic-gate #endif
295*0Sstevel@tonic-gate static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate static int read_string(UI *ui, UI_STRING *uis);
298*0Sstevel@tonic-gate static int write_string(UI *ui, UI_STRING *uis);
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate static int open_console(UI *ui);
301*0Sstevel@tonic-gate static int echo_console(UI *ui);
302*0Sstevel@tonic-gate static int noecho_console(UI *ui);
303*0Sstevel@tonic-gate static int close_console(UI *ui);
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate static UI_METHOD ui_openssl =
306*0Sstevel@tonic-gate 	{
307*0Sstevel@tonic-gate 	"OpenSSL default user interface",
308*0Sstevel@tonic-gate 	open_console,
309*0Sstevel@tonic-gate 	write_string,
310*0Sstevel@tonic-gate 	NULL,			/* No flusher is needed for command lines */
311*0Sstevel@tonic-gate 	read_string,
312*0Sstevel@tonic-gate 	close_console,
313*0Sstevel@tonic-gate 	NULL
314*0Sstevel@tonic-gate 	};
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate /* The method with all the built-in thingies */
317*0Sstevel@tonic-gate UI_METHOD *UI_OpenSSL(void)
318*0Sstevel@tonic-gate 	{
319*0Sstevel@tonic-gate 	return &ui_openssl;
320*0Sstevel@tonic-gate 	}
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate /* The following function makes sure that info and error strings are printed
323*0Sstevel@tonic-gate    before any prompt. */
324*0Sstevel@tonic-gate static int write_string(UI *ui, UI_STRING *uis)
325*0Sstevel@tonic-gate 	{
326*0Sstevel@tonic-gate 	switch (UI_get_string_type(uis))
327*0Sstevel@tonic-gate 		{
328*0Sstevel@tonic-gate 	case UIT_ERROR:
329*0Sstevel@tonic-gate 	case UIT_INFO:
330*0Sstevel@tonic-gate 		fputs(UI_get0_output_string(uis), tty_out);
331*0Sstevel@tonic-gate 		fflush(tty_out);
332*0Sstevel@tonic-gate 		break;
333*0Sstevel@tonic-gate 	default:
334*0Sstevel@tonic-gate 		break;
335*0Sstevel@tonic-gate 		}
336*0Sstevel@tonic-gate 	return 1;
337*0Sstevel@tonic-gate 	}
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate static int read_string(UI *ui, UI_STRING *uis)
340*0Sstevel@tonic-gate 	{
341*0Sstevel@tonic-gate 	int ok = 0;
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	switch (UI_get_string_type(uis))
344*0Sstevel@tonic-gate 		{
345*0Sstevel@tonic-gate 	case UIT_BOOLEAN:
346*0Sstevel@tonic-gate 		fputs(UI_get0_output_string(uis), tty_out);
347*0Sstevel@tonic-gate 		fputs(UI_get0_action_string(uis), tty_out);
348*0Sstevel@tonic-gate 		fflush(tty_out);
349*0Sstevel@tonic-gate 		return read_string_inner(ui, uis,
350*0Sstevel@tonic-gate 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0);
351*0Sstevel@tonic-gate 	case UIT_PROMPT:
352*0Sstevel@tonic-gate 		fputs(UI_get0_output_string(uis), tty_out);
353*0Sstevel@tonic-gate 		fflush(tty_out);
354*0Sstevel@tonic-gate 		return read_string_inner(ui, uis,
355*0Sstevel@tonic-gate 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1);
356*0Sstevel@tonic-gate 	case UIT_VERIFY:
357*0Sstevel@tonic-gate 		fprintf(tty_out,"Verifying - %s",
358*0Sstevel@tonic-gate 			UI_get0_output_string(uis));
359*0Sstevel@tonic-gate 		fflush(tty_out);
360*0Sstevel@tonic-gate 		if ((ok = read_string_inner(ui, uis,
361*0Sstevel@tonic-gate 			UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1)) <= 0)
362*0Sstevel@tonic-gate 			return ok;
363*0Sstevel@tonic-gate 		if (strcmp(UI_get0_result_string(uis),
364*0Sstevel@tonic-gate 			UI_get0_test_string(uis)) != 0)
365*0Sstevel@tonic-gate 			{
366*0Sstevel@tonic-gate 			fprintf(tty_out,"Verify failure\n");
367*0Sstevel@tonic-gate 			fflush(tty_out);
368*0Sstevel@tonic-gate 			return 0;
369*0Sstevel@tonic-gate 			}
370*0Sstevel@tonic-gate 		break;
371*0Sstevel@tonic-gate 	default:
372*0Sstevel@tonic-gate 		break;
373*0Sstevel@tonic-gate 		}
374*0Sstevel@tonic-gate 	return 1;
375*0Sstevel@tonic-gate 	}
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
379*0Sstevel@tonic-gate /* Internal functions to read a string without echoing */
380*0Sstevel@tonic-gate static void read_till_nl(FILE *in)
381*0Sstevel@tonic-gate 	{
382*0Sstevel@tonic-gate #define SIZE 4
383*0Sstevel@tonic-gate 	char buf[SIZE+1];
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 	do	{
386*0Sstevel@tonic-gate 		fgets(buf,SIZE,in);
387*0Sstevel@tonic-gate 		} while (strchr(buf,'\n') == NULL);
388*0Sstevel@tonic-gate 	}
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate static volatile sig_atomic_t intr_signal;
391*0Sstevel@tonic-gate #endif
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
394*0Sstevel@tonic-gate 	{
395*0Sstevel@tonic-gate 	static int ps;
396*0Sstevel@tonic-gate 	int ok;
397*0Sstevel@tonic-gate 	char result[BUFSIZ];
398*0Sstevel@tonic-gate 	int maxsize = BUFSIZ-1;
399*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
400*0Sstevel@tonic-gate 	char *p;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	intr_signal=0;
403*0Sstevel@tonic-gate 	ok=0;
404*0Sstevel@tonic-gate 	ps=0;
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	pushsig();
407*0Sstevel@tonic-gate 	ps=1;
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 	if (!echo && !noecho_console(ui))
410*0Sstevel@tonic-gate 		goto error;
411*0Sstevel@tonic-gate 	ps=2;
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	result[0]='\0';
414*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_MSDOS
415*0Sstevel@tonic-gate 	if (!echo)
416*0Sstevel@tonic-gate 		{
417*0Sstevel@tonic-gate 		noecho_fgets(result,maxsize,tty_in);
418*0Sstevel@tonic-gate 		p=result; /* FIXME: noecho_fgets doesn't return errors */
419*0Sstevel@tonic-gate 		}
420*0Sstevel@tonic-gate 	else
421*0Sstevel@tonic-gate 		p=fgets(result,maxsize,tty_in);
422*0Sstevel@tonic-gate #else
423*0Sstevel@tonic-gate 	p=fgets(result,maxsize,tty_in);
424*0Sstevel@tonic-gate #endif
425*0Sstevel@tonic-gate 	if(!p)
426*0Sstevel@tonic-gate 		goto error;
427*0Sstevel@tonic-gate 	if (feof(tty_in)) goto error;
428*0Sstevel@tonic-gate 	if (ferror(tty_in)) goto error;
429*0Sstevel@tonic-gate 	if ((p=(char *)strchr(result,'\n')) != NULL)
430*0Sstevel@tonic-gate 		{
431*0Sstevel@tonic-gate 		if (strip_nl)
432*0Sstevel@tonic-gate 			*p='\0';
433*0Sstevel@tonic-gate 		}
434*0Sstevel@tonic-gate 	else
435*0Sstevel@tonic-gate 		read_till_nl(tty_in);
436*0Sstevel@tonic-gate 	if (UI_set_result(ui, uis, result) >= 0)
437*0Sstevel@tonic-gate 		ok=1;
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate error:
440*0Sstevel@tonic-gate 	if (intr_signal == SIGINT)
441*0Sstevel@tonic-gate 		ok=-1;
442*0Sstevel@tonic-gate 	if (!echo) fprintf(tty_out,"\n");
443*0Sstevel@tonic-gate 	if (ps >= 2 && !echo && !echo_console(ui))
444*0Sstevel@tonic-gate 		ok=0;
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	if (ps >= 1)
447*0Sstevel@tonic-gate 		popsig();
448*0Sstevel@tonic-gate #else
449*0Sstevel@tonic-gate 	ok=1;
450*0Sstevel@tonic-gate #endif
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	OPENSSL_cleanse(result,BUFSIZ);
453*0Sstevel@tonic-gate 	return ok;
454*0Sstevel@tonic-gate 	}
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate /* Internal functions to open, handle and close a channel to the console.  */
458*0Sstevel@tonic-gate static int open_console(UI *ui)
459*0Sstevel@tonic-gate 	{
460*0Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_UI);
461*0Sstevel@tonic-gate 	is_a_tty = 1;
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VXWORKS)
464*0Sstevel@tonic-gate 	tty_in=stdin;
465*0Sstevel@tonic-gate 	tty_out=stderr;
466*0Sstevel@tonic-gate #else
467*0Sstevel@tonic-gate #  ifdef OPENSSL_SYS_MSDOS
468*0Sstevel@tonic-gate #    define DEV_TTY "con"
469*0Sstevel@tonic-gate #  else
470*0Sstevel@tonic-gate #    define DEV_TTY "/dev/tty"
471*0Sstevel@tonic-gate #  endif
472*0Sstevel@tonic-gate 	if ((tty_in=fopen(DEV_TTY,"r")) == NULL)
473*0Sstevel@tonic-gate 		tty_in=stdin;
474*0Sstevel@tonic-gate 	if ((tty_out=fopen(DEV_TTY,"w")) == NULL)
475*0Sstevel@tonic-gate 		tty_out=stderr;
476*0Sstevel@tonic-gate #endif
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate #if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
479*0Sstevel@tonic-gate 	if (TTY_get(fileno(tty_in),&tty_orig) == -1)
480*0Sstevel@tonic-gate 		{
481*0Sstevel@tonic-gate #ifdef ENOTTY
482*0Sstevel@tonic-gate 		if (errno == ENOTTY)
483*0Sstevel@tonic-gate 			is_a_tty=0;
484*0Sstevel@tonic-gate 		else
485*0Sstevel@tonic-gate #endif
486*0Sstevel@tonic-gate #ifdef EINVAL
487*0Sstevel@tonic-gate 		/* Ariel Glenn ariel@columbia.edu reports that solaris
488*0Sstevel@tonic-gate 		 * can return EINVAL instead.  This should be ok */
489*0Sstevel@tonic-gate 		if (errno == EINVAL)
490*0Sstevel@tonic-gate 			is_a_tty=0;
491*0Sstevel@tonic-gate 		else
492*0Sstevel@tonic-gate #endif
493*0Sstevel@tonic-gate 			return 0;
494*0Sstevel@tonic-gate 		}
495*0Sstevel@tonic-gate #endif
496*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
497*0Sstevel@tonic-gate 	status = sys$assign(&terminal,&channel,0,0);
498*0Sstevel@tonic-gate 	if (status != SS$_NORMAL)
499*0Sstevel@tonic-gate 		return 0;
500*0Sstevel@tonic-gate 	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
501*0Sstevel@tonic-gate 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
502*0Sstevel@tonic-gate 		return 0;
503*0Sstevel@tonic-gate #endif
504*0Sstevel@tonic-gate 	return 1;
505*0Sstevel@tonic-gate 	}
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate static int noecho_console(UI *ui)
508*0Sstevel@tonic-gate 	{
509*0Sstevel@tonic-gate #ifdef TTY_FLAGS
510*0Sstevel@tonic-gate 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
511*0Sstevel@tonic-gate 	tty_new.TTY_FLAGS &= ~ECHO;
512*0Sstevel@tonic-gate #endif
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
515*0Sstevel@tonic-gate 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
516*0Sstevel@tonic-gate 		return 0;
517*0Sstevel@tonic-gate #endif
518*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
519*0Sstevel@tonic-gate 	tty_new[0] = tty_orig[0];
520*0Sstevel@tonic-gate 	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
521*0Sstevel@tonic-gate 	tty_new[2] = tty_orig[2];
522*0Sstevel@tonic-gate 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
523*0Sstevel@tonic-gate 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
524*0Sstevel@tonic-gate 		return 0;
525*0Sstevel@tonic-gate #endif
526*0Sstevel@tonic-gate 	return 1;
527*0Sstevel@tonic-gate 	}
528*0Sstevel@tonic-gate 
529*0Sstevel@tonic-gate static int echo_console(UI *ui)
530*0Sstevel@tonic-gate 	{
531*0Sstevel@tonic-gate #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
532*0Sstevel@tonic-gate 	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
533*0Sstevel@tonic-gate 	tty_new.TTY_FLAGS |= ECHO;
534*0Sstevel@tonic-gate #endif
535*0Sstevel@tonic-gate 
536*0Sstevel@tonic-gate #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
537*0Sstevel@tonic-gate 	if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1))
538*0Sstevel@tonic-gate 		return 0;
539*0Sstevel@tonic-gate #endif
540*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
541*0Sstevel@tonic-gate 	tty_new[0] = tty_orig[0];
542*0Sstevel@tonic-gate 	tty_new[1] = tty_orig[1] & ~TT$M_NOECHO;
543*0Sstevel@tonic-gate 	tty_new[2] = tty_orig[2];
544*0Sstevel@tonic-gate 	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
545*0Sstevel@tonic-gate 	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
546*0Sstevel@tonic-gate 		return 0;
547*0Sstevel@tonic-gate #endif
548*0Sstevel@tonic-gate 	return 1;
549*0Sstevel@tonic-gate 	}
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate static int close_console(UI *ui)
552*0Sstevel@tonic-gate 	{
553*0Sstevel@tonic-gate 	if (tty_in != stdin) fclose(tty_in);
554*0Sstevel@tonic-gate 	if (tty_out != stderr) fclose(tty_out);
555*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
556*0Sstevel@tonic-gate 	status = sys$dassgn(channel);
557*0Sstevel@tonic-gate #endif
558*0Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_UI);
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 	return 1;
561*0Sstevel@tonic-gate 	}
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
565*0Sstevel@tonic-gate /* Internal functions to handle signals and act on them */
566*0Sstevel@tonic-gate static void pushsig(void)
567*0Sstevel@tonic-gate 	{
568*0Sstevel@tonic-gate 	int i;
569*0Sstevel@tonic-gate #ifdef SIGACTION
570*0Sstevel@tonic-gate 	struct sigaction sa;
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 	memset(&sa,0,sizeof sa);
573*0Sstevel@tonic-gate 	sa.sa_handler=recsig;
574*0Sstevel@tonic-gate #endif
575*0Sstevel@tonic-gate 
576*0Sstevel@tonic-gate 	for (i=1; i<NX509_SIG; i++)
577*0Sstevel@tonic-gate 		{
578*0Sstevel@tonic-gate #ifdef SIGUSR1
579*0Sstevel@tonic-gate 		if (i == SIGUSR1)
580*0Sstevel@tonic-gate 			continue;
581*0Sstevel@tonic-gate #endif
582*0Sstevel@tonic-gate #ifdef SIGUSR2
583*0Sstevel@tonic-gate 		if (i == SIGUSR2)
584*0Sstevel@tonic-gate 			continue;
585*0Sstevel@tonic-gate #endif
586*0Sstevel@tonic-gate #ifdef SIGKILL
587*0Sstevel@tonic-gate 		if (i == SIGKILL) /* We can't make any action on that. */
588*0Sstevel@tonic-gate 			continue;
589*0Sstevel@tonic-gate #endif
590*0Sstevel@tonic-gate #ifdef SIGACTION
591*0Sstevel@tonic-gate 		sigaction(i,&sa,&savsig[i]);
592*0Sstevel@tonic-gate #else
593*0Sstevel@tonic-gate 		savsig[i]=signal(i,recsig);
594*0Sstevel@tonic-gate #endif
595*0Sstevel@tonic-gate 		}
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate #ifdef SIGWINCH
598*0Sstevel@tonic-gate 	signal(SIGWINCH,SIG_DFL);
599*0Sstevel@tonic-gate #endif
600*0Sstevel@tonic-gate 	}
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate static void popsig(void)
603*0Sstevel@tonic-gate 	{
604*0Sstevel@tonic-gate 	int i;
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	for (i=1; i<NX509_SIG; i++)
607*0Sstevel@tonic-gate 		{
608*0Sstevel@tonic-gate #ifdef SIGUSR1
609*0Sstevel@tonic-gate 		if (i == SIGUSR1)
610*0Sstevel@tonic-gate 			continue;
611*0Sstevel@tonic-gate #endif
612*0Sstevel@tonic-gate #ifdef SIGUSR2
613*0Sstevel@tonic-gate 		if (i == SIGUSR2)
614*0Sstevel@tonic-gate 			continue;
615*0Sstevel@tonic-gate #endif
616*0Sstevel@tonic-gate #ifdef SIGACTION
617*0Sstevel@tonic-gate 		sigaction(i,&savsig[i],NULL);
618*0Sstevel@tonic-gate #else
619*0Sstevel@tonic-gate 		signal(i,savsig[i]);
620*0Sstevel@tonic-gate #endif
621*0Sstevel@tonic-gate 		}
622*0Sstevel@tonic-gate 	}
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate static void recsig(int i)
625*0Sstevel@tonic-gate 	{
626*0Sstevel@tonic-gate 	intr_signal=i;
627*0Sstevel@tonic-gate 	}
628*0Sstevel@tonic-gate #endif
629*0Sstevel@tonic-gate 
630*0Sstevel@tonic-gate /* Internal functions specific for Windows */
631*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
632*0Sstevel@tonic-gate static int noecho_fgets(char *buf, int size, FILE *tty)
633*0Sstevel@tonic-gate 	{
634*0Sstevel@tonic-gate 	int i;
635*0Sstevel@tonic-gate 	char *p;
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 	p=buf;
638*0Sstevel@tonic-gate 	for (;;)
639*0Sstevel@tonic-gate 		{
640*0Sstevel@tonic-gate 		if (size == 0)
641*0Sstevel@tonic-gate 			{
642*0Sstevel@tonic-gate 			*p='\0';
643*0Sstevel@tonic-gate 			break;
644*0Sstevel@tonic-gate 			}
645*0Sstevel@tonic-gate 		size--;
646*0Sstevel@tonic-gate #ifdef WIN16TTY
647*0Sstevel@tonic-gate 		i=_inchar();
648*0Sstevel@tonic-gate #else
649*0Sstevel@tonic-gate 		i=getch();
650*0Sstevel@tonic-gate #endif
651*0Sstevel@tonic-gate 		if (i == '\r') i='\n';
652*0Sstevel@tonic-gate 		*(p++)=i;
653*0Sstevel@tonic-gate 		if (i == '\n')
654*0Sstevel@tonic-gate 			{
655*0Sstevel@tonic-gate 			*p='\0';
656*0Sstevel@tonic-gate 			break;
657*0Sstevel@tonic-gate 			}
658*0Sstevel@tonic-gate 		}
659*0Sstevel@tonic-gate #ifdef WIN_CONSOLE_BUG
660*0Sstevel@tonic-gate /* Win95 has several evil console bugs: one of these is that the
661*0Sstevel@tonic-gate  * last character read using getch() is passed to the next read: this is
662*0Sstevel@tonic-gate  * usually a CR so this can be trouble. No STDIO fix seems to work but
663*0Sstevel@tonic-gate  * flushing the console appears to do the trick.
664*0Sstevel@tonic-gate  */
665*0Sstevel@tonic-gate 		{
666*0Sstevel@tonic-gate 			HANDLE inh;
667*0Sstevel@tonic-gate 			inh = GetStdHandle(STD_INPUT_HANDLE);
668*0Sstevel@tonic-gate 			FlushConsoleInputBuffer(inh);
669*0Sstevel@tonic-gate 		}
670*0Sstevel@tonic-gate #endif
671*0Sstevel@tonic-gate 	return(strlen(buf));
672*0Sstevel@tonic-gate 	}
673*0Sstevel@tonic-gate #endif
674