#include /* define OpenVMS descriptors */ #include /* define error definitions */ #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, */ /* structures, and functions */ #include /* Posix definitions */ #include #define SERV_BACKLOG 1 /* server backlog */ #define SERV_PORTNUM 8995 /* server port number */ #include #include #define openssl "SSL$INCLUDE" #include #include #include #include "SSL$EXAMPLES:ssl_examples.h" /* SSL callbacks and error handling */ #undef openssl #define RSA_SERVER_CERT "wasd_root:[local]starlet.pem" #define RSA_SERVER_KEY "wasd_root:[local]starlet.pem" #define ON 1 #define OFF 0 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 itemlst_3 { /* item-list 3 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ unsigned int *retlen; /* address of returned length */ }; struct sockchar { /* socket characteristics buffer */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; /* ++ SSL */ char buf[4096]; /* Global server read data buffer */ /* -- SSL */ int main( void ) { /* ++ SSL */ int err; int listen_sock; int sock; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; char *str; SSL_CTX *ctx; SSL *ssl; /* Pointer to SSL Object */ SSL_METHOD *meth; short int s_port = 8995; int one = 1; /* reuseaddr option value */ struct iosb iosb; /* i/o status block */ unsigned int status; /* system service return status */ unsigned short conn_channel; /* connect inet device i/o channel */ unsigned short listen_channel; /* listen inet device i/o channel */ struct sockchar listen_sockchar; /* listen socket char buffer */ unsigned int client_retlen; /* returned length of client socket */ /* address structure */ struct sockaddr_in client_addr; /* client socket address structure */ struct itemlst_3 client_itemlst; /* client item-list 3 descriptor */ struct sockaddr_in serv_addr; /* server socket address structure */ struct itemlst_2 serv_itemlst; /* server item-list 2 descriptor */ struct itemlst_2 sockopt_itemlst; /* sockopt item-list 2 descriptor */ struct itemlst_2 reuseaddr_itemlst; /* reuseaddr item-list 2 element */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of internet pseudodevice */ COMP_METHOD *compr; /* ++ SSL */ /*-----------------------------------------------------------------------------------------*/ /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); SSLeay_add_all_algorithms(); SSLeay_add_ssl_algorithms(); /* Create a SSL_METHOD structure (choose a SSL/TLS protocol version) */ meth = SSLv23_method(); compr = COMP_rle(); status = SSL_COMP_add_compression_method(0XE1, compr); ERR_print_errors_fp(stderr); /* Create a SSL_CTX structure */ ctx = SSL_CTX_new(meth); RETURN_NULL(ctx); /* Load the server certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Load the private-key corresponding to the server certificate */ if (SSL_CTX_use_PrivateKey_file(ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Check if the server 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); } /* ++ SSL */ /* A SSL structure is created */ ssl = SSL_new(ctx); RETURN_NULL(ssl); /* Set informational callback routine */ // SSL_set_info_callback( ssl , get_info ); /* -- SSL */ /* * init listen socket characteristics buffer */ listen_sockchar.prot = TCPIP$C_TCP; listen_sockchar.type = TCPIP$C_STREAM; listen_sockchar.af = TCPIP$C_AF_INET; /* * init reuseaddr's item-list element */ reuseaddr_itemlst.length = sizeof( one ); reuseaddr_itemlst.type = TCPIP$C_REUSEADDR; reuseaddr_itemlst.address = &one; /* * init sockopt's item-list descriptor */ sockopt_itemlst.length = sizeof( reuseaddr_itemlst ); sockopt_itemlst.type = TCPIP$C_SOCKOPT; sockopt_itemlst.address = &reuseaddr_itemlst; /* * init client's item-list descriptor */ memset( &client_itemlst, 0, sizeof(client_itemlst) ); client_itemlst.length = sizeof( client_addr ); client_itemlst.address = &client_addr; client_itemlst.retlen = &client_retlen; /* * init client's socket address structure */ memset( &client_addr, 0, sizeof(client_addr) ); /* * init server's item-list descriptor */ serv_itemlst.length = sizeof( serv_addr ); serv_itemlst.type = TCPIP$C_SOCK_NAME; 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 ); serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; /* * assign device sockets */ status = sys$assign( &inet_device, /* device name */ &listen_channel, /* i/o channel */ 0, /* access mode */ 0 /* not used */ ); if ( (status & STS$M_SUCCESS) ) status = sys$assign( &inet_device, /* device name */ &conn_channel, /* i/o channel */ 0, /* access mode */ 0 /* not used */ ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to assign i/o channel(s) to TCPIP device\n" ); exit( status ); } /* * create a listen socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &listen_sockchar, /* p1 - socket char buffer */ 0, /* p2 */ 0, /* p3 */ 0, /* p4 */ &sockopt_itemlst, /* p5 - socket options */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to create socket\n" ); exit( status ); } /* * bind server's internet address and port number to * listen socket; set socket as a passive socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &serv_itemlst, /* p3 - local socket name */ SERV_BACKLOG, /* p4 - connection backlog */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) { status = iosb.status; } if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to bind socket\n" ); exit( status ); } /* * accept a connection from a client */ /* ** Set Keep Alive and Send/Receive Buffer Size options */ { 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,listen_channel,IO$_SETMODE,&iosb,0,0, 0,0,0,0,&options,0))) || !(iosb.status & 1) ) lib$signal((1 & status)?iosb.status:status); } printf( " . . . Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port) ); status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_ACCESS|IO$M_ACCEPT, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &client_itemlst, /* p3 - remote socket name */ &conn_channel, /* p4 - i/o channel for new */ /* connection */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to accept client connection\n" ); exit( status ); } printf( " . . . Accepted connection from host: %s, port: %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port) ); /* ++ SSL */ /* ** Assign the socket 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 SERVER assigning socket to SSL object"); /* ** Perform SSL Handshake on the SSL server */ err = SSL_accept(ssl); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during SERVER accepting CLIENT connection"); /* ** Informational output (optional) */ printf(" SSL connection using %s\n", SSL_get_cipher (ssl)); /*--------------- DATA EXCHANGE - Receive message and send reply. ---------------*/ /* ** Receive data from the SSL client */ err = SSL_read(ssl, buf, sizeof(buf) - 1); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during SERVER read operation from Client"); buf[err] = '\0'; printf (" Received %d chars from client:'%s'\n", err, buf); /* ** Send data to the SSL client */ err = SSL_write( ssl, "This message is from the SSL QIO server", strlen("This message is from the SSL QIO server")); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during SERVER write operation to CLIENT"); lib$signal(SS$_DEBUG); /*--------------- SSL closure ---------------*/ /* ** Shutdown this side (server) of the connection. */ err = SSL_shutdown(ssl); if ( err == -1 ) check_error( ssl , err , \ "- ERROR - during SERVER shutting down SSL connection"); /* -- SSL */ /* * shutdown connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS|IO$M_SHUTDOWN, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ 0, /* p3 */ TCPIP$C_DSC_ALL, /* p4 - discard all packets */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to shutdown client connection\n" ); exit( status ); } /* * 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( "Failed to close socket\n" ); exit( status ); } /* * close listen socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_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( "Failed to close socket\n" ); exit( status ); } /* ++ SSL */ /* ** Free the SSL structure */ SSL_free(ssl); /* ** Free the SSL_CTX structure */ SSL_CTX_free(ctx); /* -- SSL */ /* * deassign all device sockets */ status = sys$dassgn( conn_channel ); if ( (status & STS$M_SUCCESS) ) status = sys$dassgn( listen_channel ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to deassign i/o channel(s) to TCPIP device\n" ); exit( status ); } exit( EXIT_SUCCESS ); } /* End Main */