File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / axTLS / samples / c / axssl.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Sep 28 11:55:55 2012 UTC (13 years, 3 months ago) by misho
Branches: v1_4_8, MAIN
CVS tags: datecs, HEAD
axTLS

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>