This adds command-line support to s_server for controlling the generation
[openssl.git] / apps / s_server.c
index c83337b828f5ffe6be58c943af6e862e40c7c1c4..561e3a2358fbbc951c7a6fa55e9e6b4db93da1d4 100644 (file)
@@ -62,6 +62,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <openssl/e_os2.h>
 #ifdef OPENSSL_NO_STDIO
 #define APPS_WIN16
 #endif
 #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 */
    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
 #define __U_INT
 typedef unsigned int u_int;
 #endif
@@ -86,11 +87,11 @@ typedef unsigned int u_int;
 #include <openssl/engine.h>
 #include "s_apps.h"
 
 #include <openssl/engine.h>
 #include "s_apps.h"
 
-#ifdef WINDOWS
+#ifdef OPENSSL_SYS_WINDOWS
 #include <conio.h>
 #endif
 
 #include <conio.h>
 #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
 /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
 #undef FIONBIO
 #endif
@@ -104,6 +105,8 @@ 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);
 static void sv_usage(void);
 static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp,SSL_CTX *ctx);
+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);
 #ifndef OPENSSL_NO_DH
 static DH *load_dh_param(char *dhfile);
 static DH *get_dh512(void);
@@ -178,6 +181,7 @@ static int s_quiet=0;
 
 static int hack=0;
 static char *engine_id=NULL;
 
 static int hack=0;
 static char *engine_id=NULL;
+static const char *session_id_prefix=NULL;
 
 #ifdef MONOLITH
 static void s_server_init(void)
 
 #ifdef MONOLITH
 static void s_server_init(void)
@@ -247,6 +251,7 @@ static void sv_usage(void)
        BIO_printf(bio_err," -www          - Respond to a 'GET /' with a status page\n");
        BIO_printf(bio_err," -WWW          - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\n");
        BIO_printf(bio_err," -engine id    - Initialise and use the specified engine\n");
        BIO_printf(bio_err," -www          - Respond to a 'GET /' with a status page\n");
        BIO_printf(bio_err," -WWW          - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\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);
        }
 
        BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
        }
 
@@ -572,6 +577,11 @@ int MAIN(int argc, char *argv[])
                else if (strcmp(*argv,"-tls1") == 0)
                        { meth=TLSv1_server_method(); }
 #endif
                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;
                else if (strcmp(*argv,"-engine") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -662,7 +672,22 @@ bad:
                ERR_print_errors(bio_err);
                goto end;
                }
                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);
        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);
@@ -729,7 +754,8 @@ bad:
 
 #ifndef OPENSSL_NO_RSA
 #if 1
 
 #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))
                {
 #else
        if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx))
                {
@@ -815,7 +841,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
        unsigned long l;
        SSL *con=NULL;
        BIO *sbio;
        unsigned long l;
        SSL *con=NULL;
        BIO *sbio;
-#ifdef WINDOWS
+#ifdef OPENSSL_SYS_WINDOWS
        struct timeval tv;
 #endif
 
        struct timeval tv;
 #endif
 
@@ -882,7 +908,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                if (!read_from_sslcon)
                        {
                        FD_ZERO(&readfds);
                if (!read_from_sslcon)
                        {
                        FD_ZERO(&readfds);
-#ifndef WINDOWS
+#ifndef OPENSSL_SYS_WINDOWS
                        FD_SET(fileno(stdin),&readfds);
 #endif
                        FD_SET(s,&readfds);
                        FD_SET(fileno(stdin),&readfds);
 #endif
                        FD_SET(s,&readfds);
@@ -892,7 +918,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                         * the compiler: if you do have a cast then you can either
                         * go for (int *) or (void *).
                         */
                         * the compiler: if you do have a cast then you can either
                         * go for (int *) or (void *).
                         */
-#ifdef WINDOWS
+#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
                        /* 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
@@ -1294,7 +1320,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                        else
                                {
                                BIO_printf(bio_s_out,"read R BLOCK\n");
                        else
                                {
                                BIO_printf(bio_s_out,"read R BLOCK\n");
-#ifndef MSDOS
+#ifndef OPENSSL_SYS_MSDOS
                                sleep(1);
 #endif
                                continue;
                                sleep(1);
 #endif
                                continue;
@@ -1562,3 +1588,26 @@ static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
        return(rsa_tmp);
        }
 #endif
        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;
+       }