More general definition for S_ISDIR (needed not only for VMS but
[openssl.git] / apps / s_server.c
index 8edd8e79bfe9c6c2bb0cc23df9fba5b335a9a2b7..bcb9779d504c6522a0abaf054d2e9890454a8181 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(VMS) && 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
+#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);
-static int sv_body(char *hostname, int s, char *context);
-static int www_body(char *hostname, int s, char *context);
+#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,24 +106,13 @@ 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
-#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 +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,7 +194,7 @@ 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");
@@ -226,9 +235,157 @@ 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((char*)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; i<size-1; ++i)
+       {
+               ret = ebcdic_read(bp,&buf[i],1);
+               if (ret <= 0)
+                       break;
+               else if (buf[i] == '\n')
+               {
+                       ++i;
+                       break;
+               }
+       }
+       if (i < size)
+               buf[i] = '\0';
+       return (ret < 0 && i == 0) ? ret : i;
+}
+
+static int ebcdic_puts(BIO *bp, char *str)
+{
+       if (bp->next_bio == NULL) return(0);
+       return ebcdic_write(bp, str, strlen(str));
+}
+#endif
+
+int MAIN(int argc, char *argv[])
        {
        short port=PORT;
        char *CApath=NULL,*CAfile=NULL;
@@ -488,6 +645,7 @@ bad:
                        goto end;
                }
 
+#ifndef NO_RSA
 #if 1
        SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
 #else
@@ -508,11 +666,14 @@ 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(CAfile));
 
@@ -533,9 +694,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 +719,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;
@@ -593,7 +749,8 @@ char *context;
        if (con == NULL) {
                con=(SSL *)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,7 +781,13 @@ char *context;
                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))
                        {
@@ -679,6 +842,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 +903,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 +948,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,8 +957,7 @@ static void close_accept_socket()
                }
        }
 
-static int init_ssl_connection(con)
-SSL *con;
+static int init_ssl_connection(SSL *con)
        {
        int i;
        const char *str;
@@ -844,7 +1012,7 @@ SSL *con;
        }
 
 #ifndef NO_DH
-static DH *load_dh_param()
+static DH *load_dh_param(void)
        {
        DH *ret=NULL;
        BIO *bio;
@@ -859,9 +1027,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 +1047,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;
@@ -917,7 +1080,8 @@ char *context;
        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(context) SSL_set_session_id_context(con, context,
+                                              strlen((char *)context));
 
        sbio=BIO_new_socket(s,BIO_NOCLOSE);
        if (s_nbio_test)
@@ -933,6 +1097,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 +1169,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,"<HTML><BODY BGCOLOR=ffffff>\n");
+                       BIO_puts(io,"<HTML><BODY BGCOLOR=\"#ffffff\">\n");
                        BIO_puts(io,"<pre>\n");
 /*                     BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
                        BIO_puts(io,"\n");
@@ -1074,7 +1241,7 @@ char *context;
                        BIO_puts(io,"</BODY></HTML>\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;
@@ -1226,10 +1393,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 export, int keylength)
        {
        static RSA *rsa_tmp=NULL;
 
@@ -1240,9 +1405,7 @@ int keylength;
                        BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
                        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");
@@ -1251,3 +1414,4 @@ int keylength;
                }
        return(rsa_tmp);
        }
+#endif