X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_server.c;h=a92db5cd1bfdafcb894f28d63cd1cbccff0fc7b5;hp=de0c712109212bbbc41fbf9717615ab9fde357db;hb=8a208cba97b0d08cfc6f07bb2f0e0d1f305a0b13;hpb=f73e07cf420ddad22b6148d8cbe28daf84ccae2d diff --git a/apps/s_server.c b/apps/s_server.c index de0c712109..a92db5cd1b 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -56,6 +56,7 @@ * [including the GNU Public Licence.] */ +#include #include #include #include @@ -64,47 +65,58 @@ #ifdef NO_STDIO #define APPS_WIN16 #endif -#include "lhash.h" -#include "bn.h" + +/* With IPv6, it looks like Digital has mixed up the proper order of + recursive header file inclusion, resulting in the compiler complaining + that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which + is needed to have fileno() declared correctly... So let's define u_int */ +#if defined(VMS) && defined(__DECC) && !defined(__U_INT) +#define __U_INT +typedef unsigned int u_int; +#endif + +#include +#include #define USE_SOCKETS #include "apps.h" -#include "err.h" -#include "pem.h" -#include "x509.h" -#include "ssl.h" +#include +#include +#include +#include #include "s_apps.h" -#ifndef NOPROTO -static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export,int keylength); -static int sv_body(char *hostname, int s, char *context); -static int www_body(char *hostname, int s, char *context); +#ifdef WINDOWS +#include +#endif + +#if (defined(VMS) && __VMS_VER < 70000000) +/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ +#undef FIONBIO +#endif + +#ifndef NO_RSA +static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); +#endif +static int sv_body(char *hostname, int s, unsigned char *context); +static int www_body(char *hostname, int s, unsigned char *context); static void close_accept_socket(void ); static void sv_usage(void); static int init_ssl_connection(SSL *s); static void print_stats(BIO *bp,SSL_CTX *ctx); #ifndef NO_DH -static DH *load_dh_param(void ); +static DH *load_dh_param(char *dhfile); static DH *get_dh512(void); #endif -/* static void s_server_init(void);*/ -#else -static RSA MS_CALLBACK *tmp_rsa_cb(); -static int sv_body(); -static int www_body(); -static void close_accept_socket(); -static void sv_usage(); -static int init_ssl_connection(); -static void print_stats(); -#ifndef NO_DH -static DH *load_dh_param(); -static DH *get_dh512(); -#endif -/* static void s_server_init(); */ +#ifdef MONOLITH +static void s_server_init(void); #endif - #ifndef S_ISDIR -#define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) +# if defined(_S_IFMT) && defined(_S_IFDIR) +# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) +# else +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +# endif #endif #ifndef NO_DH @@ -120,7 +132,7 @@ static unsigned char dh512_g[]={ 0x02, }; -static DH *get_dh512() +static DH *get_dh512(void) { DH *dh=NULL; @@ -137,25 +149,25 @@ static DH *get_dh512() #undef BUFSIZZ #define BUFSIZZ 16*1024 -static int bufsize=32; +static int bufsize=BUFSIZZ; static int accept_socket= -1; #define TEST_CERT "server.pem" #undef PROG #define PROG s_server_main -#define DH_PARAM "server.pem" - extern int verify_depth; static char *cipher=NULL; static int s_server_verify=SSL_VERIFY_NONE; +static int s_server_session_id_context = 1; /* anything will do */ static char *s_cert_file=TEST_CERT,*s_key_file=NULL; static char *s_dcert_file=NULL,*s_dkey_file=NULL; #ifdef FIONBIO static int s_nbio=0; #endif static int s_nbio_test=0; +int s_crlf=0; static SSL_CTX *ctx=NULL; static int www=0; @@ -163,9 +175,12 @@ static BIO *bio_s_out=NULL; static int s_debug=0; static int s_quiet=0; -#if 0 -static void s_server_init() +static int hack=0; + +#ifdef MONOLITH +static void s_server_init(void) { + accept_socket=-1; cipher=NULL; s_server_verify=SSL_VERIFY_NONE; s_dcert_file=NULL; @@ -182,10 +197,11 @@ static void s_server_init() bio_s_out=NULL; s_debug=0; s_quiet=0; + hack=0; } #endif -static void sv_usage() +static void sv_usage(void) { BIO_printf(bio_err,"usage: s_server [args ...]\n"); BIO_printf(bio_err,"\n"); @@ -195,14 +211,17 @@ static void sv_usage() BIO_printf(bio_err," -Verify arg - turn on peer certificate verification, must have a cert.\n"); BIO_printf(bio_err," -cert arg - certificate file to use, PEM format assumed\n"); BIO_printf(bio_err," (default is %s)\n",TEST_CERT); - BIO_printf(bio_err," -key arg - RSA file to use, PEM format assumed, in cert file if\n"); + BIO_printf(bio_err," -key arg - Private Key file to use, PEM format assumed, in cert file if\n"); BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT); BIO_printf(bio_err," -dcert arg - second certificate file to use (usually for DSA)\n"); BIO_printf(bio_err," -dkey arg - second private key file to use (usually for DSA)\n"); + BIO_printf(bio_err," -dhparam arg - DH parameter file to use, in cert file if not specified\n"); + BIO_printf(bio_err," or a default set of parameters is used\n"); #ifdef FIONBIO BIO_printf(bio_err," -nbio - Run with non-blocking IO\n"); #endif BIO_printf(bio_err," -nbio_test - test with the non-blocking test bio\n"); + BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); BIO_printf(bio_err," -debug - Print more output\n"); BIO_printf(bio_err," -state - Print the SSL states\n"); BIO_printf(bio_err," -CApath arg - PEM format directory of CA's\n"); @@ -217,26 +236,179 @@ static void sv_usage() BIO_printf(bio_err," -no_ssl2 - Just disable SSLv2\n"); BIO_printf(bio_err," -no_ssl3 - Just disable SSLv3\n"); BIO_printf(bio_err," -no_tls1 - Just disable TLSv1\n"); - BIO_printf(bio_err," -bugs - Turn on SSL bug compatability\n"); +#ifndef NO_DH + BIO_printf(bio_err," -no_dhe - Disable ephemeral DH\n"); +#endif + BIO_printf(bio_err," -bugs - Turn on SSL bug compatibility\n"); BIO_printf(bio_err," -www - Respond to a 'GET /' with a status page\n"); BIO_printf(bio_err," -WWW - Respond to a 'GET / HTTP/1.0' with file ./\n"); } static int local_argc=0; static char **local_argv; -static int hack=0; -int MAIN(argc, argv) -int argc; -char *argv[]; +#ifdef CHARSET_EBCDIC +static int ebcdic_new(BIO *bi); +static int ebcdic_free(BIO *a); +static int ebcdic_read(BIO *b, char *out, int outl); +static int ebcdic_write(BIO *b, char *in, int inl); +static long ebcdic_ctrl(BIO *b, int cmd, long num, char *ptr); +static int ebcdic_gets(BIO *bp, char *buf, int size); +static int ebcdic_puts(BIO *bp, char *str); + +#define BIO_TYPE_EBCDIC_FILTER (18|0x0200) +static BIO_METHOD methods_ebcdic= + { + BIO_TYPE_EBCDIC_FILTER, + "EBCDIC/ASCII filter", + ebcdic_write, + ebcdic_read, + ebcdic_puts, + ebcdic_gets, + ebcdic_ctrl, + ebcdic_new, + ebcdic_free, + }; + +typedef struct +{ + size_t alloced; + char buff[1]; +} EBCDIC_OUTBUFF; + +BIO_METHOD *BIO_f_ebcdic_filter() +{ + return(&methods_ebcdic); +} + +static int ebcdic_new(BIO *bi) +{ + EBCDIC_OUTBUFF *wbuf; + + wbuf = (EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + 1024); + wbuf->alloced = 1024; + wbuf->buff[0] = '\0'; + + bi->ptr=(char *)wbuf; + bi->init=1; + bi->flags=0; + return(1); +} + +static int ebcdic_free(BIO *a) +{ + if (a == NULL) return(0); + if (a->ptr != NULL) + Free(a->ptr); + a->ptr=NULL; + a->init=0; + a->flags=0; + return(1); +} + +static int ebcdic_read(BIO *b, char *out, int outl) +{ + int ret=0; + + if (out == NULL || outl == 0) return(0); + if (b->next_bio == NULL) return(0); + + ret=BIO_read(b->next_bio,out,outl); + if (ret > 0) + ascii2ebcdic(out,out,ret); + return(ret); +} + +static int ebcdic_write(BIO *b, char *in, int inl) +{ + EBCDIC_OUTBUFF *wbuf; + int ret=0; + int num; + unsigned char n; + + if ((in == NULL) || (inl <= 0)) return(0); + if (b->next_bio == NULL) return(0); + + wbuf=(EBCDIC_OUTBUFF *)b->ptr; + + if (inl > (num = wbuf->alloced)) + { + num = num + num; /* double the size */ + if (num < inl) + num = inl; + Free(wbuf); + wbuf=(EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + num); + + wbuf->alloced = num; + wbuf->buff[0] = '\0'; + + b->ptr=(char *)wbuf; + } + + ebcdic2ascii(wbuf->buff, in, inl); + + ret=BIO_write(b->next_bio, wbuf->buff, inl); + + return(ret); +} + +static long ebcdic_ctrl(BIO *b, int cmd, long num, char *ptr) +{ + long ret; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + case BIO_CTRL_DUP: + ret=0L; + break; + default: + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + break; + } + return(ret); +} + +static int ebcdic_gets(BIO *bp, char *buf, int size) +{ + int i, ret; + if (bp->next_bio == NULL) return(0); +/* return(BIO_gets(bp->next_bio,buf,size));*/ + for (i=0; inext_bio == NULL) return(0); + return ebcdic_write(bp, str, strlen(str)); +} +#endif + +int MAIN(int, char **); + +int MAIN(int argc, char *argv[]) { short port=PORT; char *CApath=NULL,*CAfile=NULL; char *context = NULL; + char *dhfile = NULL; int badop=0,bugs=0; int ret=1; int off=0; - int no_tmp_rsa=0,nocert=0; + int no_tmp_rsa=0,no_dhe=0,nocert=0; int state=0; SSL_METHOD *meth=NULL; #ifndef NO_DH @@ -255,8 +427,9 @@ char *argv[]; local_argv=argv; apps_startup(); - s_quiet=0; - s_debug=0; +#ifdef MONOLITH + s_server_init(); +#endif if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); @@ -309,6 +482,11 @@ char *argv[]; if (--argc < 1) goto bad; s_key_file= *(++argv); } + else if (strcmp(*argv,"-dhparam") == 0) + { + if (--argc < 1) goto bad; + dhfile = *(++argv); + } else if (strcmp(*argv,"-dcert") == 0) { if (--argc < 1) goto bad; @@ -355,12 +533,16 @@ char *argv[]; { hack=1; } else if (strcmp(*argv,"-state") == 0) { state=1; } + else if (strcmp(*argv,"-crlf") == 0) + { s_crlf=1; } else if (strcmp(*argv,"-quiet") == 0) { s_quiet=1; } else if (strcmp(*argv,"-bugs") == 0) { bugs=1; } else if (strcmp(*argv,"-no_tmp_rsa") == 0) { no_tmp_rsa=1; } + else if (strcmp(*argv,"-no_dhe") == 0) + { no_dhe=1; } else if (strcmp(*argv,"-www") == 0) { www=1; } else if (strcmp(*argv,"-WWW") == 0) @@ -399,6 +581,8 @@ bad: goto end; } + app_RAND_load_file(NULL, bio_err, 0); + if (bio_s_out == NULL) { if (s_quiet && !s_debug) @@ -423,7 +607,7 @@ bad: } SSL_load_error_strings(); - SSLeay_add_ssl_algorithms(); + OpenSSL_add_ssl_algorithms(); ctx=SSL_CTX_new(meth); if (ctx == NULL) @@ -463,21 +647,23 @@ bad: } #ifndef NO_DH - /* EAY EAY EAY evil hack */ - dh=load_dh_param(); - if (dh != NULL) - { - BIO_printf(bio_s_out,"Setting temp DH parameters\n"); - } - else + if (!no_dhe) { - BIO_printf(bio_s_out,"Using default temp DH parameters\n"); - dh=get_dh512(); - } - BIO_flush(bio_s_out); + dh=load_dh_param(dhfile ? dhfile : s_cert_file); + if (dh != NULL) + { + BIO_printf(bio_s_out,"Setting temp DH parameters\n"); + } + else + { + BIO_printf(bio_s_out,"Using default temp DH parameters\n"); + dh=get_dh512(); + } + (void)BIO_flush(bio_s_out); - SSL_CTX_set_tmp_dh(ctx,dh); - DH_free(dh); + SSL_CTX_set_tmp_dh(ctx,dh); + DH_free(dh); + } #endif if (!set_cert_stuff(ctx,s_cert_file,s_key_file)) @@ -488,6 +674,7 @@ bad: goto end; } +#ifndef NO_RSA #if 1 SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb); #else @@ -508,13 +695,21 @@ bad: RSA_free(rsa); BIO_printf(bio_s_out,"\n"); } +#endif #endif if (cipher != NULL) - SSL_CTX_set_cipher_list(ctx,cipher); + if(!SSL_CTX_set_cipher_list(ctx,cipher)) { + BIO_printf(bio_err,"error setting cipher list\n"); + ERR_print_errors(bio_err); + goto end; + } SSL_CTX_set_verify(ctx,s_server_verify,verify_callback); + SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context, + sizeof s_server_session_id_context); - SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); + if (CAfile != NULL) + SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); BIO_printf(bio_s_out,"ACCEPT\n"); if (www) @@ -533,9 +728,7 @@ end: EXIT(ret); } -static void print_stats(bio,ssl_ctx) -BIO *bio; -SSL_CTX *ssl_ctx; +static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) { BIO_printf(bio,"%4ld items in the session cache\n", SSL_CTX_sess_number(ssl_ctx)); @@ -560,10 +753,7 @@ SSL_CTX *ssl_ctx; SSL_CTX_sess_get_cache_size(ssl_ctx)); } -static int sv_body(hostname, s, context) -char *hostname; -int s; -char *context; +static int sv_body(char *hostname, int s, unsigned char *context) { char *buf=NULL; fd_set readfds; @@ -572,6 +762,9 @@ char *context; unsigned long l; SSL *con=NULL; BIO *sbio; +#ifdef WINDOWS + struct timeval tv; +#endif if ((buf=Malloc(bufsize)) == NULL) { @@ -591,9 +784,10 @@ char *context; #endif if (con == NULL) { - con=(SSL *)SSL_new(ctx); + con=SSL_new(ctx); if(context) - SSL_set_session_id_context(con, context, strlen(context)); + SSL_set_session_id_context(con, context, + strlen((char *)context)); } SSL_clear(con); @@ -624,11 +818,53 @@ char *context; FD_SET(fileno(stdin),&readfds); #endif FD_SET(s,&readfds); - i=select(width,&readfds,NULL,NULL,NULL); - if (i <= 0) continue; - if (FD_ISSET(fileno(stdin),&readfds)) + /* Note: under VMS with SOCKETSHR the second parameter is + * currently of type (int *) whereas under other systems + * it is (void *) if you don't have a cast it will choke + * the compiler: if you do have a cast then you can either + * go for (int *) or (void *). + */ +#ifdef WINDOWS + /* Under Windows we can't select on stdin: only + * on sockets. As a workaround we timeout the select every + * second and check for any keypress. In a proper Windows + * application we wouldn't do this because it is inefficient. + */ + tv.tv_sec = 1; + tv.tv_usec = 0; + i=select(width,(void *)&readfds,NULL,NULL,&tv); + if((i < 0) || (!i && !_kbhit() ) )continue; + if(_kbhit()) +#else + i=select(width,(void *)&readfds,NULL,NULL,NULL); + if (i <= 0) continue; + if (FD_ISSET(fileno(stdin),&readfds)) +#endif { - i=read(fileno(stdin),buf,bufsize); + if (s_crlf) + { + int j, lf_num; + + i=read(fileno(stdin), buf, bufsize/2); + lf_num = 0; + /* both loops are skipped when i <= 0 */ + for (j = 0; j < i; j++) + if (buf[j] == '\n') + lf_num++; + for (j = i-1; j >= 0; j--) + { + buf[j+lf_num] = buf[j]; + if (buf[j] == '\n') + { + lf_num--; + i++; + buf[j+lf_num] = '\r'; + } + } + assert(lf_num == 0); + } + else + i=read(fileno(stdin),buf,bufsize); if (!s_quiet) { if ((i <= 0) || (buf[0] == 'Q')) @@ -679,6 +915,9 @@ char *context; print_stats(bio_s_out,SSL_get_SSL_CTX(con)); } } +#ifdef CHARSET_EBCDIC + ebcdic2ascii(buf,buf,i); +#endif l=k=0; for (;;) { @@ -737,6 +976,9 @@ again: switch (SSL_get_error(con,i)) { case SSL_ERROR_NONE: +#ifdef CHARSET_EBCDIC + ascii2ebcdic(buf,buf,i); +#endif write(fileno(stdout),buf, (unsigned int)i); if (SSL_pending(con)) goto again; @@ -779,7 +1021,7 @@ err: return(ret); } -static void close_accept_socket() +static void close_accept_socket(void) { BIO_printf(bio_err,"shutdown accept socket\n"); if (accept_socket >= 0) @@ -788,11 +1030,10 @@ static void close_accept_socket() } } -static int init_ssl_connection(con) -SSL *con; +static int init_ssl_connection(SSL *con) { int i; - char *str; + const char *str; X509 *peer; long verify_error; MS_STATIC char buf[BUFSIZ]; @@ -844,14 +1085,14 @@ SSL *con; } #ifndef NO_DH -static DH *load_dh_param() +static DH *load_dh_param(char *dhfile) { DH *ret=NULL; BIO *bio; - if ((bio=BIO_new_file(DH_PARAM,"r")) == NULL) + if ((bio=BIO_new_file(dhfile,"r")) == NULL) goto err; - ret=PEM_read_bio_DHparams(bio,NULL,NULL); + ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL); err: if (bio != NULL) BIO_free(bio); return(ret); @@ -859,9 +1100,7 @@ err: #endif #if 0 -static int load_CA(ctx,file) -SSL_CTX *ctx; -char *file; +static int load_CA(SSL_CTX *ctx, char *file) { FILE *in; X509 *x=NULL; @@ -881,10 +1120,7 @@ char *file; } #endif -static int www_body(hostname, s, context) -char *hostname; -int s; -char *context; +static int www_body(char *hostname, int s, unsigned char *context) { char *buf=NULL; int ret=1; @@ -916,8 +1152,9 @@ char *context; /* lets make the output buffer a reasonable size */ if (!BIO_set_write_buffer_size(io,bufsize)) goto err; - if ((con=(SSL *)SSL_new(ctx)) == NULL) goto err; - if(context) SSL_set_session_id_context(con, context, strlen(context)); + if ((con=SSL_new(ctx)) == NULL) goto err; + if(context) SSL_set_session_id_context(con, context, + strlen((char *)context)); sbio=BIO_new_socket(s,BIO_NOCLOSE); if (s_nbio_test) @@ -933,6 +1170,9 @@ char *context; /* SSL_set_fd(con,s); */ BIO_set_ssl(ssl_bio,con,BIO_CLOSE); BIO_push(io,ssl_bio); +#ifdef CHARSET_EBCDIC + io = BIO_push(BIO_new(BIO_f_ebcdic_filter()),io); +#endif if (s_debug) { @@ -1002,7 +1242,7 @@ char *context; static char *space=" "; BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); - BIO_puts(io,"\n"); + BIO_puts(io,"\n"); BIO_puts(io,"
\n");
 /*			BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
 			BIO_puts(io,"\n");
@@ -1074,7 +1314,7 @@ char *context;
 			BIO_puts(io,"\r\n\r\n");
 			break;
 			}
-		else if ((www == 2) && (strncmp("GET ",buf,4) == 0))
+		else if ((www == 2) && (strncmp("GET /",buf,5) == 0))
 			{
 			BIO *file;
 			char *p,*e;
@@ -1210,7 +1450,7 @@ end:
 	/* make sure we re-use sessions */
 	SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
 #else
-	/* This kills performace */
+	/* This kills performance */
 /*	SSL_shutdown(con); A shutdown gets sent in the
  *	BIO_free_all(io) procession */
 #endif
@@ -1226,10 +1466,8 @@ err:
 	return(ret);
 	}
 
-static RSA MS_CALLBACK *tmp_rsa_cb(s,export,keylength)
-SSL *s;
-int export;
-int keylength;
+#ifndef NO_RSA
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
 	{
 	static RSA *rsa_tmp=NULL;
 
@@ -1238,16 +1476,15 @@ int keylength;
 		if (!s_quiet)
 			{
 			BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
-			BIO_flush(bio_err);
+			(void)BIO_flush(bio_err);
 			}
-#ifndef NO_RSA
 		rsa_tmp=RSA_generate_key(keylength,RSA_F4,NULL,NULL);
-#endif
 		if (!s_quiet)
 			{
 			BIO_printf(bio_err,"\n");
-			BIO_flush(bio_err);
+			(void)BIO_flush(bio_err);
 			}
 		}
 	return(rsa_tmp);
 	}
+#endif