Remove NOPROTO definitions and error code comments.
[openssl.git] / apps / s_client.c
1 /* apps/s_client.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #define USE_SOCKETS
63 #ifdef NO_STDIO
64 #define APPS_WIN16
65 #endif
66 #include "apps.h"
67 #include <openssl/x509.h>
68 #include <openssl/ssl.h>
69 #include <openssl/err.h>
70 #include <openssl/pem.h>
71 #include "s_apps.h"
72
73 #undef PROG
74 #define PROG    s_client_main
75
76 /*#define SSL_HOST_NAME "www.netscape.com" */
77 /*#define SSL_HOST_NAME "193.118.187.102" */
78 #define SSL_HOST_NAME   "localhost"
79
80 /*#define TEST_CERT "client.pem" */ /* no default cert. */
81
82 #undef BUFSIZZ
83 #define BUFSIZZ 1024*8
84
85 extern int verify_depth;
86 extern int verify_error;
87
88 #ifdef FIONBIO
89 static int c_nbio=0;
90 #endif
91 static int c_Pause=0;
92 static int c_debug=0;
93 static int c_showcerts=0;
94
95 static void sc_usage(void);
96 static void print_stuff(BIO *berr,SSL *con,int full);
97 static BIO *bio_c_out=NULL;
98 static int c_quiet=0;
99
100 static void sc_usage(void)
101         {
102         BIO_printf(bio_err,"usage: s_client args\n");
103         BIO_printf(bio_err,"\n");
104         BIO_printf(bio_err," -host host     - use -connect instead\n");
105         BIO_printf(bio_err," -port port     - use -connect instead\n");
106         BIO_printf(bio_err," -connect host:port - who to connect to (default is %s:%s)\n",SSL_HOST_NAME,PORT_STR);
107
108         BIO_printf(bio_err," -verify arg   - turn on peer certificate verification\n");
109         BIO_printf(bio_err," -cert arg     - certificate file to use, PEM format assumed\n");
110         BIO_printf(bio_err," -key arg      - Private key file to use, PEM format assumed, in cert file if\n");
111         BIO_printf(bio_err,"                 not specified but cert file is.\n");
112         BIO_printf(bio_err," -CApath arg   - PEM format directory of CA's\n");
113         BIO_printf(bio_err," -CAfile arg   - PEM format file of CA's\n");
114         BIO_printf(bio_err," -reconnect    - Drop and re-make the connection with the same Session-ID\n");
115         BIO_printf(bio_err," -pause        - sleep(1) after each read(2) and write(2) system call\n");
116         BIO_printf(bio_err," -showcerts    - show all certificates in the chain\n");
117         BIO_printf(bio_err," -debug        - extra output\n");
118         BIO_printf(bio_err," -nbio_test    - more ssl protocol testing\n");
119         BIO_printf(bio_err," -state        - print the 'ssl' states\n");
120 #ifdef FIONBIO
121         BIO_printf(bio_err," -nbio         - Run with non-blocking IO\n");
122 #endif
123         BIO_printf(bio_err," -quiet        - no s_client output\n");
124         BIO_printf(bio_err," -ssl2         - just use SSLv2\n");
125         BIO_printf(bio_err," -ssl3         - just use SSLv3\n");
126         BIO_printf(bio_err," -tls1         - just use TLSv1\n");
127         BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
128         BIO_printf(bio_err," -bugs         - Switch on all SSL implementation bug workarounds\n");
129         BIO_printf(bio_err," -cipher       - prefered cipher to use, use the 'openssl ciphers'\n");
130         BIO_printf(bio_err,"                 command to see what is available\n");
131
132         }
133
134 int MAIN(int argc, char **argv)
135         {
136         int off=0;
137         SSL *con=NULL,*con2=NULL;
138         int s,k,width,state=0;
139         char *cbuf=NULL,*sbuf=NULL;
140         int cbuf_len,cbuf_off;
141         int sbuf_len,sbuf_off;
142         fd_set readfds,writefds;
143         short port=PORT;
144         int full_log=1;
145         char *host=SSL_HOST_NAME;
146         char *cert_file=NULL,*key_file=NULL;
147         char *CApath=NULL,*CAfile=NULL,*cipher=NULL;
148         int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0;
149         int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending;
150         SSL_CTX *ctx=NULL;
151         int ret=1,in_init=1,i,nbio_test=0;
152         SSL_METHOD *meth=NULL;
153         BIO *sbio;
154         /*static struct timeval timeout={10,0};*/
155
156 #if !defined(NO_SSL2) && !defined(NO_SSL3)
157         meth=SSLv23_client_method();
158 #elif !defined(NO_SSL3)
159         meth=SSLv3_client_method();
160 #elif !defined(NO_SSL2)
161         meth=SSLv2_client_method();
162 #endif
163
164         apps_startup();
165         c_Pause=0;
166         c_quiet=0;
167         c_debug=0;
168         c_showcerts=0;
169
170         if (bio_err == NULL)
171                 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
172
173         if (    ((cbuf=Malloc(BUFSIZZ)) == NULL) ||
174                 ((sbuf=Malloc(BUFSIZZ)) == NULL))
175                 {
176                 BIO_printf(bio_err,"out of memory\n");
177                 goto end;
178                 }
179
180         verify_depth=0;
181         verify_error=X509_V_OK;
182 #ifdef FIONBIO
183         c_nbio=0;
184 #endif
185
186         argc--;
187         argv++;
188         while (argc >= 1)
189                 {
190                 if      (strcmp(*argv,"-host") == 0)
191                         {
192                         if (--argc < 1) goto bad;
193                         host= *(++argv);
194                         }
195                 else if (strcmp(*argv,"-port") == 0)
196                         {
197                         if (--argc < 1) goto bad;
198                         port=atoi(*(++argv));
199                         if (port == 0) goto bad;
200                         }
201                 else if (strcmp(*argv,"-connect") == 0)
202                         {
203                         if (--argc < 1) goto bad;
204                         if (!extract_host_port(*(++argv),&host,NULL,&port))
205                                 goto bad;
206                         }
207                 else if (strcmp(*argv,"-verify") == 0)
208                         {
209                         verify=SSL_VERIFY_PEER;
210                         if (--argc < 1) goto bad;
211                         verify_depth=atoi(*(++argv));
212                         BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
213                         }
214                 else if (strcmp(*argv,"-cert") == 0)
215                         {
216                         if (--argc < 1) goto bad;
217                         cert_file= *(++argv);
218                         }
219                 else if (strcmp(*argv,"-quiet") == 0)
220                         c_quiet=1;
221                 else if (strcmp(*argv,"-pause") == 0)
222                         c_Pause=1;
223                 else if (strcmp(*argv,"-debug") == 0)
224                         c_debug=1;
225                 else if (strcmp(*argv,"-showcerts") == 0)
226                         c_showcerts=1;
227                 else if (strcmp(*argv,"-nbio_test") == 0)
228                         nbio_test=1;
229                 else if (strcmp(*argv,"-state") == 0)
230                         state=1;
231 #ifndef NO_SSL2
232                 else if (strcmp(*argv,"-ssl2") == 0)
233                         meth=SSLv2_client_method();
234 #endif
235 #ifndef NO_SSL3
236                 else if (strcmp(*argv,"-ssl3") == 0)
237                         meth=SSLv3_client_method();
238 #endif
239 #ifndef NO_TLS1
240                 else if (strcmp(*argv,"-tls1") == 0)
241                         meth=TLSv1_client_method();
242 #endif
243                 else if (strcmp(*argv,"-bugs") == 0)
244                         bugs=1;
245                 else if (strcmp(*argv,"-key") == 0)
246                         {
247                         if (--argc < 1) goto bad;
248                         key_file= *(++argv);
249                         }
250                 else if (strcmp(*argv,"-reconnect") == 0)
251                         {
252                         reconnect=5;
253                         }
254                 else if (strcmp(*argv,"-CApath") == 0)
255                         {
256                         if (--argc < 1) goto bad;
257                         CApath= *(++argv);
258                         }
259                 else if (strcmp(*argv,"-CAfile") == 0)
260                         {
261                         if (--argc < 1) goto bad;
262                         CAfile= *(++argv);
263                         }
264                 else if (strcmp(*argv,"-no_tls1") == 0)
265                         off|=SSL_OP_NO_TLSv1;
266                 else if (strcmp(*argv,"-no_ssl3") == 0)
267                         off|=SSL_OP_NO_SSLv3;
268                 else if (strcmp(*argv,"-no_ssl2") == 0)
269                         off|=SSL_OP_NO_SSLv2;
270                 else if (strcmp(*argv,"-cipher") == 0)
271                         {
272                         if (--argc < 1) goto bad;
273                         cipher= *(++argv);
274                         }
275 #ifdef FIONBIO
276                 else if (strcmp(*argv,"-nbio") == 0)
277                         { c_nbio=1; }
278 #endif
279                 else
280                         {
281                         BIO_printf(bio_err,"unknown option %s\n",*argv);
282                         badop=1;
283                         break;
284                         }
285                 argc--;
286                 argv++;
287                 }
288         if (badop)
289                 {
290 bad:
291                 sc_usage();
292                 goto end;
293                 }
294
295         if (bio_c_out == NULL)
296                 {
297                 if (c_quiet)
298                         {
299                         bio_c_out=BIO_new(BIO_s_null());
300                         }
301                 else
302                         {
303                         if (bio_c_out == NULL)
304                                 bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
305                         }
306                 }
307
308         SSLeay_add_ssl_algorithms();
309         ctx=SSL_CTX_new(meth);
310         if (ctx == NULL)
311                 {
312                 ERR_print_errors(bio_err);
313                 goto end;
314                 }
315
316         if (bugs)
317                 SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
318         else
319                 SSL_CTX_set_options(ctx,off);
320
321         if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
322         if (cipher != NULL)
323                 SSL_CTX_set_cipher_list(ctx,cipher);
324 #if 0
325         else
326                 SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER"));
327 #endif
328
329         SSL_CTX_set_verify(ctx,verify,verify_callback);
330         if (!set_cert_stuff(ctx,cert_file,key_file))
331                 goto end;
332
333         if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
334                 (!SSL_CTX_set_default_verify_paths(ctx)))
335                 {
336                 /* BIO_printf(bio_err,"error seting default verify locations\n"); */
337                 ERR_print_errors(bio_err);
338                 /* goto end; */
339                 }
340
341         SSL_load_error_strings();
342
343         con=(SSL *)SSL_new(ctx);
344 /*      SSL_set_cipher_list(con,"RC4-MD5"); */
345
346 re_start:
347
348         if (init_client(&s,host,port) == 0)
349                 {
350                 BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
351                 SHUTDOWN(s);
352                 goto end;
353                 }
354         BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s);
355
356 #ifdef FIONBIO
357         if (c_nbio)
358                 {
359                 unsigned long l=1;
360                 BIO_printf(bio_c_out,"turning on non blocking io\n");
361                 if (BIO_socket_ioctl(s,FIONBIO,&l) < 0)
362                         {
363                         ERR_print_errors(bio_err);
364                         goto end;
365                         }
366                 }
367 #endif                                              
368         if (c_Pause & 0x01) con->debug=1;
369         sbio=BIO_new_socket(s,BIO_NOCLOSE);
370
371         if (nbio_test)
372                 {
373                 BIO *test;
374
375                 test=BIO_new(BIO_f_nbio_test());
376                 sbio=BIO_push(test,sbio);
377                 }
378
379         if (c_debug)
380                 {
381                 con->debug=1;
382                 BIO_set_callback(sbio,bio_dump_cb);
383                 BIO_set_callback_arg(sbio,bio_c_out);
384                 }
385
386         SSL_set_bio(con,sbio,sbio);
387         SSL_set_connect_state(con);
388
389         /* ok, lets connect */
390         width=SSL_get_fd(con)+1;
391
392         read_tty=1;
393         write_tty=0;
394         tty_on=0;
395         read_ssl=1;
396         write_ssl=1;
397         
398         cbuf_len=0;
399         cbuf_off=0;
400         sbuf_len=0;
401         sbuf_off=0;
402
403         for (;;)
404                 {
405                 FD_ZERO(&readfds);
406                 FD_ZERO(&writefds);
407
408                 if (SSL_in_init(con) && !SSL_total_renegotiations(con))
409                         {
410                         in_init=1;
411                         tty_on=0;
412                         }
413                 else
414                         {
415                         tty_on=1;
416                         if (in_init)
417                                 {
418                                 in_init=0;
419                                 print_stuff(bio_c_out,con,full_log);
420                                 if (full_log > 0) full_log--;
421
422                                 if (reconnect)
423                                         {
424                                         reconnect--;
425                                         BIO_printf(bio_c_out,"drop connection and then reconnect\n");
426                                         SSL_shutdown(con);
427                                         SSL_set_connect_state(con);
428                                         SHUTDOWN(SSL_get_fd(con));
429                                         goto re_start;
430                                         }
431                                 }
432                         }
433
434                 ssl_pending = read_ssl && SSL_pending(con);
435
436                 if (!ssl_pending)
437                         {
438 #ifndef WINDOWS
439                         if (tty_on)
440                                 {
441                                 if (read_tty)  FD_SET(fileno(stdin),&readfds);
442                                 if (write_tty) FD_SET(fileno(stdout),&writefds);
443                                 }
444 #endif
445                         if (read_ssl)
446                                 FD_SET(SSL_get_fd(con),&readfds);
447                         if (write_ssl)
448                                 FD_SET(SSL_get_fd(con),&writefds);
449
450 /*                      printf("mode tty(%d %d%d) ssl(%d%d)\n",
451                                 tty_on,read_tty,write_tty,read_ssl,write_ssl);*/
452
453                         i=select(width,&readfds,&writefds,NULL,NULL);
454                         if ( i < 0)
455                                 {
456                                 BIO_printf(bio_err,"bad select %d\n",
457                                 get_last_socket_error());
458                                 goto shut;
459                                 /* goto end; */
460                                 }
461                         }
462
463                 if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
464                         {
465                         k=SSL_write(con,&(cbuf[cbuf_off]),
466                                 (unsigned int)cbuf_len);
467                         switch (SSL_get_error(con,k))
468                                 {
469                         case SSL_ERROR_NONE:
470                                 cbuf_off+=k;
471                                 cbuf_len-=k;
472                                 if (k <= 0) goto end;
473                                 /* we have done a  write(con,NULL,0); */
474                                 if (cbuf_len <= 0)
475                                         {
476                                         read_tty=1;
477                                         write_ssl=0;
478                                         }
479                                 else /* if (cbuf_len > 0) */
480                                         {
481                                         read_tty=0;
482                                         write_ssl=1;
483                                         }
484                                 break;
485                         case SSL_ERROR_WANT_WRITE:
486                                 BIO_printf(bio_c_out,"write W BLOCK\n");
487                                 write_ssl=1;
488                                 read_tty=0;
489                                 break;
490                         case SSL_ERROR_WANT_READ:
491                                 BIO_printf(bio_c_out,"write R BLOCK\n");
492                                 write_tty=0;
493                                 read_ssl=1;
494                                 write_ssl=0;
495                                 break;
496                         case SSL_ERROR_WANT_X509_LOOKUP:
497                                 BIO_printf(bio_c_out,"write X BLOCK\n");
498                                 break;
499                         case SSL_ERROR_ZERO_RETURN:
500                                 if (cbuf_len != 0)
501                                         {
502                                         BIO_printf(bio_c_out,"shutdown\n");
503                                         goto shut;
504                                         }
505                                 else
506                                         {
507                                         read_tty=1;
508                                         write_ssl=0;
509                                         break;
510                                         }
511                                 
512                         case SSL_ERROR_SYSCALL:
513                                 if ((k != 0) || (cbuf_len != 0))
514                                         {
515                                         BIO_printf(bio_err,"write:errno=%d\n",
516                                                 get_last_socket_error());
517                                         goto shut;
518                                         }
519                                 else
520                                         {
521                                         read_tty=1;
522                                         write_ssl=0;
523                                         }
524                                 break;
525                         case SSL_ERROR_SSL:
526                                 ERR_print_errors(bio_err);
527                                 goto shut;
528                                 }
529                         }
530 #ifndef WINDOWS
531                 else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
532                         {
533                         i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);
534
535                         if (i <= 0)
536                                 {
537                                 BIO_printf(bio_c_out,"DONE\n");
538                                 goto shut;
539                                 /* goto end; */
540                                 }
541
542                         sbuf_len-=i;;
543                         sbuf_off+=i;
544                         if (sbuf_len <= 0)
545                                 {
546                                 read_ssl=1;
547                                 write_tty=0;
548                                 }
549                         }
550 #endif
551                 else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
552                         {
553 #ifdef RENEG
554 { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } }
555 #endif
556 #if 1
557                         k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
558 #else
559 /* Demo for pending and peek :-) */
560                         k=SSL_read(con,sbuf,16);
561 { char zbuf[10240]; 
562 printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
563 }
564 #endif
565
566                         switch (SSL_get_error(con,k))
567                                 {
568                         case SSL_ERROR_NONE:
569                                 if (k <= 0)
570                                         goto end;
571                                 sbuf_off=0;
572                                 sbuf_len=k;
573
574                                 read_ssl=0;
575                                 write_tty=1;
576                                 break;
577                         case SSL_ERROR_WANT_WRITE:
578                                 BIO_printf(bio_c_out,"read W BLOCK\n");
579                                 write_ssl=1;
580                                 read_tty=0;
581                                 break;
582                         case SSL_ERROR_WANT_READ:
583                                 BIO_printf(bio_c_out,"read R BLOCK\n");
584                                 write_tty=0;
585                                 read_ssl=1;
586                                 if ((read_tty == 0) && (write_ssl == 0))
587                                         write_ssl=1;
588                                 break;
589                         case SSL_ERROR_WANT_X509_LOOKUP:
590                                 BIO_printf(bio_c_out,"read X BLOCK\n");
591                                 break;
592                         case SSL_ERROR_SYSCALL:
593                                 BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
594                                 goto shut;
595                         case SSL_ERROR_ZERO_RETURN:
596                                 BIO_printf(bio_c_out,"closed\n");
597                                 goto shut;
598                         case SSL_ERROR_SSL:
599                                 ERR_print_errors(bio_err);
600                                 goto shut;
601                                 /* break; */
602                                 }
603                         }
604
605 #ifndef WINDOWS
606                 else if (FD_ISSET(fileno(stdin),&readfds))
607                         {
608                         i=read(fileno(stdin),cbuf,BUFSIZZ);
609
610                         if ((!c_quiet) && ((i <= 0) || (cbuf[0] == 'Q')))
611                                 {
612                                 BIO_printf(bio_err,"DONE\n");
613                                 goto shut;
614                                 }
615
616                         if ((!c_quiet) && (cbuf[0] == 'R'))
617                                 {
618                                 BIO_printf(bio_err,"RENEGOTIATING\n");
619                                 SSL_renegotiate(con);
620                                 cbuf_len=0;
621                                 }
622                         else
623                                 {
624                                 cbuf_len=i;
625                                 cbuf_off=0;
626                                 }
627
628                         write_ssl=1;
629                         read_tty=0;
630                         }
631 #endif
632                 }
633 shut:
634         SSL_shutdown(con);
635         SHUTDOWN(SSL_get_fd(con));
636         ret=0;
637 end:
638         if (con != NULL) SSL_free(con);
639         if (con2 != NULL) SSL_free(con2);
640         if (ctx != NULL) SSL_CTX_free(ctx);
641         if (cbuf != NULL) { memset(cbuf,0,BUFSIZZ); Free(cbuf); }
642         if (sbuf != NULL) { memset(sbuf,0,BUFSIZZ); Free(sbuf); }
643         if (bio_c_out != NULL)
644                 {
645                 BIO_free(bio_c_out);
646                 bio_c_out=NULL;
647                 }
648         EXIT(ret);
649         }
650
651
652 static void print_stuff(BIO *bio, SSL *s, int full)
653         {
654         X509 *peer=NULL;
655         char *p;
656         static char *space="                ";
657         char buf[BUFSIZ];
658         STACK_OF(X509) *sk;
659         STACK_OF(X509_NAME) *sk2;
660         SSL_CIPHER *c;
661         X509_NAME *xn;
662         int j,i;
663
664         if (full)
665                 {
666                 sk=SSL_get_peer_cert_chain(s);
667                 if (sk != NULL)
668                         {
669                         BIO_printf(bio,"---\nCertificate chain\n");
670                         for (i=0; i<sk_X509_num(sk); i++)
671                                 {
672                                 X509_NAME_oneline(X509_get_subject_name(
673                                         sk_X509_value(sk,i)),buf,BUFSIZ);
674                                 BIO_printf(bio,"%2d s:%s\n",i,buf);
675                                 X509_NAME_oneline(X509_get_issuer_name(
676                                         sk_X509_value(sk,i)),buf,BUFSIZ);
677                                 BIO_printf(bio,"   i:%s\n",buf);
678                                 if (c_showcerts)
679                                         PEM_write_bio_X509(bio,sk_X509_value(sk,i));
680                                 }
681                         }
682
683                 BIO_printf(bio,"---\n");
684                 peer=SSL_get_peer_certificate(s);
685                 if (peer != NULL)
686                         {
687                         BIO_printf(bio,"Server certificate\n");
688                         if (!c_showcerts) /* Redundant if we showed the whole chain */
689                                 PEM_write_bio_X509(bio,peer);
690                         X509_NAME_oneline(X509_get_subject_name(peer),
691                                 buf,BUFSIZ);
692                         BIO_printf(bio,"subject=%s\n",buf);
693                         X509_NAME_oneline(X509_get_issuer_name(peer),
694                                 buf,BUFSIZ);
695                         BIO_printf(bio,"issuer=%s\n",buf);
696                         }
697                 else
698                         BIO_printf(bio,"no peer certificate available\n");
699
700                 sk2=SSL_get_client_CA_list(s);
701                 if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))
702                         {
703                         BIO_printf(bio,"---\nAcceptable client certificate CA names\n");
704                         for (i=0; i<sk_X509_NAME_num(sk2); i++)
705                                 {
706                                 xn=sk_X509_NAME_value(sk2,i);
707                                 X509_NAME_oneline(xn,buf,sizeof(buf));
708                                 BIO_write(bio,buf,strlen(buf));
709                                 BIO_write(bio,"\n",1);
710                                 }
711                         }
712                 else
713                         {
714                         BIO_printf(bio,"---\nNo client certificate CA names sent\n");
715                         }
716                 p=SSL_get_shared_ciphers(s,buf,BUFSIZ);
717                 if (p != NULL)
718                         {
719                         BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");
720                         j=i=0;
721                         while (*p)
722                                 {
723                                 if (*p == ':')
724                                         {
725                                         BIO_write(bio,space,15-j%25);
726                                         i++;
727                                         j=0;
728                                         BIO_write(bio,((i%3)?" ":"\n"),1);
729                                         }
730                                 else
731                                         {
732                                         BIO_write(bio,p,1);
733                                         j++;
734                                         }
735                                 p++;
736                                 }
737                         BIO_write(bio,"\n",1);
738                         }
739
740                 BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
741                         BIO_number_read(SSL_get_rbio(s)),
742                         BIO_number_written(SSL_get_wbio(s)));
743                 }
744         BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
745         c=SSL_get_current_cipher(s);
746         BIO_printf(bio,"%s, Cipher is %s\n",
747                 SSL_CIPHER_get_version(c),
748                 SSL_CIPHER_get_name(c));
749         if (peer != NULL) {
750                 EVP_PKEY *pktmp;
751                 pktmp = X509_get_pubkey(peer);
752                 BIO_printf(bio,"Server public key is %d bit\n",
753                                                          EVP_PKEY_bits(pktmp));
754                 EVP_PKEY_free(pktmp);
755         }
756         SSL_SESSION_print(bio,SSL_get_session(s));
757         BIO_printf(bio,"---\n");
758         if (peer != NULL)
759                 X509_free(peer);
760         }
761