Annotation of embedaddon/axTLS/samples/c/axssl.c, revision 1.1

1.1     ! misho       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>