Annotation of embedaddon/axTLS/samples/c/axssl.c, revision 1.1.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>