* [including the GNU Public Licence.]
*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef NO_STDIO
+#define APPS_WIN16
+#endif
+
/* 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
typedef unsigned int u_int;
#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef NO_STDIO
-#define APPS_WIN16
-#endif
#include <openssl/lhash.h>
#include <openssl/bn.h>
#define USE_SOCKETS
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
+#include <openssl/engine.h>
#include "s_apps.h"
+#ifdef WINDOWS
+#include <conio.h>
+#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
-#if defined(NO_RSA) && !defined(NO_SSL2)
-#define NO_SSL2
-#endif
-
#ifndef NO_RSA
static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength);
#endif
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);*/
+#ifdef MONOLITH
+static void s_server_init(void);
+#endif
#ifndef S_ISDIR
# if defined(_S_IFMT) && defined(_S_IFDIR)
#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_nbio=0;
#endif
static int s_nbio_test=0;
+int s_crlf=0;
static SSL_CTX *ctx=NULL;
static int www=0;
static int s_debug=0;
static int s_quiet=0;
-#if 0
+static int hack=0;
+static char *engine_id=NULL;
+
+#ifdef MONOLITH
static void s_server_init(void)
{
+ accept_socket=-1;
cipher=NULL;
s_server_verify=SSL_VERIFY_NONE;
s_dcert_file=NULL;
bio_s_out=NULL;
s_debug=0;
s_quiet=0;
+ hack=0;
+ engine_id=NULL;
}
#endif
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");
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 /<path> HTTP/1.0' with file ./<path>\n");
+ BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n");
}
static int local_argc=0;
static char **local_argv;
-static int hack=0;
#ifdef CHARSET_EBCDIC
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';
{
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;
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';
}
#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
- DH *dh=NULL;
-#endif
+ ENGINE *e=NULL;
#if !defined(NO_SSL2) && !defined(NO_SSL3)
meth=SSLv23_server_method();
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);
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;
{ 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)
else if (strcmp(*argv,"-tls1") == 0)
{ meth=TLSv1_server_method(); }
#endif
+ else if (strcmp(*argv,"-engine") == 0)
+ {
+ if (--argc < 1) goto bad;
+ engine_id= *(++argv);
+ }
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
goto end;
}
+ app_RAND_load_file(NULL, bio_err, 0);
+
if (bio_s_out == NULL)
{
if (s_quiet && !s_debug)
}
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)
}
#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();
- }
- (void)BIO_flush(bio_s_out);
+ DH *dh=NULL;
- SSL_CTX_set_tmp_dh(ctx,dh);
- DH_free(dh);
+ 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");
+ }
+ 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);
+ }
#endif
if (!set_cert_stuff(ctx,s_cert_file,s_key_file))
#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)
unsigned long l;
SSL *con=NULL;
BIO *sbio;
+#ifdef 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;
#endif
if (con == NULL) {
- con=(SSL *)SSL_new(ctx);
+ con=SSL_new(ctx);
+#ifndef 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 /* NO_KRB5 */
if(context)
SSL_set_session_id_context(con, context,
strlen((char *)context));
width=s+1;
for (;;)
{
- FD_ZERO(&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 WINDOWS
- FD_SET(fileno(stdin),&readfds);
+ 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 *).
- */
- i=select(width,(void *)&readfds,NULL,NULL,NULL);
- if (i <= 0) continue;
- if (FD_ISSET(fileno(stdin),&readfds))
+ 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())
+ read_from_terminal = 1;
+#else
+ 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)
{
- 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'))
if (i <= 0) break;
}
}
- if (FD_ISSET(s,&readfds))
+ if (read_from_sslcon)
{
if (!SSL_is_init_finished(con))
{
if (buf != NULL)
{
memset(buf,0,bufsize);
- Free(buf);
+ OPENSSL_free(buf);
}
if (ret >= 0)
BIO_printf(bio_s_out,"ACCEPT\n");
}
#ifndef NO_DH
-static DH *load_dh_param(void)
+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);
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());
/* 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));
/* 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
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);