#include /* define OpenVMS descriptors */ #include /* define 'EFN$C_ENF' event flag */ #include /* define internet related constants, */ /* functions, and structures */ #include /* define network address info */ #include /* define i/o function codes */ #include /* define network database library info */ #include /* define system service status codes */ #include /* define system service calls */ #include /* define standard i/o functions */ #include /* define standard library functions */ #include /* define string handling functions */ #include /* define condition value fields */ #include /* define tcp/ip network constants, */ #include /* structures, and functions */ /* ++ SSL ++ */ #include #include #define openssl "SSL$INCLUDE" #include #include #include #include "SSL$EXAMPLES:ssl_examples.h" /* SSL callbacks and error handling */ #undef openssl /* -- SSL -- */ /* * NAMED CONSTANTS: */ #define BUFSZ 1024 /* user input buffer size */ #define SERV_PORTNUM 3768 /* server port number */ #define SERVER_ADDR "172.16.0.4" /* * STRUCTURE DEFINITIONS: */ struct iosb { /* i/o status block */ unsigned short status; /* i/o completion status */ unsigned short bytcnt; /* bytes transferred if read/write */ void *details; /* address of buffer or parameter */ }; struct itemlst_2 { /* item-list 2 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ }; struct sockchar { /* socket characteristics buffer */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; /* ++ SSL ++ */ SSL *ssl; /* Global Pointer to SSL Object */ char buf[4096]; /* Global client data buffer */ /* -- SSL -- */ /* * FORWARD REFERENCES: */ int main( void ); /* client main */ void get_serv_addr( void * ); /* get server host address */ const int one = 1; int main( void ) { /* ++ SSL ++ */ int err; int sock; struct sockaddr_in server_addr; char *str; char hello[80] = { " --- From SSL QIO Client, Hey, Hello Server --- " }; SSL_CTX *ctx; SSL *ssl; SSL_METHOD *meth; X509 *server_cert; EVP_PKEY *pkey; short int s_port = 5555; const char *s_ipaddr = "172.16.0.4"; struct iosb iosb; /* i/o status block */ unsigned int status; /* system service return status */ unsigned short conn_channel; /* connect inet device i/o channel */ struct sockchar conn_sockchar; /* connect socket char buffer */ struct sockaddr_in serv_addr; /* server socket address structure */ struct itemlst_2 serv_itemlst; /* server item-list 2 descriptor */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of internet pseudodevice */ /* 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); conn_sockchar.prot = TCPIP$C_TCP; conn_sockchar.type = TCPIP$C_STREAM; conn_sockchar.af = TCPIP$C_AF_INET; /* * init server's item-list descriptor */ memset( &serv_itemlst, 0, sizeof(serv_itemlst) ); serv_itemlst.length = sizeof( serv_addr ); serv_itemlst.address = &serv_addr; /* * init server's socket address structure */ memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = TCPIP$C_AF_INET; serv_addr.sin_port = htons( SERV_PORTNUM ); get_serv_addr( &serv_addr.sin_addr ); /* * assign device socket */ status = sys$assign( &inet_device, /* device name */ &conn_channel, /* i/o channel */ 0, /* access mode */ 0 /* not used */ ); if ( !(status & STS$M_SUCCESS) ) { printf( "Error - Failed to assign i/o channel to TCPIP device\n" ); exit( status ); } /* * create (and bind) connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &conn_sockchar, /* p1 - socket char buffer */ 0, /* p2 */ 0, /* p3 */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) { status = iosb.status; } if ( !(status & STS$M_SUCCESS) ) { printf( "Error - Failed to create socket\n" ); exit( status ); } { const ile2 sock_opt[]={ {sizeof(one),TCPIP$C_KEEPALIVE,&one}}, options = {sizeof(sock_opt),TCPIP$C_SOCKOPT,&sock_opt}; if ( !(1 & (status = sys$qiow(EFN$C_ENF,conn_channel,IO$_SETMODE,&iosb,0,0, 0,0,0,0,&options,0))) || !(iosb.status & 1) ) lib$signal((1 & status)?iosb.status:status); } /* * connect to specified host and port number */ printf( " Initiated connection to host: %s, port: %d\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port) ); status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_ACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &serv_itemlst, /* p3 - remote socket name */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) { status = iosb.status; } if ( !(status & STS$M_SUCCESS) ) { printf( "Error - Failed to connect to server\n" ); exit( status ); } getchar(); /* ++ SSL ++ */ /* ----------------------------------------------- */ /* An SSL structure is created */ ssl = SSL_new (ctx); RETURN_NULL(ssl); /* Set informational callback routine */ SSL_set_info_callback( ssl , get_info ); /* Assign the socket channel into the SSL structure (SSL and socket without BIO) */ sock = decc$socket_fd ( conn_channel ); err = SSL_set_fd( ssl , sock ); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during CLIENT assigning socket to SSL object"); /* Perform SSL Handshake on the SSL client */ err = SSL_connect( ssl ); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during CLIENT connect to SERVER"); /* Informational output (optional) */ printf (" SSL connection using %s\n", SSL_get_cipher (ssl)); /* ** Get the server's certificate (optional) but, ** we do set the SSL_VERIFY_PEER flag. ** - see - SSL_CTX_set_verify() */ 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(" Error - The SSL server does not have certificate.\n"); /*--------------- DATA EXCHANGE - send message and receive reply. ---------------*/ /* ** Send data to the SSL server */ printf (" Message to be sent to the SSL server: \n\t %s \n" , hello ); err = SSL_write(ssl, hello, strlen(hello)); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during CLIENT write operation to SERVER"); /* ** Receive data from the SSL server */ err = SSL_read(ssl, buf, sizeof(buf)-1); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during CLIENT read operation from SERVER"); 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); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during CLIENT shutting down SSL connection"); /* -- SSL -- */ /* * close connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ 0, /* p3 */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Error - Failed to close socket\n" ); exit( status ); } SSL_free(ssl); SSL_CTX_free(ctx); /* * deassign device socket */ status = sys$dassgn( conn_channel ); if ( !(status & STS$M_SUCCESS) ) { printf( "Error - Failed to deassign i/o channel to TCPIP device\n" ); exit( status ); } }