1 /*
2  * sslwrap.c
3  *
4  * Wrapper that encrypts all data from a simple TCP-based service
5  * (POP3, IMAP, SMTP, telnet).  Installs in inetd.
6  *
7  * Written by Rick Kaseguma
8  * <rickk@rickk.com>
9  *
10  * Version 1:
11  * December 28, 1997
12  *
13  * Version 2:
14  * September 18, 1998 - Added support for SSLeay 0.9.1 and standalone mode
15  * instead of inetd mode. Added support for connecting to other hosts.
16  *
17  * Version 2.0.1 (user contributions)
18  * Added "-exec" option to directly run a program instead of having to connect
19  *   to localhost
20  * Corrected a typo in the usage info for -accept
21  * Corrected a segmentation fault when -nocafile is used
22  *
23  * Version 2.0.2 (user contributions)
24  * Corrected missing ")" in call to RSA_generate_key for versions of SSLeay
25  * less than 9.0
26  *
27  * Version 2.0.5
28  * Compatibility with OpenSSL 0.9.4
29  *
30  * Version 2.0.6
31  * Changed Malloc to malloc and Free to free
32  * Changed #include "err.h" to #include "openssl/err.h"
33  *
34  * Copyright 1997-9, 2000 Rick R. Kaseguma
35  * All rights reserved
36  *
37  * Feel free to use this as you want for commercial or non-commercial use,
38  * but no warranty is provided.  Use at your own risk.
39  *
40  * Example inetd.conf entry (from Linux):
41  *
42  * imaps	stream tcp	nowait	sslwrap	/usr/sbin/tcpd
43  * /usr/local/ssl/bin/sslwrap -cert /usr/local/ssl/certs/mail.pem -port 143
44  *
45  * This does not need to be run as root, but it does need to be able to access
46  * the (unencrypted) certificate file.
47  *
48  * You must specify a certificate file (-cert) but it can be self-signed.
49  *
50  * You must also specify the port the service actually exists on using -port.
51  * sslwrap will make a connection to localhost (127.0.0.1) and this port to
52  * do the actual work on the connection. The connection will not come from
53  * a privileged port, so you cannot use this to front-end a service that
54  * requires that.
55  */
56 
57 
58 /* apps/s_server.c */
59 /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
60  * All rights reserved.
61  *
62  * This package is an SSL implementation written
63  * by Eric Young (eay@cryptsoft.com).
64  * The implementation was written so as to conform with Netscapes SSL.
65  *
66  * This library is free for commercial and non-commercial use as long as
67  * the following conditions are aheared to.  The following conditions
68  * apply to all code found in this distribution, be it the RC4, RSA,
69  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
70  * included with this distribution is covered by the same copyright terms
71  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
72  *
73  * Copyright remains Eric Young's, and as such any Copyright notices in
74  * the code are not to be removed.
75  * If this package is used in a product, Eric Young should be given attribution
76  * as the author of the parts of the library used.
77  * This can be in the form of a textual message at program startup or
78  * in documentation (online or textual) provided with the package.
79  *
80  * Redistribution and use in source and binary forms, with or without
81  * modification, are permitted provided that the following conditions
82  * are met:
83  * 1. Redistributions of source code must retain the copyright
84  *    notice, this list of conditions and the following disclaimer.
85  * 2. Redistributions in binary form must reproduce the above copyright
86  *    notice, this list of conditions and the following disclaimer in the
87  *    documentation and/or other materials provided with the distribution.
88  * 3. All advertising materials mentioning features or use of this software
89  *    must display the following acknowledgement:
90  *    "This product includes cryptographic software written by
91  *     Eric Young (eay@cryptsoft.com)"
92  *    The word 'cryptographic' can be left out if the rouines from the library
93  *    being used are not cryptographic related :-).
94  * 4. If you include any Windows specific code (or a derivative thereof) from
95  *    the apps directory (application code) you must include an acknowledgement:
96  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
97  *
98  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
99  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
101  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
102  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
103  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
104  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
106  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
107  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
108  * SUCH DAMAGE.
109  *
110  * The licence and distribution terms for any publically available version or
111  * derivative of this code cannot be changed.  i.e. this code cannot simply be
112  * copied and put under another distribution licence
113  * [including the GNU Public Licence.]
114  */
115 
116 #include <stdio.h>
117 #include <stdlib.h>
118 #include <string.h>
119 #include <sys/types.h>
120 #include <sys/stat.h>
121 #ifdef WIN16
122 #define APPS_WIN16
123 #endif
124 #include "openssl/lhash.h"
125 #include "openssl/bn.h"
126 #define USE_SOCKETS
127 #include "apps.h"
128 #include "openssl/err.h"
129 #include "openssl/pem.h"
130 #include "openssl/x509.h"
131 #include "openssl/ssl.h"
132 #include "s_apps.h"
133 
134 #ifndef NOPROTO
135 static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export
136 #if SSLEAY_VERSION_NUMBER >= 0x903101L
137 , int keylen
138 #endif
139 );
140 #if defined(OPENSSL_NO_SSL2)
141 #define NO_SSL2
142 #endif
143 #if defined(OPENSSL_NO_SSL3)
144 #define NO_SSL3
145 #endif
146 static int sv_body(char *hostname, int sin, int sout);
147 static void close_accept_socket(void );
148 static void sv_usage(void);
149 static int init_ssl_connection(SSL *s);
150 static void print_stats(BIO *bp,SSL_CTX *ctx);
151 static DH *load_dh_param(void );
152 static DH *get_dh512(void);
153 #else
154 static RSA MS_CALLBACK *tmp_rsa_cb();
155 static int sv_body();
156 static void close_accept_socket();
157 static void sv_usage();
158 static int init_ssl_connection();
159 static void print_stats();
160 static DH *load_dh_param();
161 static DH *get_dh512();
162 #endif
163 
164 #ifdef WIN32
165 int errno;
166 #endif
167 
168 #ifndef S_ISDIR
169 #define S_ISDIR(a)	(((a) & _S_IFMT) == _S_IFDIR)
170 #endif
171 
172 static unsigned char dh512_p[]={
173 	0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
174 	0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
175 	0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
176 	0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
177 	0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
178 	0x47,0x74,0xE8,0x33,
179 	};
180 static unsigned char dh512_g[]={
181 	0x02,
182 	};
183 
get_dh512()184 static DH *get_dh512()
185 	{
186 	DH *dh=NULL;
187 
188 #ifndef NO_DH
189 	if ((dh=DH_new()) == NULL) return(NULL);
190 	dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
191 	dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
192 	if ((dh->p == NULL) || (dh->g == NULL))
193 		return(NULL);
194 #endif
195 	return(dh);
196 	}
197 
198 /* static int load_CA(SSL_CTX *ctx, char *file);*/
199 
200 #undef BUFSIZZ
201 #define BUFSIZZ	1024
202 static int accept_socket= -1;
203 
204 #define TEST_CERT	"server.pem"
205 #undef PROG
206 #define PROG		s_server_main
207 
208 #define DH_PARAM	"server.pem"
209 
210 extern int verify_depth;
211 
212 static char *cipher=NULL;
213 int verify=SSL_VERIFY_NONE;
214 char *s_cert_file=TEST_CERT,*s_key_file=NULL;
215 #ifdef FIONBIO
216 static int s_nbio=0;
217 #endif
218 static int s_nbio_test=0;
219 static SSL_CTX *ctx=NULL;
220 
221 static BIO *bio_s_out=NULL;
222 static int s_debug=0;
223 static int s_quiet=1;
224 
225 static unsigned long dstAddr = (127 << 24) | 1;
226 static short dstPort = 0;
227 #ifndef NO_EXEC
228 static char *exec_pgm = NULL;
229 #endif /*NO_EXEC*/
230 
sv_usage()231 static void sv_usage()
232 	{
233 	BIO_printf(bio_err,"usage: sslwrap [args ...]\n");
234 	BIO_printf(bio_err,"\n");
235 	BIO_printf(bio_err," -addr arg     - address to connect to (default is 127.0.0.1)\n");
236 	BIO_printf(bio_err," -port arg     - port to connect to\n");
237 	BIO_printf(bio_err," -accept arg   - port to accept on (default is stdin for inetd)\n");
238 	BIO_printf(bio_err," -verify arg   - turn on peer certificate verification\n");
239 	BIO_printf(bio_err," -Verify arg   - turn on peer certificate verification, must have a cert.\n");
240 	BIO_printf(bio_err," -cert arg     - certificate file to use, PEM format assumed\n");
241 	BIO_printf(bio_err,"                 (default is %s)\n",TEST_CERT);
242 	BIO_printf(bio_err," -key arg      - RSA file to use, PEM format assumed, in cert file if\n");
243 	BIO_printf(bio_err,"                 not specified (default is %s)\n",TEST_CERT);
244 #ifdef FIONBIO
245 	BIO_printf(bio_err," -nbio         - Run with non-blocking IO\n");
246 #endif
247 	BIO_printf(bio_err," -nbio_test    - test with the non-blocking test bio\n");
248 	BIO_printf(bio_err," -debug        - Print more output\n");
249 	BIO_printf(bio_err," -state        - Print the SSL states\n");
250 #if 0
251 	BIO_printf(bio_err," -CApath arg   - PEM format directory of CA's\n");
252 	BIO_printf(bio_err," -CAfile arg   - PEM format file of CA's\n");
253 #endif
254 	BIO_printf(bio_err," -nocert       - Don't use any certificates (Anon-DH)\n");
255 	BIO_printf(bio_err," -cipher arg   - play with 'ssleay ciphers' to see what goes here\n");
256 	BIO_printf(bio_err," -quiet        - No server output\n");
257 	BIO_printf(bio_err," -no_tmp_rsa   - Do not generate a tmp RSA key\n");
258 	BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
259 	BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
260 	BIO_printf(bio_err," -bugs         - Turn on SSL bug compatability\n");
261 	}
262 
263 static int local_argc;
264 static char **local_argv;
265 static int hack;
266 
MAIN(argc,argv)267 int MAIN(argc, argv)
268 int argc;
269 char *argv[];
270 	{
271 	short port=0;
272 	char *CApath=NULL,*CAfile=NULL;
273 	int badop=0,bugs=0;
274 	int ret=1;
275 	int no_tmp_rsa=0,nocert=0;
276 	int state=0;
277 	SSL_METHOD *meth=NULL;
278 	DH *dh=NULL;
279 
280 #if !defined(NO_SSL2) && !defined(NO_SSL3)
281 	meth=SSLv23_server_method();
282 #elif !defined(NO_SSL3)
283 	meth=SSLv3_server_method();
284 #elif !defined(NO_SSL2)
285 	meth=SSLv2_server_method();
286 #endif
287 
288 	local_argc=argc;
289 	local_argv=argv;
290 
291 	apps_startup();
292 	s_quiet=0;
293 	s_debug=0;
294 
295 	if (bio_err == NULL)
296 		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
297 
298 	verify_depth=0;
299 #ifdef FIONBIO
300 	s_nbio=0;
301 #endif
302 	s_nbio_test=0;
303 
304 	argc--;
305 	argv++;
306 
307 	while (argc >= 1)
308 		{
309 		if	((strcmp(*argv,"-port") == 0))
310 			{
311 			if (--argc < 1) goto bad;
312 			if (!extract_port(*(++argv),&dstPort))
313 				goto bad;
314 			}
315 		else if	((strcmp(*argv,"-addr") == 0))
316 			{
317 			int v1, v2, v3, v4;
318 			if (--argc < 1) goto bad;
319 			if (sscanf(*(++argv), "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4)
320 				goto bad;
321 
322 			dstAddr = ((v1 << 24) & 0xFF000000) | ((v2 << 16) & 0xFF0000) |
323 				((v3 << 8) & 0xFF00) | (v4 & 0xFF);
324 			}
325 #ifndef NO_EXEC
326 		else if	((strcmp(*argv,"-exec") == 0))
327 			{
328 			if (--argc < 1) goto bad;
329 			exec_pgm = *(++argv);
330 			}
331 #endif /*NO_EXEC*/
332 		else if	(strcmp(*argv,"-accept") == 0)
333 			{
334 			if (--argc < 1) goto bad;
335 			if (!extract_port(*(++argv),&port))
336 				goto bad;
337 			}
338 		else if	(strcmp(*argv,"-verify") == 0)
339 			{
340 			verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
341 			if (--argc < 1) goto bad;
342 			verify_depth=atoi(*(++argv));
343 			BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
344 			}
345 		else if	(strcmp(*argv,"-Verify") == 0)
346 			{
347 			verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
348 				SSL_VERIFY_CLIENT_ONCE;
349 			if (--argc < 1) goto bad;
350 			verify_depth=atoi(*(++argv));
351 			BIO_printf(bio_err,"verify depth is %d, must return a certificate\n",verify_depth);
352 			}
353 		else if	(strcmp(*argv,"-cert") == 0)
354 			{
355 			if (--argc < 1) goto bad;
356 			s_cert_file= *(++argv);
357 			}
358 		else if	(strcmp(*argv,"-key") == 0)
359 			{
360 			if (--argc < 1) goto bad;
361 			s_key_file= *(++argv);
362 			}
363 		else if (strcmp(*argv,"-nocert") == 0)
364 			{
365 			nocert=1;
366 			}
367 		else if	(strcmp(*argv,"-CApath") == 0)
368 			{
369 			if (--argc < 1) goto bad;
370 			CApath= *(++argv);
371 			}
372 		else if	(strcmp(*argv,"-cipher") == 0)
373 			{
374 			if (--argc < 1) goto bad;
375 			cipher= *(++argv);
376 			}
377 		else if	(strcmp(*argv,"-CAfile") == 0)
378 			{
379 			if (--argc < 1) goto bad;
380 			CAfile= *(++argv);
381 			}
382 #ifdef FIONBIO
383 		else if	(strcmp(*argv,"-nbio") == 0)
384 			{ s_nbio=1; }
385 #endif
386 		else if	(strcmp(*argv,"-nbio_test") == 0)
387 			{
388 #ifdef FIONBIO
389 			s_nbio=1;
390 #endif
391 			s_nbio_test=1;
392 			}
393 		else if	(strcmp(*argv,"-debug") == 0)
394 			{ s_debug=1; }
395 		else if	(strcmp(*argv,"-hack") == 0)
396 			{ hack=1; }
397 		else if	(strcmp(*argv,"-state") == 0)
398 			{ state=1; }
399 		else if	(strcmp(*argv,"-quiet") == 0)
400 			{ s_quiet=1; }
401 		else if	(strcmp(*argv,"-bugs") == 0)
402 			{ bugs=1; }
403 		else if	(strcmp(*argv,"-no_tmp_rsa") == 0)
404 			{ no_tmp_rsa=1; }
405 #ifndef NO_SSL2
406 		else if	(strcmp(*argv,"-ssl2") == 0)
407 			{ meth=SSLv2_server_method(); }
408 #endif
409 #ifndef NO_SSL3
410 		else if	(strcmp(*argv,"-ssl3") == 0)
411 			{ meth=SSLv3_server_method(); }
412 #endif
413 		else
414 			{
415 			BIO_printf(bio_err,"unknown option %s\n",*argv);
416 			badop=1;
417 			break;
418 			}
419 		argc--;
420 		argv++;
421 		}
422 #ifndef NO_EXEC
423 	if (exec_pgm && dstPort) {
424 	    BIO_printf(bio_err,"options -port and -exec are incompatible\n");
425 	    badop=1;
426 	}
427 	if (!exec_pgm && !dstPort) {
428 	    BIO_printf(bio_err,"one of -port or -exec must be supplied\n");
429 	    badop=1;
430 	}
431 #else  /*NO_EXEC*/
432 	if (!dstPort) {
433 	    BIO_printf(bio_err,"-port must be supplied\n");
434 	    badop=1;
435 	}
436 #endif /*NO_EXEC*/
437 	if (badop)
438 		{
439 bad:
440 		sv_usage();
441 		goto end;
442 		}
443 
444 	if (bio_s_out == NULL)
445 		{
446 		if (s_quiet && !s_debug)
447 			{
448 			bio_s_out=BIO_new(BIO_s_null());
449 			}
450 		else
451 			{
452 			if (bio_s_out == NULL)
453 				bio_s_out=BIO_new_fp(stdout,BIO_NOCLOSE);
454 			}
455 		}
456 
457 #if !defined(NO_RSA) || !defined(NO_DSA)
458 	if (nocert)
459 #endif
460 		{
461 		s_cert_file=NULL;
462 		s_key_file=NULL;
463 		}
464 
465 	SSL_load_error_strings();
466 	SSLeay_add_ssl_algorithms();
467 
468 	ctx=SSL_CTX_new(meth);
469 	if (ctx == NULL)
470 		{
471 		ERR_print_errors(bio_err);
472 		goto end;
473 		}
474 
475 	if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL);
476 	if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
477 	if (hack) SSL_CTX_set_options(ctx,SSL_OP_CIPHER_SERVER_PREFERENCE);
478 
479 	if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
480 
481 #if 0
482 	if (cipher == NULL) cipher=getenv("SSL_CIPHER");
483 #endif
484 
485 #if 0
486 	if (s_cert_file == NULL)
487 		{
488 		BIO_printf(bio_err,"You must specify a certificate file for the server to use\n");
489 		goto end;
490 		}
491 #endif
492 
493 	/* 980921 RRK - Removed this code; not necessary for sslwrap */
494 #if 0
495 	if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
496 		(!SSL_CTX_set_default_verify_paths(ctx)))
497 		{
498 		BIO_printf(bio_err,"X509_load_verify_locations\n");
499 		ERR_print_errors(bio_err);
500 		goto end;
501 		}
502 #endif
503 
504 #ifndef NO_DH
505 	/* EAY EAY EAY evil hack */
506 	dh=load_dh_param();
507 	if (dh != NULL)
508 		{
509 		/* BIO_printf(bio_s_out,"Setting temp DH parameters\n"); */
510 		}
511 	else
512 		{
513 		/* BIO_printf(bio_s_out,"Using default temp DH parameters\n"); */
514 		dh=get_dh512();
515 		}
516 	/* BIO_flush(bio_s_out); */
517 
518 	SSL_CTX_set_tmp_dh(ctx,dh);
519 	DH_free(dh);
520 #endif
521 
522 	if (!set_cert_stuff(ctx,s_cert_file,s_key_file))
523 		goto end;
524 
525 #if 1
526 	SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
527 #else
528 	if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx))
529 		{
530 		RSA *rsa;
531 
532 		/* BIO_printf(bio_s_out,"Generating temp (512 bit) RSA key..."); */
533 		/* BIO_flush(bio_s_out); */
534 
535 		rsa=RSA_generate_key(512,RSA_F4,NULL);
536 
537 		if (!SSL_CTX_set_tmp_rsa(ctx,rsa))
538 			{
539 			ERR_print_errors(bio_err);
540 			goto end;
541 			}
542 		RSA_free(rsa);
543 		/* BIO_printf(bio_s_out,"\n"); */
544 		}
545 #endif
546 
547 	if (cipher != NULL)
548 		SSL_CTX_set_cipher_list(ctx,cipher);
549 	SSL_CTX_set_verify(ctx,verify,verify_callback);
550 
551 	if (s_cert_file != NULL) {
552 	    SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(s_cert_file));
553 	}
554 
555 	if (port) {
556 		/* BIO_printf(bio_s_out,"ACCEPT\n"); */
557 		do_server(port,&accept_socket,sv_body);
558 		/* print_stats(bio_s_out,ctx); */
559 		ret=0;
560 	} else {
561 		/* stdin/stdout for inetd */
562 		sv_body( "", fileno(stdin), fileno(stdout) );
563 	}
564 end:
565 	if (ctx != NULL) SSL_CTX_free(ctx);
566 	if (bio_s_out != NULL)
567 		{
568 		BIO_free(bio_s_out);
569 		bio_s_out=NULL;
570 		}
571 	EXIT(ret);
572 	}
573 
print_stats(bio,ssl_ctx)574 static void print_stats(bio,ssl_ctx)
575 BIO *bio;
576 SSL_CTX *ssl_ctx;
577 	{
578 	BIO_printf(bio,"%4ld items in the session cache\n",
579 		SSL_CTX_sess_number(ssl_ctx));
580 	BIO_printf(bio,"%4d client connects (SSL_connect())\n",
581 		SSL_CTX_sess_connect(ssl_ctx));
582 	BIO_printf(bio,"%4d client connects that finished\n",
583 		SSL_CTX_sess_connect_good(ssl_ctx));
584 	BIO_printf(bio,"%4d server accepts (SSL_accept())\n",
585 		SSL_CTX_sess_accept(ssl_ctx));
586 	BIO_printf(bio,"%4d server accepts that finished\n",
587 		SSL_CTX_sess_accept_good(ssl_ctx));
588 	BIO_printf(bio,"%4d session cache hits\n",SSL_CTX_sess_hits(ssl_ctx));
589 	BIO_printf(bio,"%4d session cache misses\n",SSL_CTX_sess_misses(ssl_ctx));
590 	BIO_printf(bio,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ssl_ctx));
591 	BIO_printf(bio,"%4d callback cache hits\n",SSL_CTX_sess_cb_hits(ssl_ctx));
592 	}
593 
sv_body(hostname,s_stdin,s_stdout)594 static int sv_body(hostname, s_stdin, s_stdout)
595 char *hostname;
596 int s_stdin;
597 int s_stdout;
598 	{
599 	char *buf=NULL;
600 	fd_set readfds;
601 	int ret=1,width;
602 	int k,i;
603 	unsigned long l;
604 	SSL *con=NULL;
605 	BIO *sbi, *sbo;
606 	int s_in, s_out;
607 	struct sockaddr_in srvr;
608 
609 	if (dstPort) {
610 	    s_in = s_out = socket( AF_INET, SOCK_STREAM, 0 );
611 
612 	    memset((void *)&srvr, 0, sizeof(srvr));
613 	    srvr.sin_family = AF_INET;
614 	    srvr.sin_port = htons( dstPort );
615 	    srvr.sin_addr.s_addr = htonl( dstAddr );
616 
617 	    connect(s_in, (struct sockaddr *) &srvr, sizeof(srvr));
618 #ifndef NO_EXEC
619 	} else {
620 	    char *exec_argv[2];
621 	    exec_argv[0] = exec_pgm;
622 	    exec_argv[1] = NULL;
623 
624 	    if (spawn(1, exec_argv, &s_in, &s_out) < 0) {
625 		BIO_printf(bio_err,"could not run %s\n", exec_pgm);
626 		goto err;
627 	    }
628 #endif /*NO_EXEC*/
629 	}
630 
631 	if ((buf=malloc(BUFSIZZ)) == NULL)
632 		{
633 		BIO_printf(bio_err,"out of memory\n");
634 		goto err;
635 		}
636 
637 	if (con == NULL)
638 		con=(SSL *)SSL_new(ctx);
639 	SSL_clear(con);
640 
641 	sbi=BIO_new_socket(s_stdin,BIO_NOCLOSE);
642 	sbo=BIO_new_socket(s_stdout,BIO_NOCLOSE);
643 
644 	SSL_set_bio(con,sbi,sbo);
645 	SSL_set_accept_state(con);
646 	/* SSL_set_fd(con,s); */
647 
648 	width=s_stdin;
649 	if (s_stdout > width) width = s_stdout;
650 	if (s_in > width) width = s_in;
651 	width++;
652 	for(;;)
653 		{
654 		FD_ZERO(&readfds);
655 		FD_SET(s_in,&readfds);
656 		FD_SET(s_stdin,&readfds);
657 		i=select(width,&readfds,NULL,NULL,NULL);
658 		if (i <= 0) continue;
659 		if (FD_ISSET(s_in,&readfds))
660 			{
661 			i=read(s_in,buf,BUFSIZZ);
662 			if (!s_quiet)
663 				{
664 				if (i <= 0)
665 					{
666 					goto err;
667 					}
668 
669 				}
670 			l=k=0;
671 			for (;;)
672 				{
673 				/* should do a select for the write */
674 				k=SSL_write(con,&(buf[l]),(unsigned int)i);
675 				if (
676 					BIO_sock_should_retry(k))
677 					{
678 					continue;
679 					}
680 				if (k <= 0)
681 					{
682 					ERR_print_errors(bio_err);
683 					ret=1;
684 					goto err;
685 					}
686 				l+=k;
687 				i-=k;
688 				if (i <= 0) break;
689 				}
690 			}
691 		if (FD_ISSET(s_stdin,&readfds))
692 			{
693 			if (!SSL_is_init_finished(con))
694 				{
695 				i=init_ssl_connection(con);
696 
697 				if (i < 0)
698 					{
699 					ret=0;
700 					goto err;
701 					}
702 				else if (i == 0)
703 					{
704 					ret=1;
705 					goto err;
706 					}
707 				}
708 			else
709 				{
710 				i=SSL_read(con,(char *)buf,BUFSIZZ);
711 				if ((i <= 0) &&
712 					BIO_sock_should_retry(i))
713 					{
714 					}
715 				else if (i <= 0)
716 					{
717 					ERR_print_errors(bio_err);
718 					ret=1;
719 					goto err;
720 					}
721 				else
722 					write(s_out,buf,
723 						(unsigned int)i);
724 				}
725 			}
726 		}
727 err:
728 
729 #if 1
730 	SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
731 #else
732 	SSL_shutdown(con);
733 #endif
734 	if (con != NULL) SSL_free(con);
735 	if (buf != NULL)
736 		{
737 		memset(buf,0,BUFSIZZ);
738 		free(buf);
739 		}
740 
741 	return(ret);
742 	}
743 
close_accept_socket()744 static void close_accept_socket()
745 	{
746 	BIO_printf(bio_err,"shutdown accept socket\n");
747 	if (accept_socket >= 0)
748 		{
749 		SHUTDOWN2(accept_socket);
750 		}
751 	}
752 
init_ssl_connection(con)753 static int init_ssl_connection(con)
754 SSL *con;
755 	{
756 	int i;
757 	X509 *peer;
758 	int verify_error;
759 	/*
760 	char *str;
761 	MS_STATIC char buf[BUFSIZ];
762 	*/
763 
764 	if ((i=SSL_accept(con)) <= 0)
765 		{
766 		if (BIO_sock_should_retry(i))
767 			{
768 			/* BIO_printf(bio_s_out,"DELAY\n"); */
769 			return(1);
770 			}
771 
772 		BIO_printf(bio_err,"ERROR\n");
773 		verify_error=SSL_get_verify_result(con);
774 		if (verify_error != X509_V_OK)
775 			{
776 			BIO_printf(bio_err,"verify error:%s\n",
777 				X509_verify_cert_error_string(verify_error));
778 			}
779 		else
780 			ERR_print_errors(bio_err);
781 		return(0);
782 		}
783 
784 	/* PEM_write_bio_SSL_SESSION(bio_s_out,SSL_get_session(con)); */
785 
786 	peer=SSL_get_peer_certificate(con);
787 	if (peer != NULL)
788 		{
789 		/*
790 		BIO_printf(bio_s_out,"Client certificate\n");
791 		PEM_write_bio_X509(bio_s_out,peer);
792 		X509_NAME_oneline(X509_get_subject_name(peer),buf,BUFSIZ);
793 		BIO_printf(bio_s_out,"subject=%s\n",buf);
794 		X509_NAME_oneline(X509_get_issuer_name(peer),buf,BUFSIZ);
795 		BIO_printf(bio_s_out,"issuer=%s\n",buf);
796 		X509_free(peer);
797 		*/
798 		}
799 	/*
800 	if (SSL_get_shared_ciphers(con,buf,BUFSIZ) != NULL)
801 		BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
802 	str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
803 	BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
804 	if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n");
805 	*/
806 	return(1);
807 	}
808 
load_dh_param()809 static DH *load_dh_param()
810 	{
811 	DH *ret=NULL;
812 	BIO *bio;
813 
814 #ifndef NO_DH
815 	if ((bio=BIO_new_file(DH_PARAM,"r")) == NULL)
816 		goto err;
817 	ret=PEM_read_bio_DHparams(bio,NULL,NULL
818 #if SSLEAY_VERSION_NUMBER >= 0x904100L
819 				  , NULL
820 #endif
821 );
822 err:
823 	if (bio != NULL) BIO_free(bio);
824 #endif
825 	return(ret);
826 	}
827 
828 #if 0
829 static int load_CA(ctx,file)
830 SSL_CTX *ctx;
831 char *file;
832 	{
833 	FILE *in;
834 	X509 *x=NULL;
835 
836 	if ((in=fopen(file,"r")) == NULL)
837 		return(0);
838 
839 	for (;;)
840 		{
841 		if (PEM_read_X509(in,&x,NULL) == NULL)
842 			break;
843 		SSL_CTX_add_client_CA(ctx,x);
844 		}
845 	if (x != NULL) X509_free(x);
846 	fclose(in);
847 	return(1);
848 	}
849 #endif
850 
851 
tmp_rsa_cb(s,export,keylen)852 static RSA MS_CALLBACK *tmp_rsa_cb(s,export
853 #if SSLEAY_VERSION_NUMBER >= 0x903101L
854 ,keylen
855 #endif
856 
857 )
858 SSL *s;
859 int export;
860 #if SSLEAY_VERSION_NUMBER >= 0x903101L
861 int keylen;
862 #endif
863 	{
864 	static RSA *rsa_tmp=NULL;
865 
866 	if (rsa_tmp == NULL)
867 		{
868 		if (!s_quiet)
869 			{
870 			/* BIO_printf(bio_err,"Generating temp (512 bit) RSA key...");
871 			BIO_flush(bio_err); */
872 			}
873 #ifndef NO_RSA
874 #if SSLEAY_VERSION_NUMBER >= 0x0900
875 		rsa_tmp=RSA_generate_key(512,RSA_F4,NULL,NULL);
876 #else
877 		rsa_tmp=RSA_generate_key(512,RSA_F4,NULL);
878 #endif
879 #endif
880 		if (!s_quiet)
881 			{
882 			/* BIO_printf(bio_err,"\n");
883 			BIO_flush(bio_err); */
884 			}
885 		}
886 	return(rsa_tmp);
887 	}
888