Oops! Get the pmatch test the right way round.
[openssl.git] / apps / s_server.c
index c9651b84af6ed5cef3ffd370ec123e39cbb94abb..23419495171c2381ace2891c03524d4251315604 100644 (file)
  * [including the GNU Public Licence.]
  */
 
+/* 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(__DECC) && !defined(__U_INT)
+#define __U_INT
+typedef unsigned int u_int;
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #ifdef NO_STDIO
 #define APPS_WIN16
 #endif
-#include "lhash.h"
-#include "bn.h"
+#include <openssl/lhash.h>
+#include <openssl/bn.h>
 #define USE_SOCKETS
 #include "apps.h"
-#include "err.h"
-#include "pem.h"
-#include "x509.h"
-#include "ssl.h"
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
 #include "s_apps.h"
 
-#ifndef NOPROTO
-static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export);
-static int sv_body(char *hostname, int s);
-static int www_body(char *hostname, int s);
+#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
+
+#if defined(NO_RSA) && !defined(NO_SSL2)
+#define NO_SSL2
+#endif
+
+#ifndef NO_RSA
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int 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);
@@ -87,25 +106,14 @@ static DH *load_dh_param(void );
 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(); */
-#endif
-
 
 #ifndef S_ISDIR
+#if defined(VMS) && !defined(__DECC)
+#define S_ISDIR(a)     (((a) & S_IFMT) == S_IFDIR)
+#else
 #define S_ISDIR(a)     (((a) & _S_IFMT) == _S_IFDIR)
 #endif
+#endif
 
 #ifndef NO_DH
 static unsigned char dh512_p[]={
@@ -120,7 +128,7 @@ static unsigned char dh512_g[]={
        0x02,
        };
 
-static DH *get_dh512()
+static DH *get_dh512(void)
        {
        DH *dh=NULL;
 
@@ -150,6 +158,7 @@ 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
@@ -164,7 +173,7 @@ static int s_debug=0;
 static int s_quiet=0;
 
 #if 0
-static void s_server_init()
+static void s_server_init(void)
        {
        cipher=NULL;
        s_server_verify=SSL_VERIFY_NONE;
@@ -185,17 +194,20 @@ static void s_server_init()
        }
 #endif
 
-static void sv_usage()
+static void sv_usage(void)
        {
        BIO_printf(bio_err,"usage: s_server [args ...]\n");
        BIO_printf(bio_err,"\n");
-       BIO_printf(bio_err," -accept arg   - port to accept on (default is %d\n",PORT);
+       BIO_printf(bio_err," -accept arg   - port to accept on (default is %d)\n",PORT);
+       BIO_printf(bio_err," -context arg  - set session ID context\n");
        BIO_printf(bio_err," -verify arg   - turn on peer certificate verification\n");
        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,"                 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");
 #ifdef FIONBIO
        BIO_printf(bio_err," -nbio         - Run with non-blocking IO\n");
 #endif
@@ -205,7 +217,7 @@ static void sv_usage()
        BIO_printf(bio_err," -CApath arg   - PEM format directory of CA's\n");
        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 'ssleay ciphers' to see what goes here\n");
+       BIO_printf(bio_err," -cipher arg   - play with 'openssl ciphers' to see what goes here\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");
@@ -216,19 +228,18 @@ static void sv_usage()
        BIO_printf(bio_err," -no_tls1      - Just disable TLSv1\n");
        BIO_printf(bio_err," -bugs         - Turn on SSL bug compatability\n");
        BIO_printf(bio_err," -www          - Respond to a 'GET /' with a status page\n");
-       BIO_printf(bio_err," -WWW          - Returns requested page from to a 'GET <path> HTTP/1.0'\n");
+       BIO_printf(bio_err," -WWW          - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\n");
        }
 
 static int local_argc=0;
 static char **local_argv;
 static int hack=0;
 
-int MAIN(argc, argv)
-int argc;
-char *argv[];
+int MAIN(int argc, char *argv[])
        {
        short port=PORT;
        char *CApath=NULL,*CAfile=NULL;
+       char *context = NULL;
        int badop=0,bugs=0;
        int ret=1;
        int off=0;
@@ -290,6 +301,11 @@ char *argv[];
                        verify_depth=atoi(*(++argv));
                        BIO_printf(bio_err,"verify depth is %d, must return a certificate\n",verify_depth);
                        }
+               else if (strcmp(*argv,"-context") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       context= *(++argv);
+                       }
                else if (strcmp(*argv,"-cert") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -479,6 +495,7 @@ bad:
                        goto end;
                }
 
+#ifndef NO_RSA
 #if 1
        SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
 #else
@@ -499,19 +516,22 @@ bad:
                RSA_free(rsa);
                BIO_printf(bio_s_out,"\n");
                }
+#endif
 #endif
 
        if (cipher != NULL)
                SSL_CTX_set_cipher_list(ctx,cipher);
        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(s_cert_file));
+       SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
 
        BIO_printf(bio_s_out,"ACCEPT\n");
        if (www)
-               do_server(port,&accept_socket,www_body);
+               do_server(port,&accept_socket,www_body, context);
        else
-               do_server(port,&accept_socket,sv_body);
+               do_server(port,&accept_socket,sv_body, context);
        print_stats(bio_s_out,ctx);
        ret=0;
 end:
@@ -524,9 +544,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));
@@ -551,9 +569,7 @@ SSL_CTX *ssl_ctx;
                SSL_CTX_sess_get_cache_size(ssl_ctx));
        }
 
-static int sv_body(hostname, s)
-char *hostname;
-int s;
+static int sv_body(char *hostname, int s, unsigned char *context)
        {
        char *buf=NULL;
        fd_set readfds;
@@ -580,8 +596,12 @@ int s;
                }
 #endif
 
-       if (con == NULL)
+       if (con == NULL) {
                con=(SSL *)SSL_new(ctx);
+               if(context)
+                     SSL_set_session_id_context(con, context,
+                                                strlen((char *)context));
+       }
        SSL_clear(con);
 
        sbio=BIO_new_socket(s,BIO_NOCLOSE);
@@ -611,7 +631,13 @@ int s;
                FD_SET(fileno(stdin),&readfds);
 #endif
                FD_SET(s,&readfds);
-               i=select(width,&readfds,NULL,NULL,NULL);
+               /* 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 *).
+                */
+               i=select(width,(void *)&readfds,NULL,NULL,NULL);
                if (i <= 0) continue;
                if (FD_ISSET(fileno(stdin),&readfds))
                        {
@@ -645,7 +671,7 @@ int s;
                                        /* strcpy(buf,"server side RE-NEGOTIATE\n"); */
                                        }
                                if ((buf[0] == 'R') &&
-                                       ((buf[1] == '\0') || (buf[1] == '\r')))
+                                       ((buf[1] == '\n') || (buf[1] == '\r')))
                                        {
                                        SSL_set_verify(con,
                                                SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,NULL);
@@ -766,7 +792,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)
@@ -775,11 +801,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];
@@ -831,7 +856,7 @@ SSL *con;
        }
 
 #ifndef NO_DH
-static DH *load_dh_param()
+static DH *load_dh_param(void)
        {
        DH *ret=NULL;
        BIO *bio;
@@ -846,9 +871,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;
@@ -868,9 +891,7 @@ char *file;
        }
 #endif
 
-static int www_body(hostname, s)
-char *hostname;
-int s;
+static int www_body(char *hostname, int s, unsigned char *context)
        {
        char *buf=NULL;
        int ret=1;
@@ -903,6 +924,8 @@ int s;
        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((char *)context));
 
        sbio=BIO_new_socket(s,BIO_NOCLOSE);
        if (s_nbio_test)
@@ -983,7 +1006,7 @@ int s;
                        {
                        char *p;
                        X509 *peer;
-                       STACK *sk;
+                       STACK_OF(SSL_CIPHER) *sk;
                        static char *space="                          ";
 
                        BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
@@ -1002,10 +1025,10 @@ int s;
                         * be done */
                        BIO_printf(io,"Ciphers supported in s_server binary\n");
                        sk=SSL_get_ciphers(con);
-                       j=sk_num(sk);
+                       j=sk_SSL_CIPHER_num(sk);
                        for (i=0; i<j; i++)
                                {
-                               c=(SSL_CIPHER *)sk_value(sk,i);
+                               c=sk_SSL_CIPHER_value(sk,i);
                                BIO_printf(io,"%-11s:%-25s",
                                        SSL_CIPHER_get_version(c),
                                        SSL_CIPHER_get_name(c));
@@ -1211,9 +1234,8 @@ err:
        return(ret);
        }
 
-static RSA MS_CALLBACK *tmp_rsa_cb(s,export)
-SSL *s;
-int export;
+#ifndef NO_RSA
+static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export, int keylength)
        {
        static RSA *rsa_tmp=NULL;
 
@@ -1221,12 +1243,10 @@ int export;
                {
                if (!s_quiet)
                        {
-                       BIO_printf(bio_err,"Generating temp (512 bit) RSA key...");
+                       BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
                        BIO_flush(bio_err);
                        }
-#ifndef NO_RSA
-               rsa_tmp=RSA_generate_key(512,RSA_F4,NULL,NULL);
-#endif
+               rsa_tmp=RSA_generate_key(keylength,RSA_F4,NULL,NULL);
                if (!s_quiet)
                        {
                        BIO_printf(bio_err,"\n");
@@ -1235,3 +1255,4 @@ int export;
                }
        return(rsa_tmp);
        }
+#endif