155714Skris/* ssl/ssl_task.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris/* VMS */ 6055714Skris/* 6155714Skris * DECnet object for servicing SSL. We accept the inbound and speak a 6255714Skris * simple protocol for multiplexing the 2 data streams (application and 6355714Skris * ssl data) over this logical link. 6455714Skris * 6555714Skris * Logical names: 6655714Skris * SSL_CIPHER Defines a list of cipher specifications the server 6755714Skris * will support in order of preference. 6855714Skris * SSL_SERVER_CERTIFICATE 6955714Skris * Points to PEM (privacy enhanced mail) file that 7055714Skris * contains the server certificate and private password. 7155714Skris * SYS$NET Logical created by netserver.exe as hook for completing 7255714Skris * DECnet logical link. 7355714Skris * 7455714Skris * Each NSP message sent over the DECnet link has the following structure: 7555714Skris * struct rpc_msg { 7655714Skris * char channel; 7755714Skris * char function; 7855714Skris * short length; 7955714Skris * char data[MAX_DATA]; 8055714Skris * } msg; 8155714Skris * 8255714Skris * The channel field designates the virtual data stream this message applies 8355714Skris * to and is one of: 8455714Skris * A - Application data (payload). 8555714Skris * R - Remote client connection that initiated the SSL connection. Encrypted 8655714Skris * data is sent over this connection. 8755714Skris * G - General data, reserved for future use. 8855714Skris * 8955714Skris * The data streams are half-duplex read/write and have following functions: 9055714Skris * G - Get, requests that up to msg.length bytes of data be returned. The 9155714Skris * data is returned in the next 'C' function response that matches the 9255714Skris * requesting channel. 9355714Skris * P - Put, requests that the first msg.length bytes of msg.data be appended 9455714Skris * to the designated stream. 9555714Skris * C - Confirms a get or put. Every get and put will get a confirm response, 9655714Skris * you cannot initiate another function on a channel until the previous 9755714Skris * operation has been confirmed. 9855714Skris * 9955714Skris * The 2 channels may interleave their operations, for example: 10055714Skris * Server msg Client msg 10155714Skris * A, Get, 4092 ----> 10255714Skris * <---- R, get, 4092 10355714Skris * R, Confirm, {hello} ----> 10455714Skris * <---- R, put, {srv hello} 10555714Skris * R, Confirm, 0 ----> 10655714Skris * . (SSL handshake completed) 10755714Skris * . (read first app data). 10855714Skris * <---- A, confirm, {http data} 10955714Skris * A, Put, {http data} ----> 11055714Skris * <---- A, confirm, 0 11155714Skris * 11255714Skris * The length field is not permitted to be larger that 4092 bytes. 11355714Skris * 11455714Skris * Author: Dave Jones 11555714Skris * Date: 22-JUL-1996 11655714Skris */ 11755714Skris#include <stdlib.h> 11855714Skris#include <stdio.h> 11955714Skris#include <iodef.h> /* VMS IO$_ definitions */ 12055714Skris#include <descrip.h> /* VMS string descriptors */ 12155714Skrisextern int SYS$QIOW(), SYS$ASSIGN(); 12255714Skrisint LIB$INIT_TIMER(), LIB$SHOW_TIMER(); 12355714Skris 12455714Skris#include <string.h> /* from ssltest.c */ 12555714Skris#include <errno.h> 12655714Skris 127109998Smarkm#include "e_os.h" 12855714Skris 12955714Skris#include <openssl/buffer.h> 13055714Skris#include <openssl/x509.h> 13155714Skris#include <openssl/ssl.h> 13255714Skris#include <openssl/err.h> 13355714Skris 13455714Skrisint MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, 13555714Skris int error); 13655714SkrisBIO *bio_err=NULL; 13755714SkrisBIO *bio_stdout=NULL; 13855714SkrisBIO_METHOD *BIO_s_rtcp(); 13955714Skris 14055714Skrisstatic char *cipher=NULL; 14155714Skrisint verbose=1; 14255714Skris#ifdef FIONBIO 14355714Skrisstatic int s_nbio=0; 14455714Skris#endif 14555714Skris#define TEST_SERVER_CERT "SSL_SERVER_CERTIFICATE" 14655714Skris/*************************************************************************/ 14755714Skrisstruct rpc_msg { /* Should have member alignment inhibited */ 14855714Skris char channel; /* 'A'-app data. 'R'-remote client 'G'-global */ 14955714Skris char function; /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 15055714Skris unsigned short int length; /* Amount of data returned or max to return */ 15155714Skris char data[4092]; /* variable data */ 15255714Skris}; 15355714Skris#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 15455714Skris 15555714Skrisstatic $DESCRIPTOR(sysnet, "SYS$NET"); 15655714Skristypedef unsigned short io_channel; 15755714Skris 15855714Skrisstruct io_status { 15955714Skris unsigned short status; 16055714Skris unsigned short count; 16155714Skris unsigned long stsval; 16255714Skris}; 16355714Skrisint doit(io_channel chan, SSL_CTX *s_ctx ); 16455714Skris/*****************************************************************************/ 16555714Skris/* Decnet I/O routines. 16655714Skris */ 16755714Skrisstatic int get ( io_channel chan, char *buffer, int maxlen, int *length ) 16855714Skris{ 16955714Skris int status; 17055714Skris struct io_status iosb; 17155714Skris status = SYS$QIOW ( 0, chan, IO$_READVBLK, &iosb, 0, 0, 17255714Skris buffer, maxlen, 0, 0, 0, 0 ); 17355714Skris if ( (status&1) == 1 ) status = iosb.status; 17455714Skris if ( (status&1) == 1 ) *length = iosb.count; 17555714Skris return status; 17655714Skris} 17755714Skris 17855714Skrisstatic int put ( io_channel chan, char *buffer, int length ) 17955714Skris{ 18055714Skris int status; 18155714Skris struct io_status iosb; 18255714Skris status = SYS$QIOW ( 0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 18355714Skris buffer, length, 0, 0, 0, 0 ); 18455714Skris if ( (status&1) == 1 ) status = iosb.status; 18555714Skris return status; 18655714Skris} 18755714Skris/***************************************************************************/ 18855714Skris/* Handle operations on the 'G' channel. 18955714Skris */ 19055714Skrisstatic int general_request ( io_channel chan, struct rpc_msg *msg, int length ) 19155714Skris{ 19255714Skris return 48; 19355714Skris} 19455714Skris/***************************************************************************/ 19555714Skrisint main ( int argc, char **argv ) 19655714Skris{ 19755714Skris int status, length; 19855714Skris io_channel chan; 19955714Skris struct rpc_msg msg; 20055714Skris 20155714Skris char *CApath=NULL,*CAfile=NULL; 20255714Skris int badop=0; 20355714Skris int ret=1; 20455714Skris int client_auth=0; 20555714Skris int server_auth=0; 20655714Skris SSL_CTX *s_ctx=NULL; 20755714Skris /* 20855714Skris * Confirm logical link with initiating client. 20955714Skris */ 21055714Skris LIB$INIT_TIMER(); 21155714Skris status = SYS$ASSIGN ( &sysnet, &chan, 0, 0, 0 ); 21255714Skris printf("status of assign to SYS$NET: %d\n", status ); 21355714Skris /* 21455714Skris * Initialize standard out and error files. 21555714Skris */ 21655714Skris if (bio_err == NULL) 21755714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 21855714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE); 21955714Skris if (bio_stdout == NULL) 22055714Skris if ((bio_stdout=BIO_new(BIO_s_file())) != NULL) 22155714Skris BIO_set_fp(bio_stdout,stdout,BIO_NOCLOSE); 22255714Skris /* 22355714Skris * get the preferred cipher list and other initialization 22455714Skris */ 22555714Skris if (cipher == NULL) cipher=getenv("SSL_CIPHER"); 22655714Skris printf("cipher list: %s\n", cipher ? cipher : "{undefined}" ); 22755714Skris 22855714Skris SSL_load_error_strings(); 22959191Skris OpenSSL_add_all_algorithms(); 23055714Skris 23155714Skris/* DRM, this was the original, but there is no such thing as SSLv2() 23255714Skris s_ctx=SSL_CTX_new(SSLv2()); 23355714Skris*/ 23455714Skris s_ctx=SSL_CTX_new(SSLv2_server_method()); 23555714Skris 23655714Skris if (s_ctx == NULL) goto end; 23755714Skris 23855714Skris SSL_CTX_use_certificate_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM); 23955714Skris SSL_CTX_use_RSAPrivateKey_file(s_ctx,TEST_SERVER_CERT,SSL_FILETYPE_PEM); 24055714Skris printf("Loaded server certificate: '%s'\n", TEST_SERVER_CERT ); 24155714Skris 24255714Skris /* 24355714Skris * Take commands from client until bad status. 24455714Skris */ 24555714Skris LIB$SHOW_TIMER(); 24655714Skris status = doit ( chan, s_ctx ); 24755714Skris LIB$SHOW_TIMER(); 24855714Skris /* 24955714Skris * do final cleanup and exit. 25055714Skris */ 25155714Skrisend: 25255714Skris if (s_ctx != NULL) SSL_CTX_free(s_ctx); 25355714Skris LIB$SHOW_TIMER(); 25455714Skris return 1; 25555714Skris} 25655714Skris 25755714Skrisint doit(io_channel chan, SSL_CTX *s_ctx ) 25855714Skris{ 25955714Skris int status, length, link_state; 26055714Skris struct rpc_msg msg; 261109998Smarkm 26255714Skris SSL *s_ssl=NULL; 26355714Skris BIO *c_to_s=NULL; 26455714Skris BIO *s_to_c=NULL; 26555714Skris BIO *c_bio=NULL; 26655714Skris BIO *s_bio=NULL; 26755714Skris int i; 26855714Skris int done=0; 26955714Skris 27055714Skris s_ssl=SSL_new(s_ctx); 27155714Skris if (s_ssl == NULL) goto err; 27255714Skris 27355714Skris c_to_s=BIO_new(BIO_s_rtcp()); 27455714Skris s_to_c=BIO_new(BIO_s_rtcp()); 27555714Skris if ((s_to_c == NULL) || (c_to_s == NULL)) goto err; 27655714Skris/* original, DRM 24-SEP-1997 27755714Skris BIO_set_fd ( c_to_s, "", chan ); 27855714Skris BIO_set_fd ( s_to_c, "", chan ); 27955714Skris*/ 28055714Skris BIO_set_fd ( c_to_s, 0, chan ); 28155714Skris BIO_set_fd ( s_to_c, 0, chan ); 28255714Skris 28355714Skris c_bio=BIO_new(BIO_f_ssl()); 28455714Skris s_bio=BIO_new(BIO_f_ssl()); 28555714Skris if ((c_bio == NULL) || (s_bio == NULL)) goto err; 28655714Skris 28755714Skris SSL_set_accept_state(s_ssl); 28855714Skris SSL_set_bio(s_ssl,c_to_s,s_to_c); 28955714Skris BIO_set_ssl(s_bio,s_ssl,BIO_CLOSE); 29055714Skris 29155714Skris /* We can always do writes */ 29255714Skris printf("Begin doit main loop\n"); 29355714Skris /* 29455714Skris * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed. 29555714Skris */ 29655714Skris for (link_state = 0; link_state < 3; ) { 29755714Skris /* 29855714Skris * Wait for remote end to request data action on A channel. 29955714Skris */ 30055714Skris while ( link_state == 0 ) { 30155714Skris status = get ( chan, (char *) &msg, sizeof(msg), &length ); 30255714Skris if ( (status&1) == 0 ) { 30355714Skris printf("Error in main loop get: %d\n", status ); 30455714Skris link_state = 3; 30555714Skris break; 30655714Skris } 30755714Skris if ( length < RPC_HDR_SIZE ) { 30855714Skris printf("Error in main loop get size: %d\n", length ); 30955714Skris break; 31055714Skris link_state = 3; 31155714Skris } 31255714Skris if ( msg.channel != 'A' ) { 31355714Skris printf("Error in main loop, unexpected channel: %c\n", 31455714Skris msg.channel ); 31555714Skris break; 31655714Skris link_state = 3; 31755714Skris } 31855714Skris if ( msg.function == 'G' ) { 31955714Skris link_state = 1; 32055714Skris } else if ( msg.function == 'P' ) { 32155714Skris link_state = 2; /* write pending */ 32255714Skris } else if ( msg.function == 'X' ) { 32355714Skris link_state = 3; 32455714Skris } else { 32555714Skris link_state = 3; 32655714Skris } 32755714Skris } 32855714Skris if ( link_state == 1 ) { 32955714Skris i = BIO_read ( s_bio, msg.data, msg.length ); 33055714Skris if ( i < 0 ) link_state = 3; 33155714Skris else { 33255714Skris msg.channel = 'A'; 33355714Skris msg.function = 'C'; /* confirm */ 33455714Skris msg.length = i; 33555714Skris status = put ( chan, (char *) &msg, i+RPC_HDR_SIZE ); 33655714Skris if ( (status&1) == 0 ) break; 33755714Skris link_state = 0; 33855714Skris } 33955714Skris } else if ( link_state == 2 ) { 34055714Skris i = BIO_write ( s_bio, msg.data, msg.length ); 34155714Skris if ( i < 0 ) link_state = 3; 34255714Skris else { 34355714Skris msg.channel = 'A'; 34455714Skris msg.function = 'C'; /* confirm */ 34555714Skris msg.length = 0; 34655714Skris status = put ( chan, (char *) &msg, RPC_HDR_SIZE ); 34755714Skris if ( (status&1) == 0 ) break; 34855714Skris link_state = 0; 34955714Skris } 35055714Skris } 35155714Skris } 35255714Skris fprintf(stdout,"DONE\n"); 35355714Skriserr: 35455714Skris /* We have to set the BIO's to NULL otherwise they will be 35555714Skris * free()ed twice. Once when th s_ssl is SSL_free()ed and 35655714Skris * again when c_ssl is SSL_free()ed. 35755714Skris * This is a hack required because s_ssl and c_ssl are sharing the same 35855714Skris * BIO structure and SSL_set_bio() and SSL_free() automatically 35955714Skris * BIO_free non NULL entries. 36055714Skris * You should not normally do this or be required to do this */ 36155714Skris s_ssl->rbio=NULL; 36255714Skris s_ssl->wbio=NULL; 36355714Skris 36455714Skris if (c_to_s != NULL) BIO_free(c_to_s); 36555714Skris if (s_to_c != NULL) BIO_free(s_to_c); 36655714Skris if (c_bio != NULL) BIO_free(c_bio); 36755714Skris if (s_bio != NULL) BIO_free(s_bio); 36855714Skris return(0); 36955714Skris} 370