174664626SKris Kennaway /* apps/s_server.c */ 274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 374664626SKris Kennaway * All rights reserved. 474664626SKris Kennaway * 574664626SKris Kennaway * This package is an SSL implementation written 674664626SKris Kennaway * by Eric Young (eay@cryptsoft.com). 774664626SKris Kennaway * The implementation was written so as to conform with Netscapes SSL. 874664626SKris Kennaway * 974664626SKris Kennaway * This library is free for commercial and non-commercial use as long as 1074664626SKris Kennaway * the following conditions are aheared to. The following conditions 1174664626SKris Kennaway * apply to all code found in this distribution, be it the RC4, RSA, 1274664626SKris Kennaway * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1374664626SKris Kennaway * included with this distribution is covered by the same copyright terms 1474664626SKris Kennaway * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1574664626SKris Kennaway * 1674664626SKris Kennaway * Copyright remains Eric Young's, and as such any Copyright notices in 1774664626SKris Kennaway * the code are not to be removed. 1874664626SKris Kennaway * If this package is used in a product, Eric Young should be given attribution 1974664626SKris Kennaway * as the author of the parts of the library used. 2074664626SKris Kennaway * This can be in the form of a textual message at program startup or 2174664626SKris Kennaway * in documentation (online or textual) provided with the package. 2274664626SKris Kennaway * 2374664626SKris Kennaway * Redistribution and use in source and binary forms, with or without 2474664626SKris Kennaway * modification, are permitted provided that the following conditions 2574664626SKris Kennaway * are met: 2674664626SKris Kennaway * 1. Redistributions of source code must retain the copyright 2774664626SKris Kennaway * notice, this list of conditions and the following disclaimer. 2874664626SKris Kennaway * 2. Redistributions in binary form must reproduce the above copyright 2974664626SKris Kennaway * notice, this list of conditions and the following disclaimer in the 3074664626SKris Kennaway * documentation and/or other materials provided with the distribution. 3174664626SKris Kennaway * 3. All advertising materials mentioning features or use of this software 3274664626SKris Kennaway * must display the following acknowledgement: 3374664626SKris Kennaway * "This product includes cryptographic software written by 3474664626SKris Kennaway * Eric Young (eay@cryptsoft.com)" 3574664626SKris Kennaway * The word 'cryptographic' can be left out if the rouines from the library 3674664626SKris Kennaway * being used are not cryptographic related :-). 3774664626SKris Kennaway * 4. If you include any Windows specific code (or a derivative thereof) from 3874664626SKris Kennaway * the apps directory (application code) you must include an acknowledgement: 3974664626SKris Kennaway * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4074664626SKris Kennaway * 4174664626SKris Kennaway * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4274664626SKris Kennaway * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4374664626SKris Kennaway * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4474664626SKris Kennaway * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4574664626SKris Kennaway * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4674664626SKris Kennaway * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4774664626SKris Kennaway * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4874664626SKris Kennaway * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4974664626SKris Kennaway * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5074664626SKris Kennaway * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5174664626SKris Kennaway * SUCH DAMAGE. 5274664626SKris Kennaway * 5374664626SKris Kennaway * The licence and distribution terms for any publically available version or 5474664626SKris Kennaway * derivative of this code cannot be changed. i.e. this code cannot simply be 5574664626SKris Kennaway * copied and put under another distribution licence 5674664626SKris Kennaway * [including the GNU Public Licence.] 5774664626SKris Kennaway */ 5874664626SKris Kennaway 5974664626SKris Kennaway #include <assert.h> 6074664626SKris Kennaway #include <stdio.h> 6174664626SKris Kennaway #include <stdlib.h> 6274664626SKris Kennaway #include <string.h> 6374664626SKris Kennaway #include <sys/types.h> 6474664626SKris Kennaway #include <sys/stat.h> 6574664626SKris Kennaway #ifdef NO_STDIO 6674664626SKris Kennaway #define APPS_WIN16 6774664626SKris Kennaway #endif 6874664626SKris Kennaway 6974664626SKris Kennaway /* With IPv6, it looks like Digital has mixed up the proper order of 7074664626SKris Kennaway recursive header file inclusion, resulting in the compiler complaining 7174664626SKris Kennaway that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which 7274664626SKris Kennaway is needed to have fileno() declared correctly... So let's define u_int */ 7374664626SKris Kennaway #if defined(VMS) && defined(__DECC) && !defined(__U_INT) 7474664626SKris Kennaway #define __U_INT 7574664626SKris Kennaway typedef unsigned int u_int; 7674664626SKris Kennaway #endif 7774664626SKris Kennaway 7874664626SKris Kennaway #include <openssl/lhash.h> 7974664626SKris Kennaway #include <openssl/bn.h> 8074664626SKris Kennaway #define USE_SOCKETS 8174664626SKris Kennaway #include "apps.h" 8274664626SKris Kennaway #include <openssl/err.h> 8374664626SKris Kennaway #include <openssl/pem.h> 8474664626SKris Kennaway #include <openssl/x509.h> 8574664626SKris Kennaway #include <openssl/ssl.h> 8674664626SKris Kennaway #include "s_apps.h" 8774664626SKris Kennaway 88f579bf8eSKris Kennaway #ifdef WINDOWS 89f579bf8eSKris Kennaway #include <conio.h> 90f579bf8eSKris Kennaway #endif 91f579bf8eSKris Kennaway 9274664626SKris Kennaway #if (defined(VMS) && __VMS_VER < 70000000) 9374664626SKris Kennaway /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 9474664626SKris Kennaway #undef FIONBIO 9574664626SKris Kennaway #endif 9674664626SKris Kennaway 9774664626SKris Kennaway #ifndef NO_RSA 9874664626SKris Kennaway static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); 9974664626SKris Kennaway #endif 10074664626SKris Kennaway static int sv_body(char *hostname, int s, unsigned char *context); 10174664626SKris Kennaway static int www_body(char *hostname, int s, unsigned char *context); 10274664626SKris Kennaway static void close_accept_socket(void ); 10374664626SKris Kennaway static void sv_usage(void); 10474664626SKris Kennaway static int init_ssl_connection(SSL *s); 10574664626SKris Kennaway static void print_stats(BIO *bp,SSL_CTX *ctx); 10674664626SKris Kennaway #ifndef NO_DH 107f579bf8eSKris Kennaway static DH *load_dh_param(char *dhfile); 10874664626SKris Kennaway static DH *get_dh512(void); 10974664626SKris Kennaway #endif 110f579bf8eSKris Kennaway #ifdef MONOLITH 111f579bf8eSKris Kennaway static void s_server_init(void); 112f579bf8eSKris Kennaway #endif 11374664626SKris Kennaway 11474664626SKris Kennaway #ifndef S_ISDIR 11574664626SKris Kennaway # if defined(_S_IFMT) && defined(_S_IFDIR) 11674664626SKris Kennaway # define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) 11774664626SKris Kennaway # else 11874664626SKris Kennaway # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 11974664626SKris Kennaway # endif 12074664626SKris Kennaway #endif 12174664626SKris Kennaway 12274664626SKris Kennaway #ifndef NO_DH 12374664626SKris Kennaway static unsigned char dh512_p[]={ 12474664626SKris Kennaway 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, 12574664626SKris Kennaway 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, 12674664626SKris Kennaway 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, 12774664626SKris Kennaway 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, 12874664626SKris Kennaway 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, 12974664626SKris Kennaway 0x47,0x74,0xE8,0x33, 13074664626SKris Kennaway }; 13174664626SKris Kennaway static unsigned char dh512_g[]={ 13274664626SKris Kennaway 0x02, 13374664626SKris Kennaway }; 13474664626SKris Kennaway 13574664626SKris Kennaway static DH *get_dh512(void) 13674664626SKris Kennaway { 13774664626SKris Kennaway DH *dh=NULL; 13874664626SKris Kennaway 13974664626SKris Kennaway if ((dh=DH_new()) == NULL) return(NULL); 14074664626SKris Kennaway dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); 14174664626SKris Kennaway dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); 14274664626SKris Kennaway if ((dh->p == NULL) || (dh->g == NULL)) 14374664626SKris Kennaway return(NULL); 14474664626SKris Kennaway return(dh); 14574664626SKris Kennaway } 14674664626SKris Kennaway #endif 14774664626SKris Kennaway 14874664626SKris Kennaway /* static int load_CA(SSL_CTX *ctx, char *file);*/ 14974664626SKris Kennaway 15074664626SKris Kennaway #undef BUFSIZZ 15174664626SKris Kennaway #define BUFSIZZ 16*1024 152f579bf8eSKris Kennaway static int bufsize=BUFSIZZ; 15374664626SKris Kennaway static int accept_socket= -1; 15474664626SKris Kennaway 15574664626SKris Kennaway #define TEST_CERT "server.pem" 15674664626SKris Kennaway #undef PROG 15774664626SKris Kennaway #define PROG s_server_main 15874664626SKris Kennaway 15974664626SKris Kennaway extern int verify_depth; 16074664626SKris Kennaway 16174664626SKris Kennaway static char *cipher=NULL; 16274664626SKris Kennaway static int s_server_verify=SSL_VERIFY_NONE; 16374664626SKris Kennaway static int s_server_session_id_context = 1; /* anything will do */ 16474664626SKris Kennaway static char *s_cert_file=TEST_CERT,*s_key_file=NULL; 16574664626SKris Kennaway static char *s_dcert_file=NULL,*s_dkey_file=NULL; 16674664626SKris Kennaway #ifdef FIONBIO 16774664626SKris Kennaway static int s_nbio=0; 16874664626SKris Kennaway #endif 16974664626SKris Kennaway static int s_nbio_test=0; 17074664626SKris Kennaway int s_crlf=0; 17174664626SKris Kennaway static SSL_CTX *ctx=NULL; 17274664626SKris Kennaway static int www=0; 17374664626SKris Kennaway 17474664626SKris Kennaway static BIO *bio_s_out=NULL; 17574664626SKris Kennaway static int s_debug=0; 17674664626SKris Kennaway static int s_quiet=0; 17774664626SKris Kennaway 178f579bf8eSKris Kennaway static int hack=0; 179f579bf8eSKris Kennaway 180f579bf8eSKris Kennaway #ifdef MONOLITH 18174664626SKris Kennaway static void s_server_init(void) 18274664626SKris Kennaway { 183f579bf8eSKris Kennaway accept_socket=-1; 18474664626SKris Kennaway cipher=NULL; 18574664626SKris Kennaway s_server_verify=SSL_VERIFY_NONE; 18674664626SKris Kennaway s_dcert_file=NULL; 18774664626SKris Kennaway s_dkey_file=NULL; 18874664626SKris Kennaway s_cert_file=TEST_CERT; 18974664626SKris Kennaway s_key_file=NULL; 19074664626SKris Kennaway #ifdef FIONBIO 19174664626SKris Kennaway s_nbio=0; 19274664626SKris Kennaway #endif 19374664626SKris Kennaway s_nbio_test=0; 19474664626SKris Kennaway ctx=NULL; 19574664626SKris Kennaway www=0; 19674664626SKris Kennaway 19774664626SKris Kennaway bio_s_out=NULL; 19874664626SKris Kennaway s_debug=0; 19974664626SKris Kennaway s_quiet=0; 200f579bf8eSKris Kennaway hack=0; 20174664626SKris Kennaway } 20274664626SKris Kennaway #endif 20374664626SKris Kennaway 20474664626SKris Kennaway static void sv_usage(void) 20574664626SKris Kennaway { 20674664626SKris Kennaway BIO_printf(bio_err,"usage: s_server [args ...]\n"); 20774664626SKris Kennaway BIO_printf(bio_err,"\n"); 20874664626SKris Kennaway BIO_printf(bio_err," -accept arg - port to accept on (default is %d)\n",PORT); 20974664626SKris Kennaway BIO_printf(bio_err," -context arg - set session ID context\n"); 21074664626SKris Kennaway BIO_printf(bio_err," -verify arg - turn on peer certificate verification\n"); 21174664626SKris Kennaway BIO_printf(bio_err," -Verify arg - turn on peer certificate verification, must have a cert.\n"); 21274664626SKris Kennaway BIO_printf(bio_err," -cert arg - certificate file to use, PEM format assumed\n"); 21374664626SKris Kennaway BIO_printf(bio_err," (default is %s)\n",TEST_CERT); 214f579bf8eSKris Kennaway BIO_printf(bio_err," -key arg - Private Key file to use, PEM format assumed, in cert file if\n"); 21574664626SKris Kennaway BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT); 21674664626SKris Kennaway BIO_printf(bio_err," -dcert arg - second certificate file to use (usually for DSA)\n"); 21774664626SKris Kennaway BIO_printf(bio_err," -dkey arg - second private key file to use (usually for DSA)\n"); 218f579bf8eSKris Kennaway BIO_printf(bio_err," -dhparam arg - DH parameter file to use, in cert file if not specified\n"); 219f579bf8eSKris Kennaway BIO_printf(bio_err," or a default set of parameters is used\n"); 22074664626SKris Kennaway #ifdef FIONBIO 22174664626SKris Kennaway BIO_printf(bio_err," -nbio - Run with non-blocking IO\n"); 22274664626SKris Kennaway #endif 22374664626SKris Kennaway BIO_printf(bio_err," -nbio_test - test with the non-blocking test bio\n"); 22474664626SKris Kennaway BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); 22574664626SKris Kennaway BIO_printf(bio_err," -debug - Print more output\n"); 22674664626SKris Kennaway BIO_printf(bio_err," -state - Print the SSL states\n"); 22774664626SKris Kennaway BIO_printf(bio_err," -CApath arg - PEM format directory of CA's\n"); 22874664626SKris Kennaway BIO_printf(bio_err," -CAfile arg - PEM format file of CA's\n"); 22974664626SKris Kennaway BIO_printf(bio_err," -nocert - Don't use any certificates (Anon-DH)\n"); 23074664626SKris Kennaway BIO_printf(bio_err," -cipher arg - play with 'openssl ciphers' to see what goes here\n"); 23174664626SKris Kennaway BIO_printf(bio_err," -quiet - No server output\n"); 23274664626SKris Kennaway BIO_printf(bio_err," -no_tmp_rsa - Do not generate a tmp RSA key\n"); 23374664626SKris Kennaway BIO_printf(bio_err," -ssl2 - Just talk SSLv2\n"); 23474664626SKris Kennaway BIO_printf(bio_err," -ssl3 - Just talk SSLv3\n"); 23574664626SKris Kennaway BIO_printf(bio_err," -tls1 - Just talk TLSv1\n"); 23674664626SKris Kennaway BIO_printf(bio_err," -no_ssl2 - Just disable SSLv2\n"); 23774664626SKris Kennaway BIO_printf(bio_err," -no_ssl3 - Just disable SSLv3\n"); 23874664626SKris Kennaway BIO_printf(bio_err," -no_tls1 - Just disable TLSv1\n"); 23974664626SKris Kennaway #ifndef NO_DH 24074664626SKris Kennaway BIO_printf(bio_err," -no_dhe - Disable ephemeral DH\n"); 24174664626SKris Kennaway #endif 242f579bf8eSKris Kennaway BIO_printf(bio_err," -bugs - Turn on SSL bug compatibility\n"); 24374664626SKris Kennaway BIO_printf(bio_err," -www - Respond to a 'GET /' with a status page\n"); 24474664626SKris Kennaway BIO_printf(bio_err," -WWW - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\n"); 24574664626SKris Kennaway } 24674664626SKris Kennaway 24774664626SKris Kennaway static int local_argc=0; 24874664626SKris Kennaway static char **local_argv; 24974664626SKris Kennaway 25074664626SKris Kennaway #ifdef CHARSET_EBCDIC 25174664626SKris Kennaway static int ebcdic_new(BIO *bi); 25274664626SKris Kennaway static int ebcdic_free(BIO *a); 25374664626SKris Kennaway static int ebcdic_read(BIO *b, char *out, int outl); 25474664626SKris Kennaway static int ebcdic_write(BIO *b, char *in, int inl); 25574664626SKris Kennaway static long ebcdic_ctrl(BIO *b, int cmd, long num, char *ptr); 25674664626SKris Kennaway static int ebcdic_gets(BIO *bp, char *buf, int size); 25774664626SKris Kennaway static int ebcdic_puts(BIO *bp, char *str); 25874664626SKris Kennaway 25974664626SKris Kennaway #define BIO_TYPE_EBCDIC_FILTER (18|0x0200) 26074664626SKris Kennaway static BIO_METHOD methods_ebcdic= 26174664626SKris Kennaway { 26274664626SKris Kennaway BIO_TYPE_EBCDIC_FILTER, 26374664626SKris Kennaway "EBCDIC/ASCII filter", 26474664626SKris Kennaway ebcdic_write, 26574664626SKris Kennaway ebcdic_read, 26674664626SKris Kennaway ebcdic_puts, 26774664626SKris Kennaway ebcdic_gets, 26874664626SKris Kennaway ebcdic_ctrl, 26974664626SKris Kennaway ebcdic_new, 27074664626SKris Kennaway ebcdic_free, 27174664626SKris Kennaway }; 27274664626SKris Kennaway 27374664626SKris Kennaway typedef struct 27474664626SKris Kennaway { 27574664626SKris Kennaway size_t alloced; 27674664626SKris Kennaway char buff[1]; 27774664626SKris Kennaway } EBCDIC_OUTBUFF; 27874664626SKris Kennaway 27974664626SKris Kennaway BIO_METHOD *BIO_f_ebcdic_filter() 28074664626SKris Kennaway { 28174664626SKris Kennaway return(&methods_ebcdic); 28274664626SKris Kennaway } 28374664626SKris Kennaway 28474664626SKris Kennaway static int ebcdic_new(BIO *bi) 28574664626SKris Kennaway { 28674664626SKris Kennaway EBCDIC_OUTBUFF *wbuf; 28774664626SKris Kennaway 28874664626SKris Kennaway wbuf = (EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + 1024); 28974664626SKris Kennaway wbuf->alloced = 1024; 29074664626SKris Kennaway wbuf->buff[0] = '\0'; 29174664626SKris Kennaway 29274664626SKris Kennaway bi->ptr=(char *)wbuf; 29374664626SKris Kennaway bi->init=1; 29474664626SKris Kennaway bi->flags=0; 29574664626SKris Kennaway return(1); 29674664626SKris Kennaway } 29774664626SKris Kennaway 29874664626SKris Kennaway static int ebcdic_free(BIO *a) 29974664626SKris Kennaway { 30074664626SKris Kennaway if (a == NULL) return(0); 30174664626SKris Kennaway if (a->ptr != NULL) 30274664626SKris Kennaway Free(a->ptr); 30374664626SKris Kennaway a->ptr=NULL; 30474664626SKris Kennaway a->init=0; 30574664626SKris Kennaway a->flags=0; 30674664626SKris Kennaway return(1); 30774664626SKris Kennaway } 30874664626SKris Kennaway 30974664626SKris Kennaway static int ebcdic_read(BIO *b, char *out, int outl) 31074664626SKris Kennaway { 31174664626SKris Kennaway int ret=0; 31274664626SKris Kennaway 31374664626SKris Kennaway if (out == NULL || outl == 0) return(0); 31474664626SKris Kennaway if (b->next_bio == NULL) return(0); 31574664626SKris Kennaway 31674664626SKris Kennaway ret=BIO_read(b->next_bio,out,outl); 31774664626SKris Kennaway if (ret > 0) 31874664626SKris Kennaway ascii2ebcdic(out,out,ret); 31974664626SKris Kennaway return(ret); 32074664626SKris Kennaway } 32174664626SKris Kennaway 32274664626SKris Kennaway static int ebcdic_write(BIO *b, char *in, int inl) 32374664626SKris Kennaway { 32474664626SKris Kennaway EBCDIC_OUTBUFF *wbuf; 32574664626SKris Kennaway int ret=0; 32674664626SKris Kennaway int num; 32774664626SKris Kennaway unsigned char n; 32874664626SKris Kennaway 32974664626SKris Kennaway if ((in == NULL) || (inl <= 0)) return(0); 33074664626SKris Kennaway if (b->next_bio == NULL) return(0); 33174664626SKris Kennaway 33274664626SKris Kennaway wbuf=(EBCDIC_OUTBUFF *)b->ptr; 33374664626SKris Kennaway 33474664626SKris Kennaway if (inl > (num = wbuf->alloced)) 33574664626SKris Kennaway { 33674664626SKris Kennaway num = num + num; /* double the size */ 33774664626SKris Kennaway if (num < inl) 33874664626SKris Kennaway num = inl; 339f579bf8eSKris Kennaway Free(wbuf); 34074664626SKris Kennaway wbuf=(EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + num); 34174664626SKris Kennaway 34274664626SKris Kennaway wbuf->alloced = num; 34374664626SKris Kennaway wbuf->buff[0] = '\0'; 34474664626SKris Kennaway 34574664626SKris Kennaway b->ptr=(char *)wbuf; 34674664626SKris Kennaway } 34774664626SKris Kennaway 34874664626SKris Kennaway ebcdic2ascii(wbuf->buff, in, inl); 34974664626SKris Kennaway 35074664626SKris Kennaway ret=BIO_write(b->next_bio, wbuf->buff, inl); 35174664626SKris Kennaway 35274664626SKris Kennaway return(ret); 35374664626SKris Kennaway } 35474664626SKris Kennaway 35574664626SKris Kennaway static long ebcdic_ctrl(BIO *b, int cmd, long num, char *ptr) 35674664626SKris Kennaway { 35774664626SKris Kennaway long ret; 35874664626SKris Kennaway 35974664626SKris Kennaway if (b->next_bio == NULL) return(0); 36074664626SKris Kennaway switch (cmd) 36174664626SKris Kennaway { 36274664626SKris Kennaway case BIO_CTRL_DUP: 36374664626SKris Kennaway ret=0L; 36474664626SKris Kennaway break; 36574664626SKris Kennaway default: 36674664626SKris Kennaway ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 36774664626SKris Kennaway break; 36874664626SKris Kennaway } 36974664626SKris Kennaway return(ret); 37074664626SKris Kennaway } 37174664626SKris Kennaway 37274664626SKris Kennaway static int ebcdic_gets(BIO *bp, char *buf, int size) 37374664626SKris Kennaway { 37474664626SKris Kennaway int i, ret; 37574664626SKris Kennaway if (bp->next_bio == NULL) return(0); 37674664626SKris Kennaway /* return(BIO_gets(bp->next_bio,buf,size));*/ 37774664626SKris Kennaway for (i=0; i<size-1; ++i) 37874664626SKris Kennaway { 37974664626SKris Kennaway ret = ebcdic_read(bp,&buf[i],1); 38074664626SKris Kennaway if (ret <= 0) 38174664626SKris Kennaway break; 38274664626SKris Kennaway else if (buf[i] == '\n') 38374664626SKris Kennaway { 38474664626SKris Kennaway ++i; 38574664626SKris Kennaway break; 38674664626SKris Kennaway } 38774664626SKris Kennaway } 38874664626SKris Kennaway if (i < size) 38974664626SKris Kennaway buf[i] = '\0'; 39074664626SKris Kennaway return (ret < 0 && i == 0) ? ret : i; 39174664626SKris Kennaway } 39274664626SKris Kennaway 39374664626SKris Kennaway static int ebcdic_puts(BIO *bp, char *str) 39474664626SKris Kennaway { 39574664626SKris Kennaway if (bp->next_bio == NULL) return(0); 39674664626SKris Kennaway return ebcdic_write(bp, str, strlen(str)); 39774664626SKris Kennaway } 39874664626SKris Kennaway #endif 39974664626SKris Kennaway 400f579bf8eSKris Kennaway int MAIN(int, char **); 401f579bf8eSKris Kennaway 40274664626SKris Kennaway int MAIN(int argc, char *argv[]) 40374664626SKris Kennaway { 40474664626SKris Kennaway short port=PORT; 40574664626SKris Kennaway char *CApath=NULL,*CAfile=NULL; 40674664626SKris Kennaway char *context = NULL; 407f579bf8eSKris Kennaway char *dhfile = NULL; 40874664626SKris Kennaway int badop=0,bugs=0; 40974664626SKris Kennaway int ret=1; 41074664626SKris Kennaway int off=0; 41174664626SKris Kennaway int no_tmp_rsa=0,no_dhe=0,nocert=0; 41274664626SKris Kennaway int state=0; 41374664626SKris Kennaway SSL_METHOD *meth=NULL; 41474664626SKris Kennaway #ifndef NO_DH 41574664626SKris Kennaway DH *dh=NULL; 41674664626SKris Kennaway #endif 41774664626SKris Kennaway 41874664626SKris Kennaway #if !defined(NO_SSL2) && !defined(NO_SSL3) 41974664626SKris Kennaway meth=SSLv23_server_method(); 42074664626SKris Kennaway #elif !defined(NO_SSL3) 42174664626SKris Kennaway meth=SSLv3_server_method(); 42274664626SKris Kennaway #elif !defined(NO_SSL2) 42374664626SKris Kennaway meth=SSLv2_server_method(); 42474664626SKris Kennaway #endif 42574664626SKris Kennaway 42674664626SKris Kennaway local_argc=argc; 42774664626SKris Kennaway local_argv=argv; 42874664626SKris Kennaway 42974664626SKris Kennaway apps_startup(); 430f579bf8eSKris Kennaway #ifdef MONOLITH 431f579bf8eSKris Kennaway s_server_init(); 432f579bf8eSKris Kennaway #endif 43374664626SKris Kennaway 43474664626SKris Kennaway if (bio_err == NULL) 43574664626SKris Kennaway bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); 43674664626SKris Kennaway 43774664626SKris Kennaway verify_depth=0; 43874664626SKris Kennaway #ifdef FIONBIO 43974664626SKris Kennaway s_nbio=0; 44074664626SKris Kennaway #endif 44174664626SKris Kennaway s_nbio_test=0; 44274664626SKris Kennaway 44374664626SKris Kennaway argc--; 44474664626SKris Kennaway argv++; 44574664626SKris Kennaway 44674664626SKris Kennaway while (argc >= 1) 44774664626SKris Kennaway { 44874664626SKris Kennaway if ((strcmp(*argv,"-port") == 0) || 44974664626SKris Kennaway (strcmp(*argv,"-accept") == 0)) 45074664626SKris Kennaway { 45174664626SKris Kennaway if (--argc < 1) goto bad; 45274664626SKris Kennaway if (!extract_port(*(++argv),&port)) 45374664626SKris Kennaway goto bad; 45474664626SKris Kennaway } 45574664626SKris Kennaway else if (strcmp(*argv,"-verify") == 0) 45674664626SKris Kennaway { 45774664626SKris Kennaway s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE; 45874664626SKris Kennaway if (--argc < 1) goto bad; 45974664626SKris Kennaway verify_depth=atoi(*(++argv)); 46074664626SKris Kennaway BIO_printf(bio_err,"verify depth is %d\n",verify_depth); 46174664626SKris Kennaway } 46274664626SKris Kennaway else if (strcmp(*argv,"-Verify") == 0) 46374664626SKris Kennaway { 46474664626SKris Kennaway s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| 46574664626SKris Kennaway SSL_VERIFY_CLIENT_ONCE; 46674664626SKris Kennaway if (--argc < 1) goto bad; 46774664626SKris Kennaway verify_depth=atoi(*(++argv)); 46874664626SKris Kennaway BIO_printf(bio_err,"verify depth is %d, must return a certificate\n",verify_depth); 46974664626SKris Kennaway } 47074664626SKris Kennaway else if (strcmp(*argv,"-context") == 0) 47174664626SKris Kennaway { 47274664626SKris Kennaway if (--argc < 1) goto bad; 47374664626SKris Kennaway context= *(++argv); 47474664626SKris Kennaway } 47574664626SKris Kennaway else if (strcmp(*argv,"-cert") == 0) 47674664626SKris Kennaway { 47774664626SKris Kennaway if (--argc < 1) goto bad; 47874664626SKris Kennaway s_cert_file= *(++argv); 47974664626SKris Kennaway } 48074664626SKris Kennaway else if (strcmp(*argv,"-key") == 0) 48174664626SKris Kennaway { 48274664626SKris Kennaway if (--argc < 1) goto bad; 48374664626SKris Kennaway s_key_file= *(++argv); 48474664626SKris Kennaway } 485f579bf8eSKris Kennaway else if (strcmp(*argv,"-dhparam") == 0) 486f579bf8eSKris Kennaway { 487f579bf8eSKris Kennaway if (--argc < 1) goto bad; 488f579bf8eSKris Kennaway dhfile = *(++argv); 489f579bf8eSKris Kennaway } 49074664626SKris Kennaway else if (strcmp(*argv,"-dcert") == 0) 49174664626SKris Kennaway { 49274664626SKris Kennaway if (--argc < 1) goto bad; 49374664626SKris Kennaway s_dcert_file= *(++argv); 49474664626SKris Kennaway } 49574664626SKris Kennaway else if (strcmp(*argv,"-dkey") == 0) 49674664626SKris Kennaway { 49774664626SKris Kennaway if (--argc < 1) goto bad; 49874664626SKris Kennaway s_dkey_file= *(++argv); 49974664626SKris Kennaway } 50074664626SKris Kennaway else if (strcmp(*argv,"-nocert") == 0) 50174664626SKris Kennaway { 50274664626SKris Kennaway nocert=1; 50374664626SKris Kennaway } 50474664626SKris Kennaway else if (strcmp(*argv,"-CApath") == 0) 50574664626SKris Kennaway { 50674664626SKris Kennaway if (--argc < 1) goto bad; 50774664626SKris Kennaway CApath= *(++argv); 50874664626SKris Kennaway } 50974664626SKris Kennaway else if (strcmp(*argv,"-cipher") == 0) 51074664626SKris Kennaway { 51174664626SKris Kennaway if (--argc < 1) goto bad; 51274664626SKris Kennaway cipher= *(++argv); 51374664626SKris Kennaway } 51474664626SKris Kennaway else if (strcmp(*argv,"-CAfile") == 0) 51574664626SKris Kennaway { 51674664626SKris Kennaway if (--argc < 1) goto bad; 51774664626SKris Kennaway CAfile= *(++argv); 51874664626SKris Kennaway } 51974664626SKris Kennaway #ifdef FIONBIO 52074664626SKris Kennaway else if (strcmp(*argv,"-nbio") == 0) 52174664626SKris Kennaway { s_nbio=1; } 52274664626SKris Kennaway #endif 52374664626SKris Kennaway else if (strcmp(*argv,"-nbio_test") == 0) 52474664626SKris Kennaway { 52574664626SKris Kennaway #ifdef FIONBIO 52674664626SKris Kennaway s_nbio=1; 52774664626SKris Kennaway #endif 52874664626SKris Kennaway s_nbio_test=1; 52974664626SKris Kennaway } 53074664626SKris Kennaway else if (strcmp(*argv,"-debug") == 0) 53174664626SKris Kennaway { s_debug=1; } 53274664626SKris Kennaway else if (strcmp(*argv,"-hack") == 0) 53374664626SKris Kennaway { hack=1; } 53474664626SKris Kennaway else if (strcmp(*argv,"-state") == 0) 53574664626SKris Kennaway { state=1; } 53674664626SKris Kennaway else if (strcmp(*argv,"-crlf") == 0) 53774664626SKris Kennaway { s_crlf=1; } 53874664626SKris Kennaway else if (strcmp(*argv,"-quiet") == 0) 53974664626SKris Kennaway { s_quiet=1; } 54074664626SKris Kennaway else if (strcmp(*argv,"-bugs") == 0) 54174664626SKris Kennaway { bugs=1; } 54274664626SKris Kennaway else if (strcmp(*argv,"-no_tmp_rsa") == 0) 54374664626SKris Kennaway { no_tmp_rsa=1; } 54474664626SKris Kennaway else if (strcmp(*argv,"-no_dhe") == 0) 54574664626SKris Kennaway { no_dhe=1; } 54674664626SKris Kennaway else if (strcmp(*argv,"-www") == 0) 54774664626SKris Kennaway { www=1; } 54874664626SKris Kennaway else if (strcmp(*argv,"-WWW") == 0) 54974664626SKris Kennaway { www=2; } 55074664626SKris Kennaway else if (strcmp(*argv,"-no_ssl2") == 0) 55174664626SKris Kennaway { off|=SSL_OP_NO_SSLv2; } 55274664626SKris Kennaway else if (strcmp(*argv,"-no_ssl3") == 0) 55374664626SKris Kennaway { off|=SSL_OP_NO_SSLv3; } 55474664626SKris Kennaway else if (strcmp(*argv,"-no_tls1") == 0) 55574664626SKris Kennaway { off|=SSL_OP_NO_TLSv1; } 55674664626SKris Kennaway #ifndef NO_SSL2 55774664626SKris Kennaway else if (strcmp(*argv,"-ssl2") == 0) 55874664626SKris Kennaway { meth=SSLv2_server_method(); } 55974664626SKris Kennaway #endif 56074664626SKris Kennaway #ifndef NO_SSL3 56174664626SKris Kennaway else if (strcmp(*argv,"-ssl3") == 0) 56274664626SKris Kennaway { meth=SSLv3_server_method(); } 56374664626SKris Kennaway #endif 56474664626SKris Kennaway #ifndef NO_TLS1 56574664626SKris Kennaway else if (strcmp(*argv,"-tls1") == 0) 56674664626SKris Kennaway { meth=TLSv1_server_method(); } 56774664626SKris Kennaway #endif 56874664626SKris Kennaway else 56974664626SKris Kennaway { 57074664626SKris Kennaway BIO_printf(bio_err,"unknown option %s\n",*argv); 57174664626SKris Kennaway badop=1; 57274664626SKris Kennaway break; 57374664626SKris Kennaway } 57474664626SKris Kennaway argc--; 57574664626SKris Kennaway argv++; 57674664626SKris Kennaway } 57774664626SKris Kennaway if (badop) 57874664626SKris Kennaway { 57974664626SKris Kennaway bad: 58074664626SKris Kennaway sv_usage(); 58174664626SKris Kennaway goto end; 58274664626SKris Kennaway } 58374664626SKris Kennaway 584f579bf8eSKris Kennaway app_RAND_load_file(NULL, bio_err, 0); 585f579bf8eSKris Kennaway 58674664626SKris Kennaway if (bio_s_out == NULL) 58774664626SKris Kennaway { 58874664626SKris Kennaway if (s_quiet && !s_debug) 58974664626SKris Kennaway { 59074664626SKris Kennaway bio_s_out=BIO_new(BIO_s_null()); 59174664626SKris Kennaway } 59274664626SKris Kennaway else 59374664626SKris Kennaway { 59474664626SKris Kennaway if (bio_s_out == NULL) 59574664626SKris Kennaway bio_s_out=BIO_new_fp(stdout,BIO_NOCLOSE); 59674664626SKris Kennaway } 59774664626SKris Kennaway } 59874664626SKris Kennaway 59974664626SKris Kennaway #if !defined(NO_RSA) || !defined(NO_DSA) 60074664626SKris Kennaway if (nocert) 60174664626SKris Kennaway #endif 60274664626SKris Kennaway { 60374664626SKris Kennaway s_cert_file=NULL; 60474664626SKris Kennaway s_key_file=NULL; 60574664626SKris Kennaway s_dcert_file=NULL; 60674664626SKris Kennaway s_dkey_file=NULL; 60774664626SKris Kennaway } 60874664626SKris Kennaway 60974664626SKris Kennaway SSL_load_error_strings(); 610f579bf8eSKris Kennaway OpenSSL_add_ssl_algorithms(); 61174664626SKris Kennaway 61274664626SKris Kennaway ctx=SSL_CTX_new(meth); 61374664626SKris Kennaway if (ctx == NULL) 61474664626SKris Kennaway { 61574664626SKris Kennaway ERR_print_errors(bio_err); 61674664626SKris Kennaway goto end; 61774664626SKris Kennaway } 61874664626SKris Kennaway 61974664626SKris Kennaway SSL_CTX_set_quiet_shutdown(ctx,1); 62074664626SKris Kennaway if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL); 62174664626SKris Kennaway if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); 62274664626SKris Kennaway SSL_CTX_set_options(ctx,off); 62374664626SKris Kennaway if (hack) SSL_CTX_set_options(ctx,SSL_OP_NON_EXPORT_FIRST); 62474664626SKris Kennaway 62574664626SKris Kennaway if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); 62674664626SKris Kennaway 62774664626SKris Kennaway SSL_CTX_sess_set_cache_size(ctx,128); 62874664626SKris Kennaway 62974664626SKris Kennaway #if 0 63074664626SKris Kennaway if (cipher == NULL) cipher=getenv("SSL_CIPHER"); 63174664626SKris Kennaway #endif 63274664626SKris Kennaway 63374664626SKris Kennaway #if 0 63474664626SKris Kennaway if (s_cert_file == NULL) 63574664626SKris Kennaway { 63674664626SKris Kennaway BIO_printf(bio_err,"You must specify a certificate file for the server to use\n"); 63774664626SKris Kennaway goto end; 63874664626SKris Kennaway } 63974664626SKris Kennaway #endif 64074664626SKris Kennaway 64174664626SKris Kennaway if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || 64274664626SKris Kennaway (!SSL_CTX_set_default_verify_paths(ctx))) 64374664626SKris Kennaway { 64474664626SKris Kennaway /* BIO_printf(bio_err,"X509_load_verify_locations\n"); */ 64574664626SKris Kennaway ERR_print_errors(bio_err); 64674664626SKris Kennaway /* goto end; */ 64774664626SKris Kennaway } 64874664626SKris Kennaway 64974664626SKris Kennaway #ifndef NO_DH 65074664626SKris Kennaway if (!no_dhe) 65174664626SKris Kennaway { 652f579bf8eSKris Kennaway dh=load_dh_param(dhfile ? dhfile : s_cert_file); 65374664626SKris Kennaway if (dh != NULL) 65474664626SKris Kennaway { 65574664626SKris Kennaway BIO_printf(bio_s_out,"Setting temp DH parameters\n"); 65674664626SKris Kennaway } 65774664626SKris Kennaway else 65874664626SKris Kennaway { 65974664626SKris Kennaway BIO_printf(bio_s_out,"Using default temp DH parameters\n"); 66074664626SKris Kennaway dh=get_dh512(); 66174664626SKris Kennaway } 66274664626SKris Kennaway (void)BIO_flush(bio_s_out); 66374664626SKris Kennaway 66474664626SKris Kennaway SSL_CTX_set_tmp_dh(ctx,dh); 66574664626SKris Kennaway DH_free(dh); 66674664626SKris Kennaway } 66774664626SKris Kennaway #endif 66874664626SKris Kennaway 66974664626SKris Kennaway if (!set_cert_stuff(ctx,s_cert_file,s_key_file)) 67074664626SKris Kennaway goto end; 67174664626SKris Kennaway if (s_dcert_file != NULL) 67274664626SKris Kennaway { 67374664626SKris Kennaway if (!set_cert_stuff(ctx,s_dcert_file,s_dkey_file)) 67474664626SKris Kennaway goto end; 67574664626SKris Kennaway } 67674664626SKris Kennaway 67774664626SKris Kennaway #ifndef NO_RSA 67874664626SKris Kennaway #if 1 67974664626SKris Kennaway SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb); 68074664626SKris Kennaway #else 68174664626SKris Kennaway if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx)) 68274664626SKris Kennaway { 68374664626SKris Kennaway RSA *rsa; 68474664626SKris Kennaway 68574664626SKris Kennaway BIO_printf(bio_s_out,"Generating temp (512 bit) RSA key..."); 68674664626SKris Kennaway BIO_flush(bio_s_out); 68774664626SKris Kennaway 68874664626SKris Kennaway rsa=RSA_generate_key(512,RSA_F4,NULL); 68974664626SKris Kennaway 69074664626SKris Kennaway if (!SSL_CTX_set_tmp_rsa(ctx,rsa)) 69174664626SKris Kennaway { 69274664626SKris Kennaway ERR_print_errors(bio_err); 69374664626SKris Kennaway goto end; 69474664626SKris Kennaway } 69574664626SKris Kennaway RSA_free(rsa); 69674664626SKris Kennaway BIO_printf(bio_s_out,"\n"); 69774664626SKris Kennaway } 69874664626SKris Kennaway #endif 69974664626SKris Kennaway #endif 70074664626SKris Kennaway 70174664626SKris Kennaway if (cipher != NULL) 702f579bf8eSKris Kennaway if(!SSL_CTX_set_cipher_list(ctx,cipher)) { 703f579bf8eSKris Kennaway BIO_printf(bio_err,"error setting cipher list\n"); 704f579bf8eSKris Kennaway ERR_print_errors(bio_err); 705f579bf8eSKris Kennaway goto end; 706f579bf8eSKris Kennaway } 70774664626SKris Kennaway SSL_CTX_set_verify(ctx,s_server_verify,verify_callback); 70874664626SKris Kennaway SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context, 70974664626SKris Kennaway sizeof s_server_session_id_context); 71074664626SKris Kennaway 711f579bf8eSKris Kennaway if (CAfile != NULL) 71274664626SKris Kennaway SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); 71374664626SKris Kennaway 71474664626SKris Kennaway BIO_printf(bio_s_out,"ACCEPT\n"); 71574664626SKris Kennaway if (www) 71674664626SKris Kennaway do_server(port,&accept_socket,www_body, context); 71774664626SKris Kennaway else 71874664626SKris Kennaway do_server(port,&accept_socket,sv_body, context); 71974664626SKris Kennaway print_stats(bio_s_out,ctx); 72074664626SKris Kennaway ret=0; 72174664626SKris Kennaway end: 72274664626SKris Kennaway if (ctx != NULL) SSL_CTX_free(ctx); 72374664626SKris Kennaway if (bio_s_out != NULL) 72474664626SKris Kennaway { 72574664626SKris Kennaway BIO_free(bio_s_out); 72674664626SKris Kennaway bio_s_out=NULL; 72774664626SKris Kennaway } 72874664626SKris Kennaway EXIT(ret); 72974664626SKris Kennaway } 73074664626SKris Kennaway 73174664626SKris Kennaway static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) 73274664626SKris Kennaway { 73374664626SKris Kennaway BIO_printf(bio,"%4ld items in the session cache\n", 73474664626SKris Kennaway SSL_CTX_sess_number(ssl_ctx)); 73574664626SKris Kennaway BIO_printf(bio,"%4d client connects (SSL_connect())\n", 73674664626SKris Kennaway SSL_CTX_sess_connect(ssl_ctx)); 73774664626SKris Kennaway BIO_printf(bio,"%4d client renegotiates (SSL_connect())\n", 73874664626SKris Kennaway SSL_CTX_sess_connect_renegotiate(ssl_ctx)); 73974664626SKris Kennaway BIO_printf(bio,"%4d client connects that finished\n", 74074664626SKris Kennaway SSL_CTX_sess_connect_good(ssl_ctx)); 74174664626SKris Kennaway BIO_printf(bio,"%4d server accepts (SSL_accept())\n", 74274664626SKris Kennaway SSL_CTX_sess_accept(ssl_ctx)); 74374664626SKris Kennaway BIO_printf(bio,"%4d server renegotiates (SSL_accept())\n", 74474664626SKris Kennaway SSL_CTX_sess_accept_renegotiate(ssl_ctx)); 74574664626SKris Kennaway BIO_printf(bio,"%4d server accepts that finished\n", 74674664626SKris Kennaway SSL_CTX_sess_accept_good(ssl_ctx)); 74774664626SKris Kennaway BIO_printf(bio,"%4d session cache hits\n",SSL_CTX_sess_hits(ssl_ctx)); 74874664626SKris Kennaway BIO_printf(bio,"%4d session cache misses\n",SSL_CTX_sess_misses(ssl_ctx)); 74974664626SKris Kennaway BIO_printf(bio,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ssl_ctx)); 75074664626SKris Kennaway BIO_printf(bio,"%4d callback cache hits\n",SSL_CTX_sess_cb_hits(ssl_ctx)); 75174664626SKris Kennaway BIO_printf(bio,"%4d cache full overflows (%d allowed)\n", 75274664626SKris Kennaway SSL_CTX_sess_cache_full(ssl_ctx), 75374664626SKris Kennaway SSL_CTX_sess_get_cache_size(ssl_ctx)); 75474664626SKris Kennaway } 75574664626SKris Kennaway 75674664626SKris Kennaway static int sv_body(char *hostname, int s, unsigned char *context) 75774664626SKris Kennaway { 75874664626SKris Kennaway char *buf=NULL; 75974664626SKris Kennaway fd_set readfds; 76074664626SKris Kennaway int ret=1,width; 76174664626SKris Kennaway int k,i; 76274664626SKris Kennaway unsigned long l; 76374664626SKris Kennaway SSL *con=NULL; 76474664626SKris Kennaway BIO *sbio; 765f579bf8eSKris Kennaway #ifdef WINDOWS 766f579bf8eSKris Kennaway struct timeval tv; 767f579bf8eSKris Kennaway #endif 76874664626SKris Kennaway 76974664626SKris Kennaway if ((buf=Malloc(bufsize)) == NULL) 77074664626SKris Kennaway { 77174664626SKris Kennaway BIO_printf(bio_err,"out of memory\n"); 77274664626SKris Kennaway goto err; 77374664626SKris Kennaway } 77474664626SKris Kennaway #ifdef FIONBIO 77574664626SKris Kennaway if (s_nbio) 77674664626SKris Kennaway { 77774664626SKris Kennaway unsigned long sl=1; 77874664626SKris Kennaway 77974664626SKris Kennaway if (!s_quiet) 78074664626SKris Kennaway BIO_printf(bio_err,"turning on non blocking io\n"); 78174664626SKris Kennaway if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0) 78274664626SKris Kennaway ERR_print_errors(bio_err); 78374664626SKris Kennaway } 78474664626SKris Kennaway #endif 78574664626SKris Kennaway 78674664626SKris Kennaway if (con == NULL) { 787f579bf8eSKris Kennaway con=SSL_new(ctx); 78874664626SKris Kennaway if(context) 78974664626SKris Kennaway SSL_set_session_id_context(con, context, 79074664626SKris Kennaway strlen((char *)context)); 79174664626SKris Kennaway } 79274664626SKris Kennaway SSL_clear(con); 79374664626SKris Kennaway 79474664626SKris Kennaway sbio=BIO_new_socket(s,BIO_NOCLOSE); 79574664626SKris Kennaway if (s_nbio_test) 79674664626SKris Kennaway { 79774664626SKris Kennaway BIO *test; 79874664626SKris Kennaway 79974664626SKris Kennaway test=BIO_new(BIO_f_nbio_test()); 80074664626SKris Kennaway sbio=BIO_push(test,sbio); 80174664626SKris Kennaway } 80274664626SKris Kennaway SSL_set_bio(con,sbio,sbio); 80374664626SKris Kennaway SSL_set_accept_state(con); 80474664626SKris Kennaway /* SSL_set_fd(con,s); */ 80574664626SKris Kennaway 80674664626SKris Kennaway if (s_debug) 80774664626SKris Kennaway { 80874664626SKris Kennaway con->debug=1; 80974664626SKris Kennaway BIO_set_callback(SSL_get_rbio(con),bio_dump_cb); 81074664626SKris Kennaway BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out); 81174664626SKris Kennaway } 81274664626SKris Kennaway 81374664626SKris Kennaway width=s+1; 81474664626SKris Kennaway for (;;) 81574664626SKris Kennaway { 816f579bf8eSKris Kennaway int read_from_terminal; 817f579bf8eSKris Kennaway int read_from_sslcon; 818f579bf8eSKris Kennaway 819f579bf8eSKris Kennaway read_from_terminal = 0; 820f579bf8eSKris Kennaway read_from_sslcon = SSL_pending(con); 821f579bf8eSKris Kennaway 822f579bf8eSKris Kennaway if (!read_from_sslcon) 823f579bf8eSKris Kennaway { 82474664626SKris Kennaway FD_ZERO(&readfds); 82574664626SKris Kennaway #ifndef WINDOWS 82674664626SKris Kennaway FD_SET(fileno(stdin),&readfds); 82774664626SKris Kennaway #endif 82874664626SKris Kennaway FD_SET(s,&readfds); 82974664626SKris Kennaway /* Note: under VMS with SOCKETSHR the second parameter is 83074664626SKris Kennaway * currently of type (int *) whereas under other systems 83174664626SKris Kennaway * it is (void *) if you don't have a cast it will choke 83274664626SKris Kennaway * the compiler: if you do have a cast then you can either 83374664626SKris Kennaway * go for (int *) or (void *). 83474664626SKris Kennaway */ 835f579bf8eSKris Kennaway #ifdef WINDOWS 836f579bf8eSKris Kennaway /* Under Windows we can't select on stdin: only 837f579bf8eSKris Kennaway * on sockets. As a workaround we timeout the select every 838f579bf8eSKris Kennaway * second and check for any keypress. In a proper Windows 839f579bf8eSKris Kennaway * application we wouldn't do this because it is inefficient. 840f579bf8eSKris Kennaway */ 841f579bf8eSKris Kennaway tv.tv_sec = 1; 842f579bf8eSKris Kennaway tv.tv_usec = 0; 843f579bf8eSKris Kennaway i=select(width,(void *)&readfds,NULL,NULL,&tv); 844f579bf8eSKris Kennaway if((i < 0) || (!i && !_kbhit() ) )continue; 845f579bf8eSKris Kennaway if(_kbhit()) 846f579bf8eSKris Kennaway read_from_terminal = 1; 847f579bf8eSKris Kennaway #else 84874664626SKris Kennaway i=select(width,(void *)&readfds,NULL,NULL,NULL); 84974664626SKris Kennaway if (i <= 0) continue; 85074664626SKris Kennaway if (FD_ISSET(fileno(stdin),&readfds)) 851f579bf8eSKris Kennaway read_from_terminal = 1; 852f579bf8eSKris Kennaway #endif 853f579bf8eSKris Kennaway if (FD_ISSET(s,&readfds)) 854f579bf8eSKris Kennaway read_from_sslcon = 1; 855f579bf8eSKris Kennaway } 856f579bf8eSKris Kennaway if (read_from_terminal) 85774664626SKris Kennaway { 85874664626SKris Kennaway if (s_crlf) 85974664626SKris Kennaway { 86074664626SKris Kennaway int j, lf_num; 86174664626SKris Kennaway 86274664626SKris Kennaway i=read(fileno(stdin), buf, bufsize/2); 86374664626SKris Kennaway lf_num = 0; 86474664626SKris Kennaway /* both loops are skipped when i <= 0 */ 86574664626SKris Kennaway for (j = 0; j < i; j++) 86674664626SKris Kennaway if (buf[j] == '\n') 86774664626SKris Kennaway lf_num++; 86874664626SKris Kennaway for (j = i-1; j >= 0; j--) 86974664626SKris Kennaway { 87074664626SKris Kennaway buf[j+lf_num] = buf[j]; 87174664626SKris Kennaway if (buf[j] == '\n') 87274664626SKris Kennaway { 87374664626SKris Kennaway lf_num--; 87474664626SKris Kennaway i++; 87574664626SKris Kennaway buf[j+lf_num] = '\r'; 87674664626SKris Kennaway } 87774664626SKris Kennaway } 87874664626SKris Kennaway assert(lf_num == 0); 87974664626SKris Kennaway } 88074664626SKris Kennaway else 88174664626SKris Kennaway i=read(fileno(stdin),buf,bufsize); 88274664626SKris Kennaway if (!s_quiet) 88374664626SKris Kennaway { 88474664626SKris Kennaway if ((i <= 0) || (buf[0] == 'Q')) 88574664626SKris Kennaway { 88674664626SKris Kennaway BIO_printf(bio_s_out,"DONE\n"); 88774664626SKris Kennaway SHUTDOWN(s); 88874664626SKris Kennaway close_accept_socket(); 88974664626SKris Kennaway ret= -11; 89074664626SKris Kennaway goto err; 89174664626SKris Kennaway } 89274664626SKris Kennaway if ((i <= 0) || (buf[0] == 'q')) 89374664626SKris Kennaway { 89474664626SKris Kennaway BIO_printf(bio_s_out,"DONE\n"); 89574664626SKris Kennaway SHUTDOWN(s); 89674664626SKris Kennaway /* close_accept_socket(); 89774664626SKris Kennaway ret= -11;*/ 89874664626SKris Kennaway goto err; 89974664626SKris Kennaway } 90074664626SKris Kennaway if ((buf[0] == 'r') && 90174664626SKris Kennaway ((buf[1] == '\n') || (buf[1] == '\r'))) 90274664626SKris Kennaway { 90374664626SKris Kennaway SSL_renegotiate(con); 90474664626SKris Kennaway i=SSL_do_handshake(con); 90574664626SKris Kennaway printf("SSL_do_handshake -> %d\n",i); 90674664626SKris Kennaway i=0; /*13; */ 90774664626SKris Kennaway continue; 90874664626SKris Kennaway /* strcpy(buf,"server side RE-NEGOTIATE\n"); */ 90974664626SKris Kennaway } 91074664626SKris Kennaway if ((buf[0] == 'R') && 91174664626SKris Kennaway ((buf[1] == '\n') || (buf[1] == '\r'))) 91274664626SKris Kennaway { 91374664626SKris Kennaway SSL_set_verify(con, 91474664626SKris Kennaway SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,NULL); 91574664626SKris Kennaway SSL_renegotiate(con); 91674664626SKris Kennaway i=SSL_do_handshake(con); 91774664626SKris Kennaway printf("SSL_do_handshake -> %d\n",i); 91874664626SKris Kennaway i=0; /* 13; */ 91974664626SKris Kennaway continue; 92074664626SKris Kennaway /* strcpy(buf,"server side RE-NEGOTIATE asking for client cert\n"); */ 92174664626SKris Kennaway } 92274664626SKris Kennaway if (buf[0] == 'P') 92374664626SKris Kennaway { 92474664626SKris Kennaway static char *str="Lets print some clear text\n"; 92574664626SKris Kennaway BIO_write(SSL_get_wbio(con),str,strlen(str)); 92674664626SKris Kennaway } 92774664626SKris Kennaway if (buf[0] == 'S') 92874664626SKris Kennaway { 92974664626SKris Kennaway print_stats(bio_s_out,SSL_get_SSL_CTX(con)); 93074664626SKris Kennaway } 93174664626SKris Kennaway } 93274664626SKris Kennaway #ifdef CHARSET_EBCDIC 93374664626SKris Kennaway ebcdic2ascii(buf,buf,i); 93474664626SKris Kennaway #endif 93574664626SKris Kennaway l=k=0; 93674664626SKris Kennaway for (;;) 93774664626SKris Kennaway { 93874664626SKris Kennaway /* should do a select for the write */ 93974664626SKris Kennaway #ifdef RENEG 94074664626SKris Kennaway { static count=0; if (++count == 100) { count=0; SSL_renegotiate(con); } } 94174664626SKris Kennaway #endif 94274664626SKris Kennaway k=SSL_write(con,&(buf[l]),(unsigned int)i); 94374664626SKris Kennaway switch (SSL_get_error(con,k)) 94474664626SKris Kennaway { 94574664626SKris Kennaway case SSL_ERROR_NONE: 94674664626SKris Kennaway break; 94774664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 94874664626SKris Kennaway case SSL_ERROR_WANT_READ: 94974664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 95074664626SKris Kennaway BIO_printf(bio_s_out,"Write BLOCK\n"); 95174664626SKris Kennaway break; 95274664626SKris Kennaway case SSL_ERROR_SYSCALL: 95374664626SKris Kennaway case SSL_ERROR_SSL: 95474664626SKris Kennaway BIO_printf(bio_s_out,"ERROR\n"); 95574664626SKris Kennaway ERR_print_errors(bio_err); 95674664626SKris Kennaway ret=1; 95774664626SKris Kennaway goto err; 95874664626SKris Kennaway /* break; */ 95974664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 96074664626SKris Kennaway BIO_printf(bio_s_out,"DONE\n"); 96174664626SKris Kennaway ret=1; 96274664626SKris Kennaway goto err; 96374664626SKris Kennaway } 96474664626SKris Kennaway l+=k; 96574664626SKris Kennaway i-=k; 96674664626SKris Kennaway if (i <= 0) break; 96774664626SKris Kennaway } 96874664626SKris Kennaway } 969f579bf8eSKris Kennaway if (read_from_sslcon) 97074664626SKris Kennaway { 97174664626SKris Kennaway if (!SSL_is_init_finished(con)) 97274664626SKris Kennaway { 97374664626SKris Kennaway i=init_ssl_connection(con); 97474664626SKris Kennaway 97574664626SKris Kennaway if (i < 0) 97674664626SKris Kennaway { 97774664626SKris Kennaway ret=0; 97874664626SKris Kennaway goto err; 97974664626SKris Kennaway } 98074664626SKris Kennaway else if (i == 0) 98174664626SKris Kennaway { 98274664626SKris Kennaway ret=1; 98374664626SKris Kennaway goto err; 98474664626SKris Kennaway } 98574664626SKris Kennaway } 98674664626SKris Kennaway else 98774664626SKris Kennaway { 98874664626SKris Kennaway again: 98974664626SKris Kennaway i=SSL_read(con,(char *)buf,bufsize); 99074664626SKris Kennaway switch (SSL_get_error(con,i)) 99174664626SKris Kennaway { 99274664626SKris Kennaway case SSL_ERROR_NONE: 99374664626SKris Kennaway #ifdef CHARSET_EBCDIC 99474664626SKris Kennaway ascii2ebcdic(buf,buf,i); 99574664626SKris Kennaway #endif 99674664626SKris Kennaway write(fileno(stdout),buf, 99774664626SKris Kennaway (unsigned int)i); 99874664626SKris Kennaway if (SSL_pending(con)) goto again; 99974664626SKris Kennaway break; 100074664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 100174664626SKris Kennaway case SSL_ERROR_WANT_READ: 100274664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 100374664626SKris Kennaway BIO_printf(bio_s_out,"Read BLOCK\n"); 100474664626SKris Kennaway break; 100574664626SKris Kennaway case SSL_ERROR_SYSCALL: 100674664626SKris Kennaway case SSL_ERROR_SSL: 100774664626SKris Kennaway BIO_printf(bio_s_out,"ERROR\n"); 100874664626SKris Kennaway ERR_print_errors(bio_err); 100974664626SKris Kennaway ret=1; 101074664626SKris Kennaway goto err; 101174664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 101274664626SKris Kennaway BIO_printf(bio_s_out,"DONE\n"); 101374664626SKris Kennaway ret=1; 101474664626SKris Kennaway goto err; 101574664626SKris Kennaway } 101674664626SKris Kennaway } 101774664626SKris Kennaway } 101874664626SKris Kennaway } 101974664626SKris Kennaway err: 102074664626SKris Kennaway BIO_printf(bio_s_out,"shutting down SSL\n"); 102174664626SKris Kennaway #if 1 102274664626SKris Kennaway SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); 102374664626SKris Kennaway #else 102474664626SKris Kennaway SSL_shutdown(con); 102574664626SKris Kennaway #endif 102674664626SKris Kennaway if (con != NULL) SSL_free(con); 102774664626SKris Kennaway BIO_printf(bio_s_out,"CONNECTION CLOSED\n"); 102874664626SKris Kennaway if (buf != NULL) 102974664626SKris Kennaway { 103074664626SKris Kennaway memset(buf,0,bufsize); 103174664626SKris Kennaway Free(buf); 103274664626SKris Kennaway } 103374664626SKris Kennaway if (ret >= 0) 103474664626SKris Kennaway BIO_printf(bio_s_out,"ACCEPT\n"); 103574664626SKris Kennaway return(ret); 103674664626SKris Kennaway } 103774664626SKris Kennaway 103874664626SKris Kennaway static void close_accept_socket(void) 103974664626SKris Kennaway { 104074664626SKris Kennaway BIO_printf(bio_err,"shutdown accept socket\n"); 104174664626SKris Kennaway if (accept_socket >= 0) 104274664626SKris Kennaway { 104374664626SKris Kennaway SHUTDOWN2(accept_socket); 104474664626SKris Kennaway } 104574664626SKris Kennaway } 104674664626SKris Kennaway 104774664626SKris Kennaway static int init_ssl_connection(SSL *con) 104874664626SKris Kennaway { 104974664626SKris Kennaway int i; 105074664626SKris Kennaway const char *str; 105174664626SKris Kennaway X509 *peer; 105274664626SKris Kennaway long verify_error; 105374664626SKris Kennaway MS_STATIC char buf[BUFSIZ]; 105474664626SKris Kennaway 105574664626SKris Kennaway if ((i=SSL_accept(con)) <= 0) 105674664626SKris Kennaway { 105774664626SKris Kennaway if (BIO_sock_should_retry(i)) 105874664626SKris Kennaway { 105974664626SKris Kennaway BIO_printf(bio_s_out,"DELAY\n"); 106074664626SKris Kennaway return(1); 106174664626SKris Kennaway } 106274664626SKris Kennaway 106374664626SKris Kennaway BIO_printf(bio_err,"ERROR\n"); 106474664626SKris Kennaway verify_error=SSL_get_verify_result(con); 106574664626SKris Kennaway if (verify_error != X509_V_OK) 106674664626SKris Kennaway { 106774664626SKris Kennaway BIO_printf(bio_err,"verify error:%s\n", 106874664626SKris Kennaway X509_verify_cert_error_string(verify_error)); 106974664626SKris Kennaway } 107074664626SKris Kennaway else 107174664626SKris Kennaway ERR_print_errors(bio_err); 107274664626SKris Kennaway return(0); 107374664626SKris Kennaway } 107474664626SKris Kennaway 107574664626SKris Kennaway PEM_write_bio_SSL_SESSION(bio_s_out,SSL_get_session(con)); 107674664626SKris Kennaway 107774664626SKris Kennaway peer=SSL_get_peer_certificate(con); 107874664626SKris Kennaway if (peer != NULL) 107974664626SKris Kennaway { 108074664626SKris Kennaway BIO_printf(bio_s_out,"Client certificate\n"); 108174664626SKris Kennaway PEM_write_bio_X509(bio_s_out,peer); 108274664626SKris Kennaway X509_NAME_oneline(X509_get_subject_name(peer),buf,BUFSIZ); 108374664626SKris Kennaway BIO_printf(bio_s_out,"subject=%s\n",buf); 108474664626SKris Kennaway X509_NAME_oneline(X509_get_issuer_name(peer),buf,BUFSIZ); 108574664626SKris Kennaway BIO_printf(bio_s_out,"issuer=%s\n",buf); 108674664626SKris Kennaway X509_free(peer); 108774664626SKris Kennaway } 108874664626SKris Kennaway 108974664626SKris Kennaway if (SSL_get_shared_ciphers(con,buf,BUFSIZ) != NULL) 109074664626SKris Kennaway BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf); 109174664626SKris Kennaway str=SSL_CIPHER_get_name(SSL_get_current_cipher(con)); 109274664626SKris Kennaway BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)"); 109374664626SKris Kennaway if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n"); 109474664626SKris Kennaway if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) & 109574664626SKris Kennaway TLS1_FLAGS_TLS_PADDING_BUG) 109674664626SKris Kennaway BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n"); 109774664626SKris Kennaway 109874664626SKris Kennaway return(1); 109974664626SKris Kennaway } 110074664626SKris Kennaway 110174664626SKris Kennaway #ifndef NO_DH 1102f579bf8eSKris Kennaway static DH *load_dh_param(char *dhfile) 110374664626SKris Kennaway { 110474664626SKris Kennaway DH *ret=NULL; 110574664626SKris Kennaway BIO *bio; 110674664626SKris Kennaway 1107f579bf8eSKris Kennaway if ((bio=BIO_new_file(dhfile,"r")) == NULL) 110874664626SKris Kennaway goto err; 110974664626SKris Kennaway ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL); 111074664626SKris Kennaway err: 111174664626SKris Kennaway if (bio != NULL) BIO_free(bio); 111274664626SKris Kennaway return(ret); 111374664626SKris Kennaway } 111474664626SKris Kennaway #endif 111574664626SKris Kennaway 111674664626SKris Kennaway #if 0 111774664626SKris Kennaway static int load_CA(SSL_CTX *ctx, char *file) 111874664626SKris Kennaway { 111974664626SKris Kennaway FILE *in; 112074664626SKris Kennaway X509 *x=NULL; 112174664626SKris Kennaway 112274664626SKris Kennaway if ((in=fopen(file,"r")) == NULL) 112374664626SKris Kennaway return(0); 112474664626SKris Kennaway 112574664626SKris Kennaway for (;;) 112674664626SKris Kennaway { 112774664626SKris Kennaway if (PEM_read_X509(in,&x,NULL) == NULL) 112874664626SKris Kennaway break; 112974664626SKris Kennaway SSL_CTX_add_client_CA(ctx,x); 113074664626SKris Kennaway } 113174664626SKris Kennaway if (x != NULL) X509_free(x); 113274664626SKris Kennaway fclose(in); 113374664626SKris Kennaway return(1); 113474664626SKris Kennaway } 113574664626SKris Kennaway #endif 113674664626SKris Kennaway 113774664626SKris Kennaway static int www_body(char *hostname, int s, unsigned char *context) 113874664626SKris Kennaway { 113974664626SKris Kennaway char *buf=NULL; 114074664626SKris Kennaway int ret=1; 114174664626SKris Kennaway int i,j,k,blank,dot; 114274664626SKris Kennaway struct stat st_buf; 114374664626SKris Kennaway SSL *con; 114474664626SKris Kennaway SSL_CIPHER *c; 114574664626SKris Kennaway BIO *io,*ssl_bio,*sbio; 114674664626SKris Kennaway long total_bytes; 114774664626SKris Kennaway 114874664626SKris Kennaway buf=Malloc(bufsize); 114974664626SKris Kennaway if (buf == NULL) return(0); 115074664626SKris Kennaway io=BIO_new(BIO_f_buffer()); 115174664626SKris Kennaway ssl_bio=BIO_new(BIO_f_ssl()); 115274664626SKris Kennaway if ((io == NULL) || (ssl_bio == NULL)) goto err; 115374664626SKris Kennaway 115474664626SKris Kennaway #ifdef FIONBIO 115574664626SKris Kennaway if (s_nbio) 115674664626SKris Kennaway { 115774664626SKris Kennaway unsigned long sl=1; 115874664626SKris Kennaway 115974664626SKris Kennaway if (!s_quiet) 116074664626SKris Kennaway BIO_printf(bio_err,"turning on non blocking io\n"); 116174664626SKris Kennaway if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0) 116274664626SKris Kennaway ERR_print_errors(bio_err); 116374664626SKris Kennaway } 116474664626SKris Kennaway #endif 116574664626SKris Kennaway 116674664626SKris Kennaway /* lets make the output buffer a reasonable size */ 116774664626SKris Kennaway if (!BIO_set_write_buffer_size(io,bufsize)) goto err; 116874664626SKris Kennaway 1169f579bf8eSKris Kennaway if ((con=SSL_new(ctx)) == NULL) goto err; 117074664626SKris Kennaway if(context) SSL_set_session_id_context(con, context, 117174664626SKris Kennaway strlen((char *)context)); 117274664626SKris Kennaway 117374664626SKris Kennaway sbio=BIO_new_socket(s,BIO_NOCLOSE); 117474664626SKris Kennaway if (s_nbio_test) 117574664626SKris Kennaway { 117674664626SKris Kennaway BIO *test; 117774664626SKris Kennaway 117874664626SKris Kennaway test=BIO_new(BIO_f_nbio_test()); 117974664626SKris Kennaway sbio=BIO_push(test,sbio); 118074664626SKris Kennaway } 118174664626SKris Kennaway SSL_set_bio(con,sbio,sbio); 118274664626SKris Kennaway SSL_set_accept_state(con); 118374664626SKris Kennaway 118474664626SKris Kennaway /* SSL_set_fd(con,s); */ 118574664626SKris Kennaway BIO_set_ssl(ssl_bio,con,BIO_CLOSE); 118674664626SKris Kennaway BIO_push(io,ssl_bio); 118774664626SKris Kennaway #ifdef CHARSET_EBCDIC 118874664626SKris Kennaway io = BIO_push(BIO_new(BIO_f_ebcdic_filter()),io); 118974664626SKris Kennaway #endif 119074664626SKris Kennaway 119174664626SKris Kennaway if (s_debug) 119274664626SKris Kennaway { 119374664626SKris Kennaway con->debug=1; 119474664626SKris Kennaway BIO_set_callback(SSL_get_rbio(con),bio_dump_cb); 119574664626SKris Kennaway BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out); 119674664626SKris Kennaway } 119774664626SKris Kennaway 119874664626SKris Kennaway blank=0; 119974664626SKris Kennaway for (;;) 120074664626SKris Kennaway { 120174664626SKris Kennaway if (hack) 120274664626SKris Kennaway { 120374664626SKris Kennaway i=SSL_accept(con); 120474664626SKris Kennaway 120574664626SKris Kennaway switch (SSL_get_error(con,i)) 120674664626SKris Kennaway { 120774664626SKris Kennaway case SSL_ERROR_NONE: 120874664626SKris Kennaway break; 120974664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 121074664626SKris Kennaway case SSL_ERROR_WANT_READ: 121174664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 121274664626SKris Kennaway continue; 121374664626SKris Kennaway case SSL_ERROR_SYSCALL: 121474664626SKris Kennaway case SSL_ERROR_SSL: 121574664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 121674664626SKris Kennaway ret=1; 121774664626SKris Kennaway goto err; 121874664626SKris Kennaway /* break; */ 121974664626SKris Kennaway } 122074664626SKris Kennaway 122174664626SKris Kennaway SSL_renegotiate(con); 122274664626SKris Kennaway SSL_write(con,NULL,0); 122374664626SKris Kennaway } 122474664626SKris Kennaway 122574664626SKris Kennaway i=BIO_gets(io,buf,bufsize-1); 122674664626SKris Kennaway if (i < 0) /* error */ 122774664626SKris Kennaway { 122874664626SKris Kennaway if (!BIO_should_retry(io)) 122974664626SKris Kennaway { 123074664626SKris Kennaway if (!s_quiet) 123174664626SKris Kennaway ERR_print_errors(bio_err); 123274664626SKris Kennaway goto err; 123374664626SKris Kennaway } 123474664626SKris Kennaway else 123574664626SKris Kennaway { 123674664626SKris Kennaway BIO_printf(bio_s_out,"read R BLOCK\n"); 123774664626SKris Kennaway #ifndef MSDOS 123874664626SKris Kennaway sleep(1); 123974664626SKris Kennaway #endif 124074664626SKris Kennaway continue; 124174664626SKris Kennaway } 124274664626SKris Kennaway } 124374664626SKris Kennaway else if (i == 0) /* end of input */ 124474664626SKris Kennaway { 124574664626SKris Kennaway ret=1; 124674664626SKris Kennaway goto end; 124774664626SKris Kennaway } 124874664626SKris Kennaway 124974664626SKris Kennaway /* else we have data */ 125074664626SKris Kennaway if ( ((www == 1) && (strncmp("GET ",buf,4) == 0)) || 125174664626SKris Kennaway ((www == 2) && (strncmp("GET /stats ",buf,10) == 0))) 125274664626SKris Kennaway { 125374664626SKris Kennaway char *p; 125474664626SKris Kennaway X509 *peer; 125574664626SKris Kennaway STACK_OF(SSL_CIPHER) *sk; 125674664626SKris Kennaway static char *space=" "; 125774664626SKris Kennaway 125874664626SKris Kennaway BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); 125974664626SKris Kennaway BIO_puts(io,"<HTML><BODY BGCOLOR=\"#ffffff\">\n"); 126074664626SKris Kennaway BIO_puts(io,"<pre>\n"); 126174664626SKris Kennaway /* BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/ 126274664626SKris Kennaway BIO_puts(io,"\n"); 126374664626SKris Kennaway for (i=0; i<local_argc; i++) 126474664626SKris Kennaway { 126574664626SKris Kennaway BIO_puts(io,local_argv[i]); 126674664626SKris Kennaway BIO_write(io," ",1); 126774664626SKris Kennaway } 126874664626SKris Kennaway BIO_puts(io,"\n"); 126974664626SKris Kennaway 127074664626SKris Kennaway /* The following is evil and should not really 127174664626SKris Kennaway * be done */ 127274664626SKris Kennaway BIO_printf(io,"Ciphers supported in s_server binary\n"); 127374664626SKris Kennaway sk=SSL_get_ciphers(con); 127474664626SKris Kennaway j=sk_SSL_CIPHER_num(sk); 127574664626SKris Kennaway for (i=0; i<j; i++) 127674664626SKris Kennaway { 127774664626SKris Kennaway c=sk_SSL_CIPHER_value(sk,i); 127874664626SKris Kennaway BIO_printf(io,"%-11s:%-25s", 127974664626SKris Kennaway SSL_CIPHER_get_version(c), 128074664626SKris Kennaway SSL_CIPHER_get_name(c)); 128174664626SKris Kennaway if ((((i+1)%2) == 0) && (i+1 != j)) 128274664626SKris Kennaway BIO_puts(io,"\n"); 128374664626SKris Kennaway } 128474664626SKris Kennaway BIO_puts(io,"\n"); 128574664626SKris Kennaway p=SSL_get_shared_ciphers(con,buf,bufsize); 128674664626SKris Kennaway if (p != NULL) 128774664626SKris Kennaway { 128874664626SKris Kennaway BIO_printf(io,"---\nCiphers common between both SSL end points:\n"); 128974664626SKris Kennaway j=i=0; 129074664626SKris Kennaway while (*p) 129174664626SKris Kennaway { 129274664626SKris Kennaway if (*p == ':') 129374664626SKris Kennaway { 129474664626SKris Kennaway BIO_write(io,space,26-j); 129574664626SKris Kennaway i++; 129674664626SKris Kennaway j=0; 129774664626SKris Kennaway BIO_write(io,((i%3)?" ":"\n"),1); 129874664626SKris Kennaway } 129974664626SKris Kennaway else 130074664626SKris Kennaway { 130174664626SKris Kennaway BIO_write(io,p,1); 130274664626SKris Kennaway j++; 130374664626SKris Kennaway } 130474664626SKris Kennaway p++; 130574664626SKris Kennaway } 130674664626SKris Kennaway BIO_puts(io,"\n"); 130774664626SKris Kennaway } 130874664626SKris Kennaway BIO_printf(io,((con->hit) 130974664626SKris Kennaway ?"---\nReused, " 131074664626SKris Kennaway :"---\nNew, ")); 131174664626SKris Kennaway c=SSL_get_current_cipher(con); 131274664626SKris Kennaway BIO_printf(io,"%s, Cipher is %s\n", 131374664626SKris Kennaway SSL_CIPHER_get_version(c), 131474664626SKris Kennaway SSL_CIPHER_get_name(c)); 131574664626SKris Kennaway SSL_SESSION_print(io,SSL_get_session(con)); 131674664626SKris Kennaway BIO_printf(io,"---\n"); 131774664626SKris Kennaway print_stats(io,SSL_get_SSL_CTX(con)); 131874664626SKris Kennaway BIO_printf(io,"---\n"); 131974664626SKris Kennaway peer=SSL_get_peer_certificate(con); 132074664626SKris Kennaway if (peer != NULL) 132174664626SKris Kennaway { 132274664626SKris Kennaway BIO_printf(io,"Client certificate\n"); 132374664626SKris Kennaway X509_print(io,peer); 132474664626SKris Kennaway PEM_write_bio_X509(io,peer); 132574664626SKris Kennaway } 132674664626SKris Kennaway else 132774664626SKris Kennaway BIO_puts(io,"no client certificate available\n"); 132874664626SKris Kennaway BIO_puts(io,"</BODY></HTML>\r\n\r\n"); 132974664626SKris Kennaway break; 133074664626SKris Kennaway } 133174664626SKris Kennaway else if ((www == 2) && (strncmp("GET /",buf,5) == 0)) 133274664626SKris Kennaway { 133374664626SKris Kennaway BIO *file; 133474664626SKris Kennaway char *p,*e; 133574664626SKris Kennaway static char *text="HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"; 133674664626SKris Kennaway 133774664626SKris Kennaway /* skip the '/' */ 133874664626SKris Kennaway p= &(buf[5]); 133974664626SKris Kennaway dot=0; 134074664626SKris Kennaway for (e=p; *e != '\0'; e++) 134174664626SKris Kennaway { 134274664626SKris Kennaway if (e[0] == ' ') break; 134374664626SKris Kennaway if ( (e[0] == '.') && 134474664626SKris Kennaway (strncmp(&(e[-1]),"/../",4) == 0)) 134574664626SKris Kennaway dot=1; 134674664626SKris Kennaway } 134774664626SKris Kennaway 134874664626SKris Kennaway 134974664626SKris Kennaway if (*e == '\0') 135074664626SKris Kennaway { 135174664626SKris Kennaway BIO_puts(io,text); 135274664626SKris Kennaway BIO_printf(io,"'%s' is an invalid file name\r\n",p); 135374664626SKris Kennaway break; 135474664626SKris Kennaway } 135574664626SKris Kennaway *e='\0'; 135674664626SKris Kennaway 135774664626SKris Kennaway if (dot) 135874664626SKris Kennaway { 135974664626SKris Kennaway BIO_puts(io,text); 136074664626SKris Kennaway BIO_printf(io,"'%s' contains '..' reference\r\n",p); 136174664626SKris Kennaway break; 136274664626SKris Kennaway } 136374664626SKris Kennaway 136474664626SKris Kennaway if (*p == '/') 136574664626SKris Kennaway { 136674664626SKris Kennaway BIO_puts(io,text); 136774664626SKris Kennaway BIO_printf(io,"'%s' is an invalid path\r\n",p); 136874664626SKris Kennaway break; 136974664626SKris Kennaway } 137074664626SKris Kennaway 137174664626SKris Kennaway /* append if a directory lookup */ 137274664626SKris Kennaway if (e[-1] == '/') 137374664626SKris Kennaway strcat(p,"index.html"); 137474664626SKris Kennaway 137574664626SKris Kennaway /* if a directory, do the index thang */ 137674664626SKris Kennaway if (stat(p,&st_buf) < 0) 137774664626SKris Kennaway { 137874664626SKris Kennaway BIO_puts(io,text); 137974664626SKris Kennaway BIO_printf(io,"Error accessing '%s'\r\n",p); 138074664626SKris Kennaway ERR_print_errors(io); 138174664626SKris Kennaway break; 138274664626SKris Kennaway } 138374664626SKris Kennaway if (S_ISDIR(st_buf.st_mode)) 138474664626SKris Kennaway { 138574664626SKris Kennaway strcat(p,"/index.html"); 138674664626SKris Kennaway } 138774664626SKris Kennaway 138874664626SKris Kennaway if ((file=BIO_new_file(p,"r")) == NULL) 138974664626SKris Kennaway { 139074664626SKris Kennaway BIO_puts(io,text); 139174664626SKris Kennaway BIO_printf(io,"Error opening '%s'\r\n",p); 139274664626SKris Kennaway ERR_print_errors(io); 139374664626SKris Kennaway break; 139474664626SKris Kennaway } 139574664626SKris Kennaway 139674664626SKris Kennaway if (!s_quiet) 139774664626SKris Kennaway BIO_printf(bio_err,"FILE:%s\n",p); 139874664626SKris Kennaway 139974664626SKris Kennaway i=strlen(p); 140074664626SKris Kennaway if ( ((i > 5) && (strcmp(&(p[i-5]),".html") == 0)) || 140174664626SKris Kennaway ((i > 4) && (strcmp(&(p[i-4]),".php") == 0)) || 140274664626SKris Kennaway ((i > 4) && (strcmp(&(p[i-4]),".htm") == 0))) 140374664626SKris Kennaway BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); 140474664626SKris Kennaway else 140574664626SKris Kennaway BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); 140674664626SKris Kennaway /* send the file */ 140774664626SKris Kennaway total_bytes=0; 140874664626SKris Kennaway for (;;) 140974664626SKris Kennaway { 141074664626SKris Kennaway i=BIO_read(file,buf,bufsize); 141174664626SKris Kennaway if (i <= 0) break; 141274664626SKris Kennaway 141374664626SKris Kennaway #ifdef RENEG 141474664626SKris Kennaway total_bytes+=i; 141574664626SKris Kennaway fprintf(stderr,"%d\n",i); 141674664626SKris Kennaway if (total_bytes > 3*1024) 141774664626SKris Kennaway { 141874664626SKris Kennaway total_bytes=0; 141974664626SKris Kennaway fprintf(stderr,"RENEGOTIATE\n"); 142074664626SKris Kennaway SSL_renegotiate(con); 142174664626SKris Kennaway } 142274664626SKris Kennaway #endif 142374664626SKris Kennaway 142474664626SKris Kennaway for (j=0; j<i; ) 142574664626SKris Kennaway { 142674664626SKris Kennaway #ifdef RENEG 142774664626SKris Kennaway { static count=0; if (++count == 13) { SSL_renegotiate(con); } } 142874664626SKris Kennaway #endif 142974664626SKris Kennaway k=BIO_write(io,&(buf[j]),i-j); 143074664626SKris Kennaway if (k <= 0) 143174664626SKris Kennaway { 143274664626SKris Kennaway if (!BIO_should_retry(io)) 143374664626SKris Kennaway goto write_error; 143474664626SKris Kennaway else 143574664626SKris Kennaway { 143674664626SKris Kennaway BIO_printf(bio_s_out,"rwrite W BLOCK\n"); 143774664626SKris Kennaway } 143874664626SKris Kennaway } 143974664626SKris Kennaway else 144074664626SKris Kennaway { 144174664626SKris Kennaway j+=k; 144274664626SKris Kennaway } 144374664626SKris Kennaway } 144474664626SKris Kennaway } 144574664626SKris Kennaway write_error: 144674664626SKris Kennaway BIO_free(file); 144774664626SKris Kennaway break; 144874664626SKris Kennaway } 144974664626SKris Kennaway } 145074664626SKris Kennaway 145174664626SKris Kennaway for (;;) 145274664626SKris Kennaway { 145374664626SKris Kennaway i=(int)BIO_flush(io); 145474664626SKris Kennaway if (i <= 0) 145574664626SKris Kennaway { 145674664626SKris Kennaway if (!BIO_should_retry(io)) 145774664626SKris Kennaway break; 145874664626SKris Kennaway } 145974664626SKris Kennaway else 146074664626SKris Kennaway break; 146174664626SKris Kennaway } 146274664626SKris Kennaway end: 146374664626SKris Kennaway #if 1 146474664626SKris Kennaway /* make sure we re-use sessions */ 146574664626SKris Kennaway SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); 146674664626SKris Kennaway #else 1467f579bf8eSKris Kennaway /* This kills performance */ 146874664626SKris Kennaway /* SSL_shutdown(con); A shutdown gets sent in the 146974664626SKris Kennaway * BIO_free_all(io) procession */ 147074664626SKris Kennaway #endif 147174664626SKris Kennaway 147274664626SKris Kennaway err: 147374664626SKris Kennaway 147474664626SKris Kennaway if (ret >= 0) 147574664626SKris Kennaway BIO_printf(bio_s_out,"ACCEPT\n"); 147674664626SKris Kennaway 147774664626SKris Kennaway if (buf != NULL) Free(buf); 147874664626SKris Kennaway if (io != NULL) BIO_free_all(io); 147974664626SKris Kennaway /* if (ssl_bio != NULL) BIO_free(ssl_bio);*/ 148074664626SKris Kennaway return(ret); 148174664626SKris Kennaway } 148274664626SKris Kennaway 148374664626SKris Kennaway #ifndef NO_RSA 148474664626SKris Kennaway static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) 148574664626SKris Kennaway { 148674664626SKris Kennaway static RSA *rsa_tmp=NULL; 148774664626SKris Kennaway 148874664626SKris Kennaway if (rsa_tmp == NULL) 148974664626SKris Kennaway { 149074664626SKris Kennaway if (!s_quiet) 149174664626SKris Kennaway { 149274664626SKris Kennaway BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength); 149374664626SKris Kennaway (void)BIO_flush(bio_err); 149474664626SKris Kennaway } 149574664626SKris Kennaway rsa_tmp=RSA_generate_key(keylength,RSA_F4,NULL,NULL); 149674664626SKris Kennaway if (!s_quiet) 149774664626SKris Kennaway { 149874664626SKris Kennaway BIO_printf(bio_err,"\n"); 149974664626SKris Kennaway (void)BIO_flush(bio_err); 150074664626SKris Kennaway } 150174664626SKris Kennaway } 150274664626SKris Kennaway return(rsa_tmp); 150374664626SKris Kennaway } 150474664626SKris Kennaway #endif 1505