Return to axssl.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / axTLS / samples / c |
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: }