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>