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