11573Srgrimes/* ssl/ssl_task.c */ 223661Speter/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 31573Srgrimes * All rights reserved. 41573Srgrimes * 51573Srgrimes * This package is an SSL implementation written 61573Srgrimes * by Eric Young (eay@cryptsoft.com). 71573Srgrimes * The implementation was written so as to conform with Netscapes SSL. 81573Srgrimes * 91573Srgrimes * This library is free for commercial and non-commercial use as long as 101573Srgrimes * the following conditions are aheared to. The following conditions 111573Srgrimes * apply to all code found in this distribution, be it the RC4, RSA, 121573Srgrimes * lhash, DES, etc., code; not just the SSL code. The SSL documentation 131573Srgrimes * included with this distribution is covered by the same copyright terms 141573Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com). 151573Srgrimes * 161573Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in 171573Srgrimes * the code are not to be removed. 181573Srgrimes * If this package is used in a product, Eric Young should be given attribution 191573Srgrimes * as the author of the parts of the library used. 201573Srgrimes * This can be in the form of a textual message at program startup or 211573Srgrimes * in documentation (online or textual) provided with the package. 221573Srgrimes * 231573Srgrimes * Redistribution and use in source and binary forms, with or without 241573Srgrimes * modification, are permitted provided that the following conditions 251573Srgrimes * are met: 261573Srgrimes * 1. Redistributions of source code must retain the copyright 271573Srgrimes * notice, this list of conditions and the following disclaimer. 281573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 291573Srgrimes * notice, this list of conditions and the following disclaimer in the 301573Srgrimes * documentation and/or other materials provided with the distribution. 311573Srgrimes * 3. All advertising materials mentioning features or use of this software 3251758Smarcel * must display the following acknowledgement: 3351758Smarcel * "This product includes cryptographic software written by 341573Srgrimes * Eric Young (eay@cryptsoft.com)" 351573Srgrimes * The word 'cryptographic' can be left out if the rouines from the library 361573Srgrimes * being used are not cryptographic related :-). 3723661Speter * 4. If you include any Windows specific code (or a derivative thereof) from 381573Srgrimes * the apps directory (application code) you must include an acknowledgement: 391573Srgrimes * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4071579Sdeischen * 411573Srgrimes * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 421573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4423661Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 451573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4623661Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 471573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 481573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 491573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 501573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5171579Sdeischen * SUCH DAMAGE. 521573Srgrimes * 531573Srgrimes * The licence and distribution terms for any publically available version or 541573Srgrimes * derivative of this code cannot be changed. i.e. this code cannot simply be 5517141Sjkh * copied and put under another distribution licence 561573Srgrimes * [including the GNU Public Licence.] 571573Srgrimes */ 581573Srgrimes 591573Srgrimes/* VMS */ 601573Srgrimes/*- 611573Srgrimes * DECnet object for servicing SSL. We accept the inbound and speak a 621573Srgrimes * simple protocol for multiplexing the 2 data streams (application and 6328235Sdg * ssl data) over this logical link. 641573Srgrimes * 651573Srgrimes * Logical names: 661573Srgrimes * SSL_CIPHER Defines a list of cipher specifications the server 671573Srgrimes * will support in order of preference. 681573Srgrimes * SSL_SERVER_CERTIFICATE 691573Srgrimes * Points to PEM (privacy enhanced mail) file that 701573Srgrimes * contains the server certificate and private password. 716227Sdg * SYS$NET Logical created by netserver.exe as hook for completing 721573Srgrimes * DECnet logical link. 7329462Sphk * 741573Srgrimes * Each NSP message sent over the DECnet link has the following structure: 751573Srgrimes * struct rpc_msg { 761573Srgrimes * char channel; 771573Srgrimes * char function; 781573Srgrimes * short length; 791573Srgrimes * char data[MAX_DATA]; 801573Srgrimes * } msg; 811573Srgrimes * 821573Srgrimes * The channel field designates the virtual data stream this message applies 831573Srgrimes * to and is one of: 841573Srgrimes * A - Application data (payload). 851573Srgrimes * R - Remote client connection that initiated the SSL connection. Encrypted 865072Sbde * data is sent over this connection. 875072Sbde * G - General data, reserved for future use. 885072Sbde * 895072Sbde * The data streams are half-duplex read/write and have following functions: 901573Srgrimes * G - Get, requests that up to msg.length bytes of data be returned. The 911573Srgrimes * data is returned in the next 'C' function response that matches the 921573Srgrimes * requesting channel. 931573Srgrimes * P - Put, requests that the first msg.length bytes of msg.data be appended 941573Srgrimes * to the designated stream. 951573Srgrimes * C - Confirms a get or put. Every get and put will get a confirm response, 9665468Speter * you cannot initiate another function on a channel until the previous 9765468Speter * operation has been confirmed. 9865468Speter * 9965468Speter * The 2 channels may interleave their operations, for example: 10065468Speter * Server msg Client msg 10165468Speter * A, Get, 4092 ----> 10265468Speter * <---- R, get, 4092 10365468Speter * R, Confirm, {hello} ----> 10465468Speter * <---- R, put, {srv hello} 10529476Sphk * R, Confirm, 0 ----> 10629392Sphk * . (SSL handshake completed) 10765468Speter * . (read first app data). 10829392Sphk * <---- A, confirm, {http data} 10936060Sjb * A, Put, {http data} ----> 1101573Srgrimes * <---- A, confirm, 0 1111573Srgrimes * 1121573Srgrimes * The length field is not permitted to be larger that 4092 bytes. 1131573Srgrimes * 1141573Srgrimes * Author: Dave Jones 1151573Srgrimes * Date: 22-JUL-1996 11623661Speter */ 1171573Srgrimes#include <stdlib.h> 1181573Srgrimes#include <stdio.h> 1191573Srgrimes#include <iodef.h> /* VMS IO$_ definitions */ 1201573Srgrimes#include <descrip.h> /* VMS string descriptors */ 1211573Srgrimesextern int SYS$QIOW(), SYS$ASSIGN(); 1221573Srgrimesint LIB$INIT_TIMER(), LIB$SHOW_TIMER(); 1231573Srgrimes 1241573Srgrimes#include <string.h> /* from ssltest.c */ 1251573Srgrimes#include <errno.h> 1261573Srgrimes 1271573Srgrimes#include "e_os.h" 1281573Srgrimes 1291573Srgrimes#include <openssl/buffer.h> 1301573Srgrimes#include <openssl/x509.h> 1311573Srgrimes#include <openssl/ssl.h> 1321573Srgrimes#include <openssl/err.h> 1331573Srgrimes 1341573Srgrimesint MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, 1351573Srgrimes int error); 1361573SrgrimesBIO *bio_err = NULL; 1371573SrgrimesBIO *bio_stdout = NULL; 1381573SrgrimesBIO_METHOD *BIO_s_rtcp(); 1391573Srgrimes 1401573Srgrimesstatic char *cipher = NULL; 1411573Srgrimesint verbose = 1; 1421573Srgrimes#ifdef FIONBIO 1431573Srgrimesstatic int s_nbio = 0; 1441573Srgrimes#endif 1451573Srgrimes#define TEST_SERVER_CERT "SSL_SERVER_CERTIFICATE" 1461573Srgrimes/*************************************************************************/ 1471573Srgrimes/* Should have member alignment inhibited */ 1481573Srgrimesstruct rpc_msg { 1491573Srgrimes /* 'A'-app data. 'R'-remote client 'G'-global */ 1509272Shsu char channel; 1511573Srgrimes /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 1521573Srgrimes char function; 1531573Srgrimes /* Amount of data returned or max to return */ 1541573Srgrimes unsigned short int length; 1551573Srgrimes /* variable data */ 1561573Srgrimes char data[4092]; 1571573Srgrimes}; 1581573Srgrimes#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 1591573Srgrimes 1601573Srgrimesstatic $DESCRIPTOR(sysnet, "SYS$NET"); 16139327Simptypedef unsigned short io_channel; 1621573Srgrimes 1631573Srgrimesstruct io_status { 1641573Srgrimes unsigned short status; 1651573Srgrimes unsigned short count; 1661573Srgrimes unsigned long stsval; 1671573Srgrimes}; 1681573Srgrimesint doit(io_channel chan, SSL_CTX *s_ctx); 1691573Srgrimes/*****************************************************************************/ 1701573Srgrimes/* 17171579Sdeischen * Decnet I/O routines. 1721573Srgrimes */ 1731573Srgrimesstatic int get(io_channel chan, char *buffer, int maxlen, int *length) 1741573Srgrimes{ 1751573Srgrimes int status; 17618971Speter struct io_status iosb; 1771573Srgrimes status = SYS$QIOW(0, chan, IO$_READVBLK, &iosb, 0, 0, 1781573Srgrimes buffer, maxlen, 0, 0, 0, 0); 1791573Srgrimes if ((status & 1) == 1) 1801573Srgrimes status = iosb.status; 1811573Srgrimes if ((status & 1) == 1) 1821573Srgrimes *length = iosb.count; 1831573Srgrimes return status; 1841573Srgrimes} 1851573Srgrimes 1861573Srgrimesstatic int put(io_channel chan, char *buffer, int length) 1871573Srgrimes{ 1881573Srgrimes int status; 1891573Srgrimes struct io_status iosb; 1901573Srgrimes status = SYS$QIOW(0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 1911573Srgrimes buffer, length, 0, 0, 0, 0); 1921573Srgrimes if ((status & 1) == 1) 1931573Srgrimes status = iosb.status; 1941573Srgrimes return status; 1951573Srgrimes} 1961573Srgrimes 1971573Srgrimes/***************************************************************************/ 1981573Srgrimes/* 1991573Srgrimes * Handle operations on the 'G' channel. 2001573Srgrimes */ 2011573Srgrimesstatic int general_request(io_channel chan, struct rpc_msg *msg, int length) 2021573Srgrimes{ 2031573Srgrimes return 48; 2041573Srgrimes} 2051573Srgrimes 2061573Srgrimes/***************************************************************************/ 2071573Srgrimesint main(int argc, char **argv) 2081573Srgrimes{ 2091573Srgrimes int status, length; 2101573Srgrimes io_channel chan; 2111573Srgrimes struct rpc_msg msg; 2121573Srgrimes 2131573Srgrimes char *CApath = NULL, *CAfile = NULL; 2145072Sbde int badop = 0; 2151573Srgrimes int ret = 1; 2161573Srgrimes int client_auth = 0; 2171573Srgrimes int server_auth = 0; 2181573Srgrimes SSL_CTX *s_ctx = NULL; 2191573Srgrimes /* 2201573Srgrimes * Confirm logical link with initiating client. 2211573Srgrimes */ 2221573Srgrimes LIB$INIT_TIMER(); 2231573Srgrimes status = SYS$ASSIGN(&sysnet, &chan, 0, 0, 0); 2241573Srgrimes printf("status of assign to SYS$NET: %d\n", status); 2251573Srgrimes /* 2261573Srgrimes * Initialize standard out and error files. 2279272Shsu */ 2281573Srgrimes if (bio_err == NULL) 2291573Srgrimes if ((bio_err = BIO_new(BIO_s_file())) != NULL) 2301573Srgrimes BIO_set_fp(bio_err, stderr, BIO_NOCLOSE); 2311573Srgrimes if (bio_stdout == NULL) 2321573Srgrimes if ((bio_stdout = BIO_new(BIO_s_file())) != NULL) 2331573Srgrimes BIO_set_fp(bio_stdout, stdout, BIO_NOCLOSE); 23428235Sdg /* 23528235Sdg * get the preferred cipher list and other initialization 2361573Srgrimes */ 2371573Srgrimes if (cipher == NULL) 2381573Srgrimes cipher = getenv("SSL_CIPHER"); 2391573Srgrimes printf("cipher list: %s\n", cipher ? cipher : "{undefined}"); 2401573Srgrimes 2411573Srgrimes SSL_load_error_strings(); 2421573Srgrimes OpenSSL_add_all_algorithms(); 2431573Srgrimes 2441573Srgrimes /* 2451573Srgrimes * DRM, this was the original, but there is no such thing as SSLv2() 2461573Srgrimes * s_ctx=SSL_CTX_new(SSLv2()); 2471573Srgrimes */ 2481573Srgrimes s_ctx = SSL_CTX_new(SSLv2_server_method()); 2491573Srgrimes 2501573Srgrimes if (s_ctx == NULL) 25132530Smckay goto end; 25232530Smckay 2531573Srgrimes SSL_CTX_use_certificate_file(s_ctx, TEST_SERVER_CERT, SSL_FILETYPE_PEM); 2541573Srgrimes SSL_CTX_use_RSAPrivateKey_file(s_ctx, TEST_SERVER_CERT, SSL_FILETYPE_PEM); 25528235Sdg printf("Loaded server certificate: '%s'\n", TEST_SERVER_CERT); 25628235Sdg 2571573Srgrimes /* 25832530Smckay * Take commands from client until bad status. 25932530Smckay */ 2601573Srgrimes LIB$SHOW_TIMER(); 2611573Srgrimes status = doit(chan, s_ctx); 262 LIB$SHOW_TIMER(); 263 /* 264 * do final cleanup and exit. 265 */ 266 end: 267 if (s_ctx != NULL) 268 SSL_CTX_free(s_ctx); 269 LIB$SHOW_TIMER(); 270 return 1; 271} 272 273int doit(io_channel chan, SSL_CTX *s_ctx) 274{ 275 int status, length, link_state; 276 struct rpc_msg msg; 277 278 SSL *s_ssl = NULL; 279 BIO *c_to_s = NULL; 280 BIO *s_to_c = NULL; 281 BIO *c_bio = NULL; 282 BIO *s_bio = NULL; 283 int i; 284 int done = 0; 285 286 s_ssl = SSL_new(s_ctx); 287 if (s_ssl == NULL) 288 goto err; 289 290 c_to_s = BIO_new(BIO_s_rtcp()); 291 s_to_c = BIO_new(BIO_s_rtcp()); 292 if ((s_to_c == NULL) || (c_to_s == NULL)) 293 goto err; 294/*- original, DRM 24-SEP-1997 295 BIO_set_fd ( c_to_s, "", chan ); 296 BIO_set_fd ( s_to_c, "", chan ); 297*/ 298 BIO_set_fd(c_to_s, 0, chan); 299 BIO_set_fd(s_to_c, 0, chan); 300 301 c_bio = BIO_new(BIO_f_ssl()); 302 s_bio = BIO_new(BIO_f_ssl()); 303 if ((c_bio == NULL) || (s_bio == NULL)) 304 goto err; 305 306 SSL_set_accept_state(s_ssl); 307 SSL_set_bio(s_ssl, c_to_s, s_to_c); 308 BIO_set_ssl(s_bio, s_ssl, BIO_CLOSE); 309 310 /* We can always do writes */ 311 printf("Begin doit main loop\n"); 312 /* 313 * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed. 314 */ 315 for (link_state = 0; link_state < 3;) { 316 /* 317 * Wait for remote end to request data action on A channel. 318 */ 319 while (link_state == 0) { 320 status = get(chan, (char *)&msg, sizeof(msg), &length); 321 if ((status & 1) == 0) { 322 printf("Error in main loop get: %d\n", status); 323 link_state = 3; 324 break; 325 } 326 if (length < RPC_HDR_SIZE) { 327 printf("Error in main loop get size: %d\n", length); 328 break; 329 link_state = 3; 330 } 331 if (msg.channel != 'A') { 332 printf("Error in main loop, unexpected channel: %c\n", 333 msg.channel); 334 break; 335 link_state = 3; 336 } 337 if (msg.function == 'G') { 338 link_state = 1; 339 } else if (msg.function == 'P') { 340 link_state = 2; /* write pending */ 341 } else if (msg.function == 'X') { 342 link_state = 3; 343 } else { 344 link_state = 3; 345 } 346 } 347 if (link_state == 1) { 348 i = BIO_read(s_bio, msg.data, msg.length); 349 if (i < 0) 350 link_state = 3; 351 else { 352 msg.channel = 'A'; 353 msg.function = 'C'; /* confirm */ 354 msg.length = i; 355 status = put(chan, (char *)&msg, i + RPC_HDR_SIZE); 356 if ((status & 1) == 0) 357 break; 358 link_state = 0; 359 } 360 } else if (link_state == 2) { 361 i = BIO_write(s_bio, msg.data, msg.length); 362 if (i < 0) 363 link_state = 3; 364 else { 365 msg.channel = 'A'; 366 msg.function = 'C'; /* confirm */ 367 msg.length = 0; 368 status = put(chan, (char *)&msg, RPC_HDR_SIZE); 369 if ((status & 1) == 0) 370 break; 371 link_state = 0; 372 } 373 } 374 } 375 fprintf(stdout, "DONE\n"); 376 err: 377 /* 378 * We have to set the BIO's to NULL otherwise they will be free()ed 379 * twice. Once when th s_ssl is SSL_free()ed and again when c_ssl is 380 * SSL_free()ed. This is a hack required because s_ssl and c_ssl are 381 * sharing the same BIO structure and SSL_set_bio() and SSL_free() 382 * automatically BIO_free non NULL entries. You should not normally do 383 * this or be required to do this 384 */ 385 s_ssl->rbio = NULL; 386 s_ssl->wbio = NULL; 387 388 if (c_to_s != NULL) 389 BIO_free(c_to_s); 390 if (s_to_c != NULL) 391 BIO_free(s_to_c); 392 if (c_bio != NULL) 393 BIO_free(c_bio); 394 if (s_bio != NULL) 395 BIO_free(s_bio); 396 return (0); 397} 398