X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_server.c;h=561e3a2358fbbc951c7a6fa55e9e6b4db93da1d4;hp=a33e0ff1477046506bca972a357bd2d948c5e469;hb=1aa0d9478159b8be4249fc96f575afe8b84e2fa9;hpb=a31011e8e0ea18f1cc79d7eb53238768ae9369c6 diff --git a/apps/s_server.c b/apps/s_server.c index a33e0ff147..561e3a2358 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -62,7 +62,8 @@ #include #include #include -#ifdef NO_STDIO +#include +#ifdef OPENSSL_NO_STDIO #define APPS_WIN16 #endif @@ -70,7 +71,7 @@ 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) +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) #define __U_INT typedef unsigned int u_int; #endif @@ -83,22 +84,19 @@ typedef unsigned int u_int; #include #include #include +#include #include "s_apps.h" -#ifdef WINDOWS +#ifdef OPENSSL_SYS_WINDOWS #include #endif -#if (defined(VMS) && __VMS_VER < 70000000) +#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ #undef FIONBIO #endif -#if defined(NO_RSA) && !defined(NO_SSL2) -#define NO_SSL2 -#endif - -#ifndef NO_RSA +#ifndef OPENSSL_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); @@ -107,7 +105,9 @@ 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 int generate_session_id(const SSL *ssl, unsigned char *id, + unsigned int *id_len); +#ifndef OPENSSL_NO_DH static DH *load_dh_param(char *dhfile); static DH *get_dh512(void); #endif @@ -123,7 +123,7 @@ static void s_server_init(void); # endif #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH static unsigned char dh512_p[]={ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, @@ -180,6 +180,8 @@ static int s_debug=0; static int s_quiet=0; static int hack=0; +static char *engine_id=NULL; +static const char *session_id_prefix=NULL; #ifdef MONOLITH static void s_server_init(void) @@ -202,6 +204,7 @@ static void s_server_init(void) s_debug=0; s_quiet=0; hack=0; + engine_id=NULL; } #endif @@ -232,6 +235,7 @@ static void sv_usage(void) BIO_printf(bio_err," -CAfile arg - PEM format file of CA's\n"); BIO_printf(bio_err," -nocert - Don't use any certificates (Anon-DH)\n"); BIO_printf(bio_err," -cipher arg - play with 'openssl ciphers' to see what goes here\n"); + BIO_printf(bio_err," -serverpref - Use server's cipher preferences\n"); BIO_printf(bio_err," -quiet - No server output\n"); BIO_printf(bio_err," -no_tmp_rsa - Do not generate a tmp RSA key\n"); BIO_printf(bio_err," -ssl2 - Just talk SSLv2\n"); @@ -240,12 +244,15 @@ static void sv_usage(void) 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"); -#ifndef NO_DH +#ifndef OPENSSL_NO_DH BIO_printf(bio_err," -no_dhe - Disable ephemeral DH\n"); #endif - BIO_printf(bio_err," -bugs - Turn on SSL bug compatability\n"); + 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"); + BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); + BIO_printf(bio_err," -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n"); + BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); } static int local_argc=0; @@ -289,7 +296,7 @@ static int ebcdic_new(BIO *bi) { EBCDIC_OUTBUFF *wbuf; - wbuf = (EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + 1024); + wbuf = (EBCDIC_OUTBUFF *)OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + 1024); wbuf->alloced = 1024; wbuf->buff[0] = '\0'; @@ -303,7 +310,7 @@ static int ebcdic_free(BIO *a) { if (a == NULL) return(0); if (a->ptr != NULL) - Free(a->ptr); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; @@ -340,8 +347,8 @@ static int ebcdic_write(BIO *b, char *in, int inl) num = num + num; /* double the size */ if (num < inl) num = inl; - Free((char*)wbuf); - wbuf=(EBCDIC_OUTBUFF *)Malloc(sizeof(EBCDIC_OUTBUFF) + num); + OPENSSL_free(wbuf); + wbuf=(EBCDIC_OUTBUFF *)OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + num); wbuf->alloced = num; wbuf->buff[0] = '\0'; @@ -401,6 +408,8 @@ static int ebcdic_puts(BIO *bp, char *str) } #endif +int MAIN(int, char **); + int MAIN(int argc, char *argv[]) { short port=PORT; @@ -413,15 +422,14 @@ int MAIN(int argc, char *argv[]) int no_tmp_rsa=0,no_dhe=0,nocert=0; int state=0; SSL_METHOD *meth=NULL; -#ifndef NO_DH - DH *dh=NULL; -#endif + ENGINE *e=NULL; + char *inrand=NULL; -#if !defined(NO_SSL2) && !defined(NO_SSL3) +#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_server_method(); -#elif !defined(NO_SSL3) +#elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_server_method(); -#elif !defined(NO_SSL2) +#elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_server_method(); #endif @@ -508,6 +516,8 @@ int MAIN(int argc, char *argv[]) if (--argc < 1) goto bad; CApath= *(++argv); } + else if (strcmp(*argv,"-serverpref") == 0) + { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; } else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; @@ -555,18 +565,33 @@ int MAIN(int argc, char *argv[]) { off|=SSL_OP_NO_SSLv3; } else if (strcmp(*argv,"-no_tls1") == 0) { off|=SSL_OP_NO_TLSv1; } -#ifndef NO_SSL2 +#ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) { meth=SSLv2_server_method(); } #endif -#ifndef NO_SSL3 +#ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) { meth=SSLv3_server_method(); } #endif -#ifndef NO_TLS1 +#ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) { meth=TLSv1_server_method(); } #endif + else if (strcmp(*argv, "-id_prefix") == 0) + { + if (--argc < 1) goto bad; + session_id_prefix = *(++argv); + } + else if (strcmp(*argv,"-engine") == 0) + { + if (--argc < 1) goto bad; + engine_id= *(++argv); + } + else if (strcmp(*argv,"-rand") == 0) + { + if (--argc < 1) goto bad; + inrand= *(++argv); + } else { BIO_printf(bio_err,"unknown option %s\n",*argv); @@ -583,7 +608,14 @@ bad: goto end; } - app_RAND_load_file(NULL, bio_err, 0); + if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL + && !RAND_status()) + { + BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); + } + if (inrand != NULL) + BIO_printf(bio_err,"%ld semi-random bytes loaded\n", + app_RAND_load_files(inrand)); if (bio_s_out == NULL) { @@ -598,7 +630,7 @@ bad: } } -#if !defined(NO_RSA) || !defined(NO_DSA) +#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) if (nocert) #endif { @@ -609,7 +641,30 @@ bad: } SSL_load_error_strings(); - SSLeay_add_ssl_algorithms(); + OpenSSL_add_ssl_algorithms(); + + if (engine_id != NULL) + { + if((e = ENGINE_by_id(engine_id)) == NULL) + { + BIO_printf(bio_err,"invalid engine\n"); + ERR_print_errors(bio_err); + goto end; + } + if (s_debug) + { + ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, + 0, bio_err, 0); + } + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) + { + BIO_printf(bio_err,"can't use that engine\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err,"engine \"%s\" set.\n", engine_id); + ENGINE_free(e); + } ctx=SSL_CTX_new(meth); if (ctx == NULL) @@ -617,7 +672,22 @@ bad: ERR_print_errors(bio_err); goto end; } - + if (session_id_prefix) + { + if(strlen(session_id_prefix) >= 32) + BIO_printf(bio_err, +"warning: id_prefix is too long, only one new session will be possible\n"); + else if(strlen(session_id_prefix) >= 16) + BIO_printf(bio_err, +"warning: id_prefix is too long if you use SSLv2\n"); + if(!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) + { + BIO_printf(bio_err,"error setting 'id_prefix'\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err,"id_prefix '%s' set.\n", session_id_prefix); + } SSL_CTX_set_quiet_shutdown(ctx,1); if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL); if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); @@ -648,10 +718,16 @@ bad: /* goto end; */ } -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (!no_dhe) { - dh=load_dh_param(dhfile ? dhfile : s_cert_file); + DH *dh=NULL; + + if (dhfile) + dh = load_dh_param(dhfile); + else if (s_cert_file) + dh = load_dh_param(s_cert_file); + if (dh != NULL) { BIO_printf(bio_s_out,"Setting temp DH parameters\n"); @@ -676,9 +752,10 @@ bad: goto end; } -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA #if 1 - SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb); + if (!no_tmp_rsa) + SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb); #else if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx)) { @@ -701,7 +778,11 @@ bad: #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); @@ -760,11 +841,11 @@ static int sv_body(char *hostname, int s, unsigned char *context) unsigned long l; SSL *con=NULL; BIO *sbio; -#ifdef WINDOWS +#ifdef OPENSSL_SYS_WINDOWS struct timeval tv; #endif - if ((buf=Malloc(bufsize)) == NULL) + if ((buf=OPENSSL_malloc(bufsize)) == NULL) { BIO_printf(bio_err,"out of memory\n"); goto err; @@ -782,7 +863,14 @@ static int sv_body(char *hostname, int s, unsigned char *context) #endif if (con == NULL) { - con=(SSL *)SSL_new(ctx); + con=SSL_new(ctx); +#ifndef OPENSSL_NO_KRB5 + if ((con->kssl_ctx = kssl_ctx_new()) != NULL) + { + kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, KRB5SVC); + kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB); + } +#endif /* OPENSSL_NO_KRB5 */ if(context) SSL_set_session_id_context(con, context, strlen((char *)context)); @@ -811,33 +899,47 @@ static int sv_body(char *hostname, int s, unsigned char *context) width=s+1; for (;;) { - FD_ZERO(&readfds); -#ifndef WINDOWS - FD_SET(fileno(stdin),&readfds); + int read_from_terminal; + int read_from_sslcon; + + read_from_terminal = 0; + read_from_sslcon = SSL_pending(con); + + if (!read_from_sslcon) + { + FD_ZERO(&readfds); +#ifndef OPENSSL_SYS_WINDOWS + FD_SET(fileno(stdin),&readfds); #endif - FD_SET(s,&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()) + FD_SET(s,&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 OPENSSL_SYS_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()) + read_from_terminal = 1; #else - i=select(width,(void *)&readfds,NULL,NULL,NULL); - if (i <= 0) continue; - if (FD_ISSET(fileno(stdin),&readfds)) + i=select(width,(void *)&readfds,NULL,NULL,NULL); + if (i <= 0) continue; + if (FD_ISSET(fileno(stdin),&readfds)) + read_from_terminal = 1; #endif + if (FD_ISSET(s,&readfds)) + read_from_sslcon = 1; + } + if (read_from_terminal) { if (s_crlf) { @@ -950,7 +1052,7 @@ static int sv_body(char *hostname, int s, unsigned char *context) if (i <= 0) break; } } - if (FD_ISSET(s,&readfds)) + if (read_from_sslcon) { if (!SSL_is_init_finished(con)) { @@ -1012,7 +1114,7 @@ err: if (buf != NULL) { memset(buf,0,bufsize); - Free(buf); + OPENSSL_free(buf); } if (ret >= 0) BIO_printf(bio_s_out,"ACCEPT\n"); @@ -1082,7 +1184,7 @@ static int init_ssl_connection(SSL *con) return(1); } -#ifndef NO_DH +#ifndef OPENSSL_NO_DH static DH *load_dh_param(char *dhfile) { DH *ret=NULL; @@ -1129,7 +1231,7 @@ static int www_body(char *hostname, int s, unsigned char *context) BIO *io,*ssl_bio,*sbio; long total_bytes; - buf=Malloc(bufsize); + buf=OPENSSL_malloc(bufsize); if (buf == NULL) return(0); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); @@ -1150,7 +1252,7 @@ static int www_body(char *hostname, int s, unsigned 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 ((con=SSL_new(ctx)) == NULL) goto err; if(context) SSL_set_session_id_context(con, context, strlen((char *)context)); @@ -1218,7 +1320,7 @@ static int www_body(char *hostname, int s, unsigned char *context) else { BIO_printf(bio_s_out,"read R BLOCK\n"); -#ifndef MSDOS +#ifndef OPENSSL_SYS_MSDOS sleep(1); #endif continue; @@ -1448,7 +1550,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 @@ -1458,13 +1560,13 @@ err: if (ret >= 0) BIO_printf(bio_s_out,"ACCEPT\n"); - if (buf != NULL) Free(buf); + if (buf != NULL) OPENSSL_free(buf); if (io != NULL) BIO_free_all(io); /* if (ssl_bio != NULL) BIO_free(ssl_bio);*/ return(ret); } -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) { static RSA *rsa_tmp=NULL; @@ -1486,3 +1588,26 @@ static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) return(rsa_tmp); } #endif + +#define MAX_SESSION_ID_ATTEMPTS 10 +static int generate_session_id(const SSL *ssl, unsigned char *id, + unsigned int *id_len) + { + unsigned int count = 0; + do { + RAND_pseudo_bytes(id, *id_len); + /* Prefix the session_id with the required prefix. NB: If our + * prefix is too long, clip it - but there will be worse effects + * anyway, eg. the server could only possibly create 1 session + * ID (ie. the prefix!) so all future session negotiations will + * fail due to conflicts. */ + memcpy(id, session_id_prefix, + (strlen(session_id_prefix) < *id_len) ? + strlen(session_id_prefix) : *id_len); + } + while(SSL_CTX_has_matching_session_id(ssl->ctx, id, *id_len) && + (++count < MAX_SESSION_ID_ATTEMPTS)); + if(count >= MAX_SESSION_ID_ATTEMPTS) + return 0; + return 1; + }