|
HP Open Source Security for OpenVMS Volume 2: HP SSL for OpenVMS > Chapter 5 Example Programs
Simple SSL Client Program
The following is the program listing of the SSL$SIMPLE_CLI.C
example program. /* * ++ * FACILITY: * * Simplest SSL Client * * ABSTRACT: * * This is an example of an SSL client with minimum functionality. * The socket APIs are used to handle TCP/IP operations. * * This SSL client verifies the server's certificate against the CA * certificate loaded in the client. * * This SSL client does not load its own certificate and key because * the SSL server does not request nor verify the client certificate. *
|
|
|
*/ /* Assumptions, Build, Configuration, and Execution Instructions */ /* * ASSUMPTIONS: * * The following are assumed to be true for the * execution of this program to succeed: * * - SSL is installed and started on this system. * * - this server program, and its accompanying client * program are run on the same system, but in different * processes. * * - the certificate and keys referenced by this program * reside in the same directory as this program. There * is a command procedure, SSL$EXAMPLES_SETUP.COM, to * help set up the certificates and keys. * * * BUILD INSTRUCTIONS: * * To build this example program use commands of the form, * * For a 32-bit application using only SSL APIs needs to run the * following commands for SSL_APP.C . * ----------------------------------------------------------------- * $CC/POINTER_SIZE=32/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES SSL_APP.C * $LINK SSL_APP.OBJ, VMS_DECC_OPTIONS.OPT/OPT * ----------------------------------------------------------------- * VMS_DECC_OPTIONS.OPT should include the following lines. * ------------------------------------------------- * SYS$LIBRARY:SSL$LIBCRYPTO_SHR32.EXE/SHARE * SYS$LIBRARY:SSL$LIBSSL_SHR32.EXE/SHARE * ------------------------------------------------- * * Creating a 64-bit application of SSL_APP.C should run the * following commands. * ----------------------------------------------------------------- * $CC/POINTER_SIZE=64/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES SSL_APP.C * $LINK SSL_APP.OBJ, VMS_DECC_OPTIONS.OPT/OPT * ----------------------------------------------------------------- * VMS_DECC_OPTIONS.OPT should include the following lines. * ------------------------------------------------- * SYS$LIBRARY:SSL$LIBCRYPTO_SHR.EXE/SHARE * SYS$LIBRARY:SSL$LIBSSL_SHR.EXE/SHARE * ------------------------------------------------- * * * CONFIGURATION INSTRUCTIONS: * * * RUN INSTRUCTIONS: * * To run this example program: * * 1) Start the server program, * * $ run server on this system * * 2) Start the client program on this same system, * * $ run client * */ #include <stdio.h> #include <string.h> #include <errno.h> #include <netdb.h> #include <unistd.h> #ifdef __VMS #include <socket.h> #include <inet.h> #include <in.h> #else #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #endif #include <openssl/crypto.h> #include <openssl/ssl.h> #include <openssl/err.h> #define RETURN_NULL(x) if ((x)==NULL) exit (1) #define RETURN_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } #define RETURN_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(1); } static int verify_callback(int ok, X509_STORE_CTX *ctx); #define RSA_CLIENT_CERT "client.crt" #define RSA_CLIENT_KEY "client.key" #define RSA_CLIENT_CA_CERT "client_ca.crt" #define RSA_CLIENT_CA_PATH "sys$common:[syshlp.examples.ssl]" #define ON 1 #define OFF 0 void main() { int err;
|
|
|
int verify_client = OFF; /* To verify a client certificate, set ON */ int sock; struct sockaddr_in server_addr; char *str; char buf [4096]; char hello[80];
|
SSL_CTX *ctx; SSL *ssl; SSL_METHOD *meth; X509 *server_cert; EVP_PKEY *pkey;
|
|
|
short int s_port = 5555; const char *s_ipaddr = "127.0.0.1"; /*----------------------------------------------------------*/ printf ("Message to be sent to the SSL server: "); fgets (hello, 80, stdin); /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */ meth = SSLv3_method(); /* Create an SSL_CTX structure */ ctx = SSL_CTX_new(meth); RETURN_NULL(ctx); /*----------------------------------------------------------*/ if(verify_client == ON) { /* Load the client certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(ctx, RSA_CLIENT_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Load the private-key corresponding to the client certificate */ if (SSL_CTX_use_PrivateKey_file(ctx, RSA_CLIENT_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Check if the client certificate and private-key matches */ if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr,"Private key does not match the certificate public key\n"); exit(1); } } /* Load the RSA CA certificate into the SSL_CTX structure */ /* This will allow this client to verify the server's */ /* certificate. */
|
|
|
if (!SSL_CTX_load_verify_locations(ctx, RSA_CLIENT_CA_CERT, NULL)) { ERR_print_errors_fp(stderr); exit(1); } /* Set flag in context to require peer (server) certificate */ /* verification */ SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); SSL_CTX_set_verify_depth(ctx,1); /* ------------------------------------------------------------- */ /* Set up a TCP socket */ sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); RETURN_ERR(sock, "socket"); memset (&server_addr, '\0', sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(s_port); /* Server Port number */ server_addr.sin_addr.s_addr = inet_addr(s_ipaddr); /* Server IP */ /* Establish a TCP/IP connection to the SSL client */ err = connect(sock, (struct sockaddr*) &server_addr, sizeof(server_addr)); RETURN_ERR(err, "connect"); /* ----------------------------------------------- */ /* An SSL structure is created */ ssl = SSL_new (ctx); RETURN_NULL(ssl); /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(ssl, sock); /* Perform SSL Handshake on the SSL client */ err = SSL_connect(ssl); RETURN_SSL(err); /* Informational output (optional) */ printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); /* Get the server's certificate (optional) */ server_cert = SSL_get_peer_certificate (ssl); if (server_cert != NULL) { printf ("Server certificate:\n");
|
|
|
str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0); RETURN_NULL(str); printf ("\t subject: %s\n", str); free (str); str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0); RETURN_NULL(str); printf ("\t issuer: %s\n", str); free(str); X509_free (server_cert);
|
} else printf("The SSL server does not have certificate.\n"); /*-------- DATA EXCHANGE - send message and receive reply. -------*/ /* Send data to the SSL server */ err = SSL_write(ssl, hello, strlen(hello)); RETURN_SSL(err); /* Receive data from the SSL server */ err = SSL_read(ssl, buf, sizeof(buf)-1); RETURN_SSL(err); buf[err] = '\0'; printf ("Received %d chars:'%s'\n", err, buf); /*--------------- SSL closure ---------------*/ /* Shutdown the client side of the SSL connection */ err = SSL_shutdown(ssl); RETURN_SSL(err); /* Terminate communication on a socket */ err = close(sock); RETURN_ERR(err, "close"); /* Free the SSL structure */ SSL_free(ssl); /* Free the SSL_CTX structure */ SSL_CTX_free(ctx); }
|
|
|