| 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);
 }
 | 
 |