ssl_task.c revision 296465
116359Sasami/* ssl/ssl_task.c */ 216359Sasami/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 316359Sasami * All rights reserved. 416359Sasami * 516359Sasami * This package is an SSL implementation written 616359Sasami * by Eric Young (eay@cryptsoft.com). 716359Sasami * The implementation was written so as to conform with Netscapes SSL. 816359Sasami * 916359Sasami * This library is free for commercial and non-commercial use as long as 1016359Sasami * the following conditions are aheared to. The following conditions 1116359Sasami * apply to all code found in this distribution, be it the RC4, RSA, 1216359Sasami * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1316359Sasami * included with this distribution is covered by the same copyright terms 1416359Sasami * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1516359Sasami * 1616359Sasami * Copyright remains Eric Young's, and as such any Copyright notices in 1716359Sasami * the code are not to be removed. 1816359Sasami * If this package is used in a product, Eric Young should be given attribution 1916359Sasami * as the author of the parts of the library used. 2016359Sasami * This can be in the form of a textual message at program startup or 2116359Sasami * in documentation (online or textual) provided with the package. 2216359Sasami * 2316359Sasami * Redistribution and use in source and binary forms, with or without 2416359Sasami * modification, are permitted provided that the following conditions 2516359Sasami * are met: 2616359Sasami * 1. Redistributions of source code must retain the copyright 2716359Sasami * notice, this list of conditions and the following disclaimer. 2816359Sasami * 2. Redistributions in binary form must reproduce the above copyright 2916359Sasami * notice, this list of conditions and the following disclaimer in the 3016359Sasami * documentation and/or other materials provided with the distribution. 3116359Sasami * 3. All advertising materials mentioning features or use of this software 3216359Sasami * must display the following acknowledgement: 3350477Speter * "This product includes cryptographic software written by 3416359Sasami * Eric Young (eay@cryptsoft.com)" 3545816Skato * The word 'cryptographic' can be left out if the rouines from the library 3616359Sasami * being used are not cryptographic related :-). 3716359Sasami * 4. If you include any Windows specific code (or a derivative thereof) from 3816359Sasami * the apps directory (application code) you must include an acknowledgement: 3931778Seivind * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4016359Sasami * 4146871Skato * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4254407Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4358888Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4416359Sasami * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4516359Sasami * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4616359Sasami * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4716359Sasami * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4816359Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4916359Sasami * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5016359Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5116359Sasami * SUCH DAMAGE. 5216359Sasami * 5316359Sasami * The licence and distribution terms for any publically available version or 5416359Sasami * derivative of this code cannot be changed. i.e. this code cannot simply be 5516359Sasami * copied and put under another distribution licence 5616359Sasami * [including the GNU Public Licence.] 5716359Sasami */ 5816359Sasami 5916359Sasami/* VMS */ 6016359Sasami/*- 6116359Sasami * DECnet object for servicing SSL. We accept the inbound and speak a 6216359Sasami * simple protocol for multiplexing the 2 data streams (application and 6316359Sasami * ssl data) over this logical link. 6416359Sasami * 6516359Sasami * Logical names: 6616359Sasami * SSL_CIPHER Defines a list of cipher specifications the server 6716359Sasami * will support in order of preference. 6816359Sasami * SSL_SERVER_CERTIFICATE 6916359Sasami * Points to PEM (privacy enhanced mail) file that 7016359Sasami * contains the server certificate and private password. 7116359Sasami * SYS$NET Logical created by netserver.exe as hook for completing 7216359Sasami * DECnet logical link. 7316359Sasami * 7416359Sasami * Each NSP message sent over the DECnet link has the following structure: 7516359Sasami * struct rpc_msg { 7616359Sasami * char channel; 7716359Sasami * char function; 7840565Sbde * short length; 7940565Sbde * char data[MAX_DATA]; 8040565Sbde * } msg; 8116359Sasami * 8216359Sasami * The channel field designates the virtual data stream this message applies 8316359Sasami * to and is one of: 8416359Sasami * A - Application data (payload). 8516359Sasami * R - Remote client connection that initiated the SSL connection. Encrypted 8616359Sasami * data is sent over this connection. 8716359Sasami * G - General data, reserved for future use. 8816359Sasami * 8916359Sasami * The data streams are half-duplex read/write and have following functions: 9016359Sasami * G - Get, requests that up to msg.length bytes of data be returned. The 9116359Sasami * data is returned in the next 'C' function response that matches the 9216359Sasami * requesting channel. 9316359Sasami * P - Put, requests that the first msg.length bytes of msg.data be appended 9416359Sasami * to the designated stream. 9516359Sasami * C - Confirms a get or put. Every get and put will get a confirm response, 9616359Sasami * you cannot initiate another function on a channel until the previous 9716359Sasami * operation has been confirmed. 9816359Sasami * 9916359Sasami * The 2 channels may interleave their operations, for example: 10016359Sasami * Server msg Client msg 10116359Sasami * A, Get, 4092 ----> 10216359Sasami * <---- R, get, 4092 10316359Sasami * R, Confirm, {hello} ----> 10416359Sasami * <---- R, put, {srv hello} 10516359Sasami * R, Confirm, 0 ----> 10616359Sasami * . (SSL handshake completed) 10740565Sbde * . (read first app data). 10840565Sbde * <---- A, confirm, {http data} 10916359Sasami * A, Put, {http data} ----> 11016359Sasami * <---- A, confirm, 0 11142262Skato * 11242262Skato * The length field is not permitted to be larger that 4092 bytes. 11342262Skato * 11454174Snyan * Author: Dave Jones 11554174Snyan * Date: 22-JUL-1996 11654174Snyan */ 11742262Skato#include <stdlib.h> 11816359Sasami#include <stdio.h> 11942262Skato#include <iodef.h> /* VMS IO$_ definitions */ 12042262Skato#include <descrip.h> /* VMS string descriptors */ 12142262Skatoextern int SYS$QIOW(), SYS$ASSIGN(); 12242262Skatoint LIB$INIT_TIMER(), LIB$SHOW_TIMER(); 12342262Skato 12442262Skato#include <string.h> /* from ssltest.c */ 12542262Skato#include <errno.h> 12642262Skato 12742262Skato#include "e_os.h" 12842262Skato 12942262Skato#include <openssl/buffer.h> 13042262Skato#include <openssl/x509.h> 13142262Skato#include <openssl/ssl.h> 13242262Skato#include <openssl/err.h> 13342262Skato 13442262Skatoint MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, 13542262Skato int error); 13642262SkatoBIO *bio_err = NULL; 13742262SkatoBIO *bio_stdout = NULL; 13842262SkatoBIO_METHOD *BIO_s_rtcp(); 13942262Skato 14016359Sasamistatic char *cipher = NULL; 14116359Sasamiint verbose = 1; 14216359Sasami#ifdef FIONBIO 14365877Skatostatic int s_nbio = 0; 14416359Sasami#endif 14516359Sasami#define TEST_SERVER_CERT "SSL_SERVER_CERTIFICATE" 14630368Skato/*************************************************************************/ 14716359Sasami/* Should have member alignment inhibited */ 14816359Sasamistruct rpc_msg { 14945783Skato /* 'A'-app data. 'R'-remote client 'G'-global */ 15016359Sasami char channel; 15116359Sasami /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 15224132Sbde char function; 15338297Skato /* Amount of data returned or max to return */ 15466738Skato unsigned short int length; 15516359Sasami /* variable data */ 15616359Sasami char data[4092]; 15726439Skato}; 15845783Skato#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 15945783Skato 16045783Skatostatic $DESCRIPTOR(sysnet, "SYS$NET"); 16158477Skatotypedef unsigned short io_channel; 16245226Skato 16316359Sasamistruct io_status { 16416359Sasami unsigned short status; 16516359Sasami unsigned short count; 16622407Skato unsigned long stsval; 16718265Sasami}; 16816359Sasamiint doit(io_channel chan, SSL_CTX *s_ctx); 16945783Skato/*****************************************************************************/ 17042262Skato/* 17145783Skato * Decnet I/O routines. 17258888Skato */ 17358888Skatostatic int get(io_channel chan, char *buffer, int maxlen, int *length) 17458888Skato{ 17558888Skato int status; 17645783Skato struct io_status iosb; 17716359Sasami status = SYS$QIOW(0, chan, IO$_READVBLK, &iosb, 0, 0, 17845783Skato buffer, maxlen, 0, 0, 0, 0); 17945783Skato if ((status & 1) == 1) 18045783Skato status = iosb.status; 18145783Skato if ((status & 1) == 1) 18245783Skato *length = iosb.count; 18345783Skato return status; 18445783Skato} 18516359Sasami 18616359Sasamistatic int put(io_channel chan, char *buffer, int length) 18716359Sasami{ 18816359Sasami int status; 18942265Skato struct io_status iosb; 19042265Skato status = SYS$QIOW(0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 19142265Skato buffer, length, 0, 0, 0, 0); 19216359Sasami if ((status & 1) == 1) 19365568Skato status = iosb.status; 19445783Skato return status; 19551202Snyan} 19651202Snyan 19745783Skato/***************************************************************************/ 19845783Skato/* 19916359Sasami * Handle operations on the 'G' channel. 20016359Sasami */ 20116359Sasamistatic int general_request(io_channel chan, struct rpc_msg *msg, int length) 20216359Sasami{ 20316359Sasami return 48; 20416359Sasami} 20516359Sasami 20616359Sasami/***************************************************************************/ 20716359Sasamiint main(int argc, char **argv) 20816359Sasami{ 20916359Sasami int status, length; 21016359Sasami io_channel chan; 21116359Sasami struct rpc_msg msg; 21216359Sasami 21345783Skato char *CApath = NULL, *CAfile = NULL; 21445783Skato int badop = 0; 21545783Skato int ret = 1; 21616359Sasami int client_auth = 0; 21716359Sasami int server_auth = 0; 21845783Skato SSL_CTX *s_ctx = NULL; 21945783Skato /* 22045783Skato * Confirm logical link with initiating client. 22146766Skato */ 22245783Skato LIB$INIT_TIMER(); 22345783Skato status = SYS$ASSIGN(&sysnet, &chan, 0, 0, 0); 22445783Skato printf("status of assign to SYS$NET: %d\n", status); 22545783Skato /* 22645783Skato * Initialize standard out and error files. 22745783Skato */ 22845783Skato if (bio_err == NULL) 22945783Skato if ((bio_err = BIO_new(BIO_s_file())) != NULL) 23016359Sasami BIO_set_fp(bio_err, stderr, BIO_NOCLOSE); 23142265Skato if (bio_stdout == NULL) 23242265Skato if ((bio_stdout = BIO_new(BIO_s_file())) != NULL) 23360472Snyan BIO_set_fp(bio_stdout, stdout, BIO_NOCLOSE); 23416359Sasami /* 23516359Sasami * get the preferred cipher list and other initialization 23660472Snyan */ 23760472Snyan if (cipher == NULL) 23860472Snyan cipher = getenv("SSL_CIPHER"); 23960472Snyan printf("cipher list: %s\n", cipher ? cipher : "{undefined}"); 24060472Snyan 24116359Sasami SSL_load_error_strings(); 24216359Sasami OpenSSL_add_all_algorithms(); 24316359Sasami 24416359Sasami /* 24516359Sasami * DRM, this was the original, but there is no such thing as SSLv2() 24616359Sasami * s_ctx=SSL_CTX_new(SSLv2()); 24716359Sasami */ 24816359Sasami s_ctx = SSL_CTX_new(SSLv2_server_method()); 24951654Sphk 25016359Sasami if (s_ctx == NULL) 25116359Sasami goto end; 25216359Sasami 25316359Sasami SSL_CTX_use_certificate_file(s_ctx, TEST_SERVER_CERT, SSL_FILETYPE_PEM); 25416359Sasami SSL_CTX_use_RSAPrivateKey_file(s_ctx, TEST_SERVER_CERT, SSL_FILETYPE_PEM); 25516359Sasami printf("Loaded server certificate: '%s'\n", TEST_SERVER_CERT); 25616359Sasami 25716359Sasami /* 25816359Sasami * Take commands from client until bad status. 25916359Sasami */ 26016359Sasami LIB$SHOW_TIMER(); 26116359Sasami status = doit(chan, s_ctx); 26216359Sasami LIB$SHOW_TIMER(); 26316359Sasami /* 26416359Sasami * do final cleanup and exit. 26525026Skato */ 26616359Sasami end: 26716359Sasami if (s_ctx != NULL) 26816359Sasami SSL_CTX_free(s_ctx); 26916359Sasami LIB$SHOW_TIMER(); 27016359Sasami return 1; 27116359Sasami} 27216359Sasami 27316359Sasamiint doit(io_channel chan, SSL_CTX *s_ctx) 27416359Sasami{ 27516359Sasami int status, length, link_state; 27616359Sasami struct rpc_msg msg; 27716359Sasami 27816359Sasami SSL *s_ssl = NULL; 27916359Sasami BIO *c_to_s = NULL; 28016359Sasami BIO *s_to_c = NULL; 28116359Sasami BIO *c_bio = NULL; 28216359Sasami BIO *s_bio = NULL; 28316359Sasami int i; 28416359Sasami int done = 0; 28516359Sasami 28616359Sasami s_ssl = SSL_new(s_ctx); 28716359Sasami if (s_ssl == NULL) 28816359Sasami goto err; 28916359Sasami 29016359Sasami c_to_s = BIO_new(BIO_s_rtcp()); 29116359Sasami s_to_c = BIO_new(BIO_s_rtcp()); 29216359Sasami if ((s_to_c == NULL) || (c_to_s == NULL)) 29345783Skato goto err; 29416359Sasami/*- original, DRM 24-SEP-1997 29516359Sasami BIO_set_fd ( c_to_s, "", chan ); 29616359Sasami BIO_set_fd ( s_to_c, "", chan ); 29716359Sasami*/ 29816359Sasami BIO_set_fd(c_to_s, 0, chan); 29916359Sasami BIO_set_fd(s_to_c, 0, chan); 30025026Skato 30116359Sasami c_bio = BIO_new(BIO_f_ssl()); 30216359Sasami s_bio = BIO_new(BIO_f_ssl()); 30327479Skato if ((c_bio == NULL) || (s_bio == NULL)) 30416359Sasami goto err; 30516359Sasami 30616359Sasami SSL_set_accept_state(s_ssl); 30716359Sasami SSL_set_bio(s_ssl, c_to_s, s_to_c); 30816359Sasami BIO_set_ssl(s_bio, s_ssl, BIO_CLOSE); 30916359Sasami 31016359Sasami /* We can always do writes */ 31116359Sasami printf("Begin doit main loop\n"); 31216359Sasami /* 31316359Sasami * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed. 31416359Sasami */ 31516359Sasami for (link_state = 0; link_state < 3;) { 31616359Sasami /* 31716359Sasami * Wait for remote end to request data action on A channel. 31816359Sasami */ 31916359Sasami while (link_state == 0) { 32016359Sasami status = get(chan, (char *)&msg, sizeof(msg), &length); 32116359Sasami if ((status & 1) == 0) { 32216359Sasami printf("Error in main loop get: %d\n", status); 32316359Sasami link_state = 3; 32416359Sasami break; 32516359Sasami } 32616359Sasami if (length < RPC_HDR_SIZE) { 32716359Sasami printf("Error in main loop get size: %d\n", length); 32816359Sasami break; 32916359Sasami link_state = 3; 33043663Skato } 33116359Sasami if (msg.channel != 'A') { 33216359Sasami printf("Error in main loop, unexpected channel: %c\n", 33343663Skato msg.channel); 33443663Skato break; 33516359Sasami link_state = 3; 33616359Sasami } 33716359Sasami if (msg.function == 'G') { 33816359Sasami link_state = 1; 33960472Snyan } else if (msg.function == 'P') { 34060472Snyan link_state = 2; /* write pending */ 34160472Snyan } else if (msg.function == 'X') { 34216359Sasami link_state = 3; 34316359Sasami } else { 34416359Sasami link_state = 3; 34516359Sasami } 34616359Sasami } 34760472Snyan if (link_state == 1) { 34816359Sasami i = BIO_read(s_bio, msg.data, msg.length); 34916359Sasami if (i < 0) 35016359Sasami link_state = 3; 35116359Sasami else { 35216359Sasami msg.channel = 'A'; 35316359Sasami msg.function = 'C'; /* confirm */ 35416359Sasami msg.length = i; 35516359Sasami status = put(chan, (char *)&msg, i + RPC_HDR_SIZE); 35654174Snyan if ((status & 1) == 0) 35754174Snyan break; 35854174Snyan link_state = 0; 35916359Sasami } 36016359Sasami } else if (link_state == 2) { 36116359Sasami i = BIO_write(s_bio, msg.data, msg.length); 36216359Sasami if (i < 0) 36316359Sasami link_state = 3; 36416359Sasami else { 36516359Sasami msg.channel = 'A'; 36616359Sasami msg.function = 'C'; /* confirm */ 36716359Sasami msg.length = 0; 36832332Skato status = put(chan, (char *)&msg, RPC_HDR_SIZE); 36916359Sasami if ((status & 1) == 0) 37016359Sasami break; 37116359Sasami link_state = 0; 37216359Sasami } 37316359Sasami } 37416359Sasami } 37516359Sasami fprintf(stdout, "DONE\n"); 37616359Sasami err: 37716359Sasami /* 37816359Sasami * We have to set the BIO's to NULL otherwise they will be free()ed 37916359Sasami * twice. Once when th s_ssl is SSL_free()ed and again when c_ssl is 38016359Sasami * SSL_free()ed. This is a hack required because s_ssl and c_ssl are 38117256Sasami * sharing the same BIO structure and SSL_set_bio() and SSL_free() 38216359Sasami * automatically BIO_free non NULL entries. You should not normally do 38317256Sasami * this or be required to do this 38445226Skato */ 38516359Sasami s_ssl->rbio = NULL; 38616359Sasami s_ssl->wbio = NULL; 38716359Sasami 38816359Sasami if (c_to_s != NULL) 38916359Sasami BIO_free(c_to_s); 39016359Sasami if (s_to_c != NULL) 39151202Snyan BIO_free(s_to_c); 39251202Snyan if (c_bio != NULL) 39354407Skato BIO_free(c_bio); 39451202Snyan if (s_bio != NULL) 39516359Sasami BIO_free(s_bio); 39642262Skato return (0); 39742262Skato} 39842262Skato