Add axTLS sourcecode
[project/luci.git] / libs / nixio / axTLS / samples / c / axssl.c
1 /*
2  * Copyright (c) 2007, Cameron Rich
3  * 
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, 
10  *   this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice, 
12  *   this list of conditions and the following disclaimer in the documentation 
13  *   and/or other materials provided with the distribution.
14  * * Neither the name of the axTLS project nor the names of its contributors 
15  *   may be used to endorse or promote products derived from this software 
16  *   without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /**
32  * Demonstrate the use of the axTLS library in C with a set of 
33  * command-line parameters similar to openssl. In fact, openssl clients 
34  * should be able to communicate with axTLS servers and visa-versa.
35  *
36  * This code has various bits enabled depending on the configuration. To enable
37  * the most interesting version, compile with the 'full mode' enabled.
38  *
39  * To see what options you have, run the following:
40  * > axssl s_server -?
41  * > axssl s_client -?
42  *
43  * The axtls shared library must be in the same directory or be found 
44  * by the OS.
45  */
46 #include <string.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include "ssl.h"
50
51 /* define standard input */
52 #ifndef STDIN_FILENO
53 #define STDIN_FILENO        0
54 #endif
55
56 static void do_server(int argc, char *argv[]);
57 static void print_options(char *option);
58 static void print_server_options(char *option);
59 static void do_client(int argc, char *argv[]);
60 static void print_client_options(char *option);
61 static void display_cipher(SSL *ssl);
62 static void display_session_id(SSL *ssl);
63
64 /**
65  * Main entry point. Doesn't do much except works out whether we are a client
66  * or a server.
67  */
68 int main(int argc, char *argv[])
69 {
70 #ifdef WIN32
71     WSADATA wsaData;
72     WORD wVersionRequested = MAKEWORD(2, 2);
73     WSAStartup(wVersionRequested, &wsaData);
74 #elif !defined(CONFIG_PLATFORM_SOLARIS)
75     signal(SIGPIPE, SIG_IGN);           /* ignore pipe errors */
76 #endif
77
78     if (argc == 2 && strcmp(argv[1], "version") == 0)
79     {
80         printf("axssl %s %s\n", ssl_version(), __DATE__);
81         exit(0);
82     }
83
84     if (argc < 2 || (
85                 strcmp(argv[1], "s_server") && strcmp(argv[1], "s_client")))
86         print_options(argc > 1 ? argv[1] : "");
87
88     strcmp(argv[1], "s_server") ? 
89         do_client(argc, argv) : do_server(argc, argv);
90     return 0;
91 }
92
93 /**
94  * Implement the SSL server logic. 
95  */
96 static void do_server(int argc, char *argv[])
97 {
98     int i = 2;
99     uint16_t port = 4433;
100     uint32_t options = SSL_DISPLAY_CERTS;
101     int client_fd;
102     SSL_CTX *ssl_ctx;
103     int server_fd, res = 0;
104     socklen_t client_len;
105 #ifndef CONFIG_SSL_SKELETON_MODE
106     char *private_key_file = NULL;
107     const char *password = NULL;
108     char **cert;
109     int cert_index = 0;
110     int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
111 #endif
112 #ifdef WIN32
113     char yes = 1;
114 #else
115     int yes = 1;
116 #endif
117     struct sockaddr_in serv_addr;
118     struct sockaddr_in client_addr;
119     int quiet = 0;
120 #ifdef CONFIG_SSL_CERT_VERIFICATION
121     int ca_cert_index = 0;
122     int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
123     char **ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
124 #endif
125     fd_set read_set;
126
127 #ifndef CONFIG_SSL_SKELETON_MODE
128     cert = (char **)calloc(1, sizeof(char *)*cert_size);
129 #endif
130
131     while (i < argc)
132     {
133         if (strcmp(argv[i], "-accept") == 0)
134         {
135             if (i >= argc-1)
136             {
137                 print_server_options(argv[i]);
138             }
139
140             port = atoi(argv[++i]);
141         }
142 #ifndef CONFIG_SSL_SKELETON_MODE
143         else if (strcmp(argv[i], "-cert") == 0)
144         {
145             if (i >= argc-1 || cert_index >= cert_size)
146             {
147                 print_server_options(argv[i]);
148             }
149
150             cert[cert_index++] = argv[++i];
151         }
152         else if (strcmp(argv[i], "-key") == 0)
153         {
154             if (i >= argc-1)
155             {
156                 print_server_options(argv[i]);
157             }
158
159             private_key_file = argv[++i];
160             options |= SSL_NO_DEFAULT_KEY;
161         }
162         else if (strcmp(argv[i], "-pass") == 0)
163         {
164             if (i >= argc-1)
165             {
166                 print_server_options(argv[i]);
167             }
168
169             password = argv[++i];
170         }
171 #endif
172         else if (strcmp(argv[i], "-quiet") == 0)
173         {
174             quiet = 1;
175             options &= ~SSL_DISPLAY_CERTS;
176         }
177 #ifdef CONFIG_SSL_CERT_VERIFICATION
178         else if (strcmp(argv[i], "-verify") == 0)
179         {
180             options |= SSL_CLIENT_AUTHENTICATION;
181         }
182         else if (strcmp(argv[i], "-CAfile") == 0)
183         {
184             if (i >= argc-1 || ca_cert_index >= ca_cert_size)
185             {
186                 print_server_options(argv[i]);
187             }
188
189             ca_cert[ca_cert_index++] = argv[++i];
190         }
191 #endif
192 #ifdef CONFIG_SSL_FULL_MODE
193         else if (strcmp(argv[i], "-debug") == 0)
194         {
195             options |= SSL_DISPLAY_BYTES;
196         }
197         else if (strcmp(argv[i], "-state") == 0)
198         {
199             options |= SSL_DISPLAY_STATES;
200         }
201         else if (strcmp(argv[i], "-show-rsa") == 0)
202         {
203             options |= SSL_DISPLAY_RSA;
204         }
205 #endif
206         else    /* don't know what this is */
207         {
208             print_server_options(argv[i]);
209         }
210
211         i++;
212     }
213
214     if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL)
215     {
216         fprintf(stderr, "Error: Server context is invalid\n");
217         exit(1);
218     }
219
220 #ifndef CONFIG_SSL_SKELETON_MODE
221     if (private_key_file)
222     {
223         int obj_type = SSL_OBJ_RSA_KEY;
224         
225         /* auto-detect the key type from the file extension */
226         if (strstr(private_key_file, ".p8"))
227             obj_type = SSL_OBJ_PKCS8;
228         else if (strstr(private_key_file, ".p12"))
229             obj_type = SSL_OBJ_PKCS12;
230
231         if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
232         {
233             fprintf(stderr, "Error: Private key '%s' is undefined.\n", 
234                                                         private_key_file);
235             exit(1);
236         }
237     }
238
239     for (i = 0; i < cert_index; i++)
240     {
241         if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL))
242         {
243             printf("Certificate '%s' is undefined.\n", cert[i]);
244             exit(1);
245         }
246     }
247 #endif
248
249 #ifdef CONFIG_SSL_CERT_VERIFICATION
250     for (i = 0; i < ca_cert_index; i++)
251     {
252         if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL))
253         {
254             printf("Certificate '%s' is undefined.\n", ca_cert[i]);
255             exit(1);
256         }
257     }
258
259     free(ca_cert);
260 #endif
261 #ifndef CONFIG_SSL_SKELETON_MODE
262     free(cert);
263 #endif
264
265     /* Create socket for incoming connections */
266     if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
267     {
268         perror("socket");
269         return;
270     }
271       
272     setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
273
274     /* Construct local address structure */
275     memset(&serv_addr, 0, sizeof(serv_addr));      /* Zero out structure */
276     serv_addr.sin_family = AF_INET;                /* Internet address family */
277     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
278     serv_addr.sin_port = htons(port);              /* Local port */
279
280     /* Bind to the local address */
281     if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
282     {
283         perror("bind");
284         exit(1);
285     }
286
287     if (listen(server_fd, 5) < 0)
288     {
289         perror("listen");
290         exit(1);
291     }
292
293     client_len = sizeof(client_addr);
294
295     /*************************************************************************
296      * This is where the interesting stuff happens. Up until now we've
297      * just been setting up sockets etc. Now we do the SSL handshake.
298      *************************************************************************/
299     for (;;)
300     {
301         SSL *ssl;
302         int reconnected = 0;
303
304         if (!quiet)
305         {
306             printf("ACCEPT\n");
307             TTY_FLUSH();
308         }
309
310         if ((client_fd = accept(server_fd, 
311                 (struct sockaddr *)&client_addr, &client_len)) < 0)
312         {
313             res = 1;
314             break;
315         }
316
317         ssl = ssl_server_new(ssl_ctx, client_fd);
318
319         /* now read (and display) whatever the client sends us */
320         for (;;)
321         {
322             /* allow parallel reading of client and standard input */
323             FD_ZERO(&read_set);
324             FD_SET(client_fd, &read_set);
325
326 #ifndef WIN32
327             /* win32 doesn't like mixing up stdin and sockets */
328             if (isatty(STDIN_FILENO))/* but only if we are in an active shell */
329             {
330                 FD_SET(STDIN_FILENO, &read_set);
331             }
332
333             if ((res = select(client_fd+1, &read_set, NULL, NULL, NULL)) > 0)
334             {
335                uint8_t buf[1024];
336
337                 /* read standard input? */
338                 if (FD_ISSET(STDIN_FILENO, &read_set))
339                 {
340                     if (fgets((char *)buf, sizeof(buf), stdin) == NULL)
341                     {
342                         res = SSL_ERROR_CONN_LOST;
343                     }
344                     else
345                     {
346                         /* small hack to check renegotiation */
347                         if (buf[0] == 'r' && (buf[1] == '\n' || buf[1] == '\r'))
348                         {
349                             res = ssl_renegotiate(ssl);
350                         }
351                         else    /* write our ramblings to the client */
352                         {
353                             res = ssl_write(ssl, buf, strlen((char *)buf)+1);
354                         }
355                     }
356                 }
357                 else    /* a socket read */
358 #endif
359                 {
360                     /* keep reading until we get something interesting */
361                     uint8_t *read_buf;
362
363                     if ((res = ssl_read(ssl, &read_buf)) == SSL_OK)
364                     {
365                         /* are we in the middle of doing a handshake? */
366                         if (ssl_handshake_status(ssl) != SSL_OK)
367                         {
368                             reconnected = 0;
369                         }
370                         else if (!reconnected)
371                         {
372                             /* we are connected/reconnected */
373                             if (!quiet)
374                             {
375                                 display_session_id(ssl);
376                                 display_cipher(ssl);
377                             }
378
379                             reconnected = 1;
380                         }
381                     }
382
383                     if (res > SSL_OK)    /* display our interesting output */
384                     {
385                         printf("%s", read_buf);
386                         TTY_FLUSH();
387                     }
388                     else if (res < SSL_OK && !quiet)
389                     {
390                         ssl_display_error(res);
391                     }
392                 }
393 #ifndef WIN32
394             }
395 #endif
396
397             if (res < SSL_OK)
398             {
399                 if (!quiet)
400                 {
401                     printf("CONNECTION CLOSED\n");
402                     TTY_FLUSH();
403                 }
404
405                 break;
406             }
407         }
408
409         /* client was disconnected or the handshake failed. */
410         ssl_free(ssl);
411         SOCKET_CLOSE(client_fd);
412     }
413
414     ssl_ctx_free(ssl_ctx);
415 }
416
417 /**
418  * Implement the SSL client logic.
419  */
420 static void do_client(int argc, char *argv[])
421 {
422 #ifdef CONFIG_SSL_ENABLE_CLIENT
423     int res, i = 2;
424     uint16_t port = 4433;
425     uint32_t options = SSL_SERVER_VERIFY_LATER|SSL_DISPLAY_CERTS;
426     int client_fd;
427     char *private_key_file = NULL;
428     struct sockaddr_in client_addr;
429     struct hostent *hostent;
430     int reconnect = 0;
431     uint32_t sin_addr;
432     SSL_CTX *ssl_ctx;
433     SSL *ssl = NULL;
434     int quiet = 0;
435     int cert_index = 0, ca_cert_index = 0;
436     int cert_size, ca_cert_size;
437     char **ca_cert, **cert;
438     uint8_t session_id[SSL_SESSION_ID_SIZE];
439     fd_set read_set;
440     const char *password = NULL;
441
442     FD_ZERO(&read_set);
443     sin_addr = inet_addr("127.0.0.1");
444     cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
445     ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
446     ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
447     cert = (char **)calloc(1, sizeof(char *)*cert_size);
448
449     while (i < argc)
450     {
451         if (strcmp(argv[i], "-connect") == 0)
452         {
453             char *host, *ptr;
454
455             if (i >= argc-1)
456             {
457                 print_client_options(argv[i]);
458             }
459
460             host = argv[++i];
461             if ((ptr = strchr(host, ':')) == NULL)
462             {
463                 print_client_options(argv[i]);
464             }
465
466             *ptr++ = 0;
467             port = atoi(ptr);
468             hostent = gethostbyname(host);
469
470             if (hostent == NULL)
471             {
472                 print_client_options(argv[i]);
473             }
474
475             sin_addr = *((uint32_t **)hostent->h_addr_list)[0];
476         }
477         else if (strcmp(argv[i], "-cert") == 0)
478         {
479             if (i >= argc-1 || cert_index >= cert_size)
480             {
481                 print_client_options(argv[i]);
482             }
483
484             cert[cert_index++] = argv[++i];
485         }
486         else if (strcmp(argv[i], "-key") == 0)
487         {
488             if (i >= argc-1)
489             {
490                 print_client_options(argv[i]);
491             }
492
493             private_key_file = argv[++i];
494             options |= SSL_NO_DEFAULT_KEY;
495         }
496         else if (strcmp(argv[i], "-CAfile") == 0)
497         {
498             if (i >= argc-1 || ca_cert_index >= ca_cert_size)
499             {
500                 print_client_options(argv[i]);
501             }
502
503             ca_cert[ca_cert_index++] = argv[++i];
504         }
505         else if (strcmp(argv[i], "-verify") == 0)
506         {
507             options &= ~SSL_SERVER_VERIFY_LATER;
508         }
509         else if (strcmp(argv[i], "-reconnect") == 0)
510         {
511             reconnect = 4;
512         }
513         else if (strcmp(argv[i], "-quiet") == 0)
514         {
515             quiet = 1;
516             options &= ~SSL_DISPLAY_CERTS;
517         }
518         else if (strcmp(argv[i], "-pass") == 0)
519         {
520             if (i >= argc-1)
521             {
522                 print_client_options(argv[i]);
523             }
524
525             password = argv[++i];
526         }
527 #ifdef CONFIG_SSL_FULL_MODE
528         else if (strcmp(argv[i], "-debug") == 0)
529         {
530             options |= SSL_DISPLAY_BYTES;
531         }
532         else if (strcmp(argv[i], "-state") == 0)
533         {
534             options |= SSL_DISPLAY_STATES;
535         }
536         else if (strcmp(argv[i], "-show-rsa") == 0)
537         {
538             options |= SSL_DISPLAY_RSA;
539         }
540 #endif
541         else    /* don't know what this is */
542         {
543             print_client_options(argv[i]);
544         }
545
546         i++;
547     }
548
549     if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL)
550     {
551         fprintf(stderr, "Error: Client context is invalid\n");
552         exit(1);
553     }
554
555     if (private_key_file)
556     {
557         int obj_type = SSL_OBJ_RSA_KEY;
558         
559         /* auto-detect the key type from the file extension */
560         if (strstr(private_key_file, ".p8"))
561             obj_type = SSL_OBJ_PKCS8;
562         else if (strstr(private_key_file, ".p12"))
563             obj_type = SSL_OBJ_PKCS12;
564
565         if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
566         {
567             fprintf(stderr, "Error: Private key '%s' is undefined.\n", 
568                                                         private_key_file);
569             exit(1);
570         }
571     }
572
573     for (i = 0; i < cert_index; i++)
574     {
575         if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL))
576         {
577             printf("Certificate '%s' is undefined.\n", cert[i]);
578             exit(1);
579         }
580     }
581
582     for (i = 0; i < ca_cert_index; i++)
583     {
584         if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL))
585         {
586             printf("Certificate '%s' is undefined.\n", ca_cert[i]);
587             exit(1);
588         }
589     }
590
591     free(cert);
592     free(ca_cert);
593
594     /*************************************************************************
595      * This is where the interesting stuff happens. Up until now we've
596      * just been setting up sockets etc. Now we do the SSL handshake.
597      *************************************************************************/
598     client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
599     memset(&client_addr, 0, sizeof(client_addr));
600     client_addr.sin_family = AF_INET;
601     client_addr.sin_port = htons(port);
602     client_addr.sin_addr.s_addr = sin_addr;
603
604     if (connect(client_fd, (struct sockaddr *)&client_addr, 
605                 sizeof(client_addr)) < 0)
606     {
607         perror("connect");
608         exit(1);
609     }
610
611     if (!quiet)
612     {
613         printf("CONNECTED\n");
614         TTY_FLUSH();
615     }
616
617     /* Try session resumption? */
618     if (reconnect)
619     {
620         while (reconnect--)
621         {
622             ssl = ssl_client_new(ssl_ctx, client_fd, session_id,
623                     sizeof(session_id));
624             if ((res = ssl_handshake_status(ssl)) != SSL_OK)
625             {
626                 if (!quiet)
627                 {
628                     ssl_display_error(res);
629                 }
630
631                 ssl_free(ssl);
632                 exit(1);
633             }
634
635             display_session_id(ssl);
636             memcpy(session_id, ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);
637
638             if (reconnect)
639             {
640                 ssl_free(ssl);
641                 SOCKET_CLOSE(client_fd);
642
643                 client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
644                 connect(client_fd, (struct sockaddr *)&client_addr, 
645                         sizeof(client_addr));
646             }
647         }
648     }
649     else
650     {
651         ssl = ssl_client_new(ssl_ctx, client_fd, NULL, 0);
652     }
653
654     /* check the return status */
655     if ((res = ssl_handshake_status(ssl)) != SSL_OK)
656     {
657         if (!quiet)
658         {
659             ssl_display_error(res);
660         }
661
662         exit(1);
663     }
664
665     if (!quiet)
666     {
667         const char *common_name = ssl_get_cert_dn(ssl,
668                 SSL_X509_CERT_COMMON_NAME);
669         if (common_name)
670         {
671             printf("Common Name:\t\t\t%s\n", common_name);
672         }
673
674         display_session_id(ssl);
675         display_cipher(ssl);
676     }
677
678     for (;;)
679     {
680         uint8_t buf[1024];
681         res = SSL_OK;
682
683         /* allow parallel reading of server and standard input */
684         FD_SET(client_fd, &read_set);
685 #ifndef WIN32
686         /* win32 doesn't like mixing up stdin and sockets */
687         FD_SET(STDIN_FILENO, &read_set);
688
689         if ((res = select(client_fd+1, &read_set, NULL, NULL, NULL)) > 0)
690         {
691             /* read standard input? */
692             if (FD_ISSET(STDIN_FILENO, &read_set))
693 #endif
694             {
695                 if (fgets((char *)buf, sizeof(buf), stdin) == NULL)
696                 {
697                     /* bomb out of here */
698                     ssl_free(ssl);
699                     break;
700                 }
701                 else
702                 {
703                     /* small hack to check renegotiation */
704                     if (buf[0] == 'R' && (buf[1] == '\n' || buf[1] == '\r'))
705                     {
706                         res = ssl_renegotiate(ssl);
707                     }
708                     else
709                     {
710                         res = ssl_write(ssl, buf, strlen((char *)buf)+1);
711                     }
712                 }
713             }
714 #ifndef WIN32
715             else    /* a socket read */
716             {
717                 uint8_t *read_buf;
718
719                 res = ssl_read(ssl, &read_buf);
720
721                 if (res > 0)    /* display our interesting output */
722                 {
723                     printf("%s", read_buf);
724                     TTY_FLUSH();
725                 }
726             }
727         }
728 #endif
729
730         if (res < 0)
731         {
732             if (!quiet)
733             {
734                 ssl_display_error(res);
735             }
736
737             break;      /* get outta here */
738         }
739     }
740
741     ssl_ctx_free(ssl_ctx);
742     SOCKET_CLOSE(client_fd);
743 #else
744     print_client_options(argv[1]);
745 #endif
746 }
747
748 /**
749  * We've had some sort of command-line error. Print out the basic options.
750  */
751 static void print_options(char *option)
752 {
753     printf("axssl: Error: '%s' is an invalid command.\n", option);
754     printf("usage: axssl [s_server|s_client|version] [args ...]\n");
755     exit(1);
756 }
757
758 /**
759  * We've had some sort of command-line error. Print out the server options.
760  */
761 static void print_server_options(char *option)
762 {
763 #ifndef CONFIG_SSL_SKELETON_MODE
764     int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
765 #endif
766 #ifdef CONFIG_SSL_CERT_VERIFICATION
767     int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
768 #endif
769
770     printf("unknown option %s\n", option);
771     printf("usage: s_server [args ...]\n");
772     printf(" -accept arg\t- port to accept on (default is 4433)\n");
773 #ifndef CONFIG_SSL_SKELETON_MODE
774     printf(" -cert arg\t- certificate file to add (in addition to default)"
775                                     " to chain -\n"
776           "\t\t  Can repeat up to %d times\n", cert_size);
777     printf(" -key arg\t- Private key file to use\n");
778     printf(" -pass\t\t- private key file pass phrase source\n");
779 #endif
780     printf(" -quiet\t\t- No server output\n");
781 #ifdef CONFIG_SSL_CERT_VERIFICATION
782     printf(" -verify\t- turn on peer certificate verification\n");
783     printf(" -CAfile arg\t- Certificate authority\n");
784     printf("\t\t  Can repeat up to %d times\n", ca_cert_size);
785 #endif
786 #ifdef CONFIG_SSL_FULL_MODE
787     printf(" -debug\t\t- Print more output\n");
788     printf(" -state\t\t- Show state messages\n");
789     printf(" -show-rsa\t- Show RSA state\n");
790 #endif
791     exit(1);
792 }
793
794 /**
795  * We've had some sort of command-line error. Print out the client options.
796  */
797 static void print_client_options(char *option)
798 {
799 #ifdef CONFIG_SSL_ENABLE_CLIENT
800     int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
801     int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
802 #endif
803
804     printf("unknown option %s\n", option);
805 #ifdef CONFIG_SSL_ENABLE_CLIENT
806     printf("usage: s_client [args ...]\n");
807     printf(" -connect host:port - who to connect to (default "
808             "is localhost:4433)\n");
809     printf(" -verify\t- turn on peer certificate verification\n");
810     printf(" -cert arg\t- certificate file to use\n");
811     printf("\t\t  Can repeat up to %d times\n", cert_size);
812     printf(" -key arg\t- Private key file to use\n");
813     printf(" -CAfile arg\t- Certificate authority\n");
814     printf("\t\t  Can repeat up to %d times\n", ca_cert_size);
815     printf(" -quiet\t\t- No client output\n");
816     printf(" -reconnect\t- Drop and re-make the connection "
817             "with the same Session-ID\n");
818     printf(" -pass\t\t- private key file pass phrase source\n");
819 #ifdef CONFIG_SSL_FULL_MODE
820     printf(" -debug\t\t- Print more output\n");
821     printf(" -state\t\t- Show state messages\n");
822     printf(" -show-rsa\t- Show RSA state\n");
823 #endif
824 #else
825     printf("Change configuration to allow this feature\n");
826 #endif
827     exit(1);
828 }
829
830 /**
831  * Display what cipher we are using 
832  */
833 static void display_cipher(SSL *ssl)
834 {
835     printf("CIPHER is ");
836     switch (ssl_get_cipher_id(ssl))
837     {
838         case SSL_AES128_SHA:
839             printf("AES128-SHA");
840             break;
841
842         case SSL_AES256_SHA:
843             printf("AES256-SHA");
844             break;
845
846         case SSL_RC4_128_SHA:
847             printf("RC4-SHA");
848             break;
849
850         case SSL_RC4_128_MD5:
851             printf("RC4-MD5");
852             break;
853
854         default:
855             printf("Unknown - %d", ssl_get_cipher_id(ssl));
856             break;
857     }
858
859     printf("\n");
860     TTY_FLUSH();
861 }
862
863 /**
864  * Display what session id we have.
865  */
866 static void display_session_id(SSL *ssl)
867 {    
868     int i;
869     const uint8_t *session_id = ssl_get_session_id(ssl);
870     int sess_id_size = ssl_get_session_id_size(ssl);
871
872     if (sess_id_size > 0)
873     {
874         printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
875         for (i = 0; i < sess_id_size; i++)
876         {
877             printf("%02x", session_id[i]);
878         }
879
880         printf("\n-----END SSL SESSION PARAMETERS-----\n");
881         TTY_FLUSH();
882     }
883 }