replace macros with functions
[openssl.git] / apps / s_server.c
index e07f3dd20ed81bdd155c2d029a87e4a3716047e3..28501eb43a2fea35c556083d8556b158f90cba1e 100644 (file)
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 /* Until the key-gen callbacks are modified to use newer prototypes, we allow
  * deprecated functions for openssl-internal code */
 #endif
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -166,6 +193,10 @@ typedef unsigned int u_int;
 #undef FIONBIO
 #endif
 
+#if defined(OPENSSL_SYS_BEOS_R5)
+#include <fcntl.h>
+#endif
+
 #ifndef OPENSSL_NO_RSA
 static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength);
 #endif
@@ -227,7 +258,7 @@ static int accept_socket= -1;
 #undef PROG
 #define PROG           s_server_main
 
-extern int verify_depth;
+extern int verify_depth, verify_return_error;
 
 static char *cipher=NULL;
 static int s_server_verify=SSL_VERIFY_NONE;
@@ -263,6 +294,70 @@ static int enable_timeouts = 0;
 static long socket_mtu;
 static int cert_chain = 0;
 
+#ifndef OPENSSL_NO_PSK
+static char *psk_identity="Client_identity";
+static char *psk_key=NULL; /* by default PSK is not used */
+
+static unsigned int psk_server_cb(SSL *ssl, const char *identity,
+       unsigned char *psk, unsigned int max_psk_len)
+       {
+       unsigned int psk_len = 0;
+       int ret;
+       BIGNUM *bn = NULL;
+
+       if (s_debug)
+               BIO_printf(bio_s_out,"psk_server_cb\n");
+       if (!identity)
+               {
+               BIO_printf(bio_err,"Error: client did not send PSK identity\n");
+               goto out_err;
+               }
+       if (s_debug)
+               BIO_printf(bio_s_out,"identity_len=%d identity=%s\n",
+                       identity ? strlen(identity) : 0, identity);
+
+       /* here we could lookup the given identity e.g. from a database */
+       if (strcmp(identity, psk_identity) != 0)
+               {
+                BIO_printf(bio_s_out, "PSK error: client identity not found\n");
+               goto out_err;
+                }
+       if (s_debug)
+               BIO_printf(bio_s_out, "PSK client identity found\n");
+
+       /* convert the PSK key to binary */
+       ret = BN_hex2bn(&bn, psk_key);
+       if (!ret)
+               {
+               BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", psk_key);
+               if (bn)
+                       BN_free(bn);
+               return 0;
+               }
+       if (BN_num_bytes(bn) > (int)max_psk_len)
+               {
+               BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n",
+                       max_psk_len, BN_num_bytes(bn));
+               BN_free(bn);
+               return 0;
+               }
+
+       ret = BN_bn2bin(bn, psk);
+       BN_free(bn);
+
+       if (ret < 0)
+               goto out_err;
+       psk_len = (unsigned int)ret;
+
+       if (s_debug)
+               BIO_printf(bio_s_out, "fetched PSK len=%d\n", psk_len);
+        return psk_len;
+ out_err:
+       if (s_debug)
+               BIO_printf(bio_err, "Error in PSK server callback\n");
+       return 0;
+        }
+#endif
 
 #ifdef MONOLITH
 static void s_server_init(void)
@@ -322,7 +417,7 @@ static void sv_usage(void)
 #ifndef OPENSSL_NO_ECDH
        BIO_printf(bio_err," -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n" \
                           "                 Use \"openssl ecparam -list_curves\" for all names\n" \
-                          "                 (default is sect163r2).\n");
+                          "                 (default is nistp256).\n");
 #endif
 #ifdef FIONBIO
        BIO_printf(bio_err," -nbio         - Run with non-blocking IO\n");
@@ -339,6 +434,10 @@ static void sv_usage(void)
        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");
+#ifndef OPENSSL_NO_PSK
+       BIO_printf(bio_err," -psk_hint arg - PSK identity hint to use\n");
+       BIO_printf(bio_err," -psk arg      - PSK in hex (without 0x)\n");
+#endif
        BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
        BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
        BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
@@ -367,7 +466,7 @@ static void sv_usage(void)
        BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
 #ifndef OPENSSL_NO_TLSEXT
        BIO_printf(bio_err," -servername host - servername for HostName TLS extension\n");
-       BIO_printf(bio_err," -servername_warn - on mismatch send warning (default fatal alert)\n");
+       BIO_printf(bio_err," -servername_fatal - on mismatch send fatal alert (default warning alert)\n");
        BIO_printf(bio_err," -cert2 arg    - certificate file to use for servername\n");
        BIO_printf(bio_err,"                 (default is %s)\n",TEST_CERT2);
        BIO_printf(bio_err," -key2 arg     - Private Key file to use for servername, in cert file if\n");
@@ -534,7 +633,7 @@ static int ebcdic_puts(BIO *bp, const char *str)
 typedef struct tlsextctx_st {
    char * servername;
    BIO * biodebug;
-   int servername_warn;
+   int extension_error;
 } tlsextctx;
 
 
@@ -546,18 +645,19 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
                BIO_printf(p->biodebug,"Hostname in TLS extension: \"%s\"\n",servername);
         
        if (!p->servername)
-               return 1;
+               return SSL_TLSEXT_ERR_NOACK;
        
        if (servername)
                {
                if (strcmp(servername,p->servername)) 
-                       return  p->servername_warn;
-               if (ctx2) {
+                       return p->extension_error;
+               if (ctx2)
+                       {
                        BIO_printf(p->biodebug,"Swiching server context.\n");
                        SSL_set_SSL_CTX(s,ctx2);
                        }     
                }
-       return 1;
+       return SSL_TLSEXT_ERR_OK;
 }
 #endif
 
@@ -597,7 +697,11 @@ int MAIN(int argc, char *argv[])
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
-        tlsextctx tlsextcbp = {NULL, NULL, -1};
+        tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING};
+#endif
+#ifndef OPENSSL_NO_PSK
+       /* by default do not send a PSK identity hint */
+       static char *psk_identity_hint=NULL;
 #endif
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
@@ -738,6 +842,8 @@ int MAIN(int argc, char *argv[])
                        {
                        vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
                        }
+               else if (strcmp(*argv,"-verify_return_error") == 0)
+                       verify_return_error = 1;
                else if (strcmp(*argv,"-serverpref") == 0)
                        { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; }
                else if (strcmp(*argv,"-cipher") == 0)
@@ -781,6 +887,27 @@ int MAIN(int argc, char *argv[])
                        { no_dhe=1; }
                else if (strcmp(*argv,"-no_ecdhe") == 0)
                        { no_ecdhe=1; }
+#ifndef OPENSSL_NO_PSK
+                else if (strcmp(*argv,"-psk_hint") == 0)
+                       {
+                        if (--argc < 1) goto bad;
+                        psk_identity_hint= *(++argv);
+                        }
+                else if (strcmp(*argv,"-psk") == 0)
+                       {
+                       size_t i;
+
+                       if (--argc < 1) goto bad;
+                       psk_key=*(++argv);
+                       for (i=0; i<strlen(psk_key); i++)
+                               {
+                               if (isxdigit((int)psk_key[i]))
+                                       continue;
+                               BIO_printf(bio_err,"Not a hex number '%s'\n",*argv);
+                               goto bad;
+                               }
+                       }
+#endif
                else if (strcmp(*argv,"-www") == 0)
                        { www=1; }
                else if (strcmp(*argv,"-WWW") == 0)
@@ -846,8 +973,8 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        tlsextcbp.servername= *(++argv);
                        }
-               else if (strcmp(*argv,"-servername_warn") == 0)
-                       { tlsextcbp.servername_warn = 0; }
+               else if (strcmp(*argv,"-servername_fatal") == 0)
+                       { tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL; }
                else if (strcmp(*argv,"-cert2") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -1187,10 +1314,10 @@ bad:
                else
                        {
                        BIO_printf(bio_s_out,"Using default temp ECDH parameters\n");
-                       ecdh = EC_KEY_new_by_curve_name(NID_sect163r2);
+                       ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
                        if (ecdh == NULL) 
                                {
-                               BIO_printf(bio_err, "unable to create curve (sect163r2)\n");
+                               BIO_printf(bio_err, "unable to create curve (nistp256)\n");
                                goto end;
                                }
                        }
@@ -1258,6 +1385,22 @@ bad:
 #endif
 #endif
 
+#ifndef OPENSSL_NO_PSK
+       if (psk_key != NULL)
+               {
+               if (s_debug)
+                       BIO_printf(bio_s_out, "PSK key given, setting server callback\n");
+               SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
+               }
+
+       if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint))
+               {
+               BIO_printf(bio_err,"error setting PSK identity hint to context\n");
+               ERR_print_errors(bio_err);
+               goto end;
+               }
+#endif
+
        if (cipher != NULL)
                {
                if(!SSL_CTX_set_cipher_list(ctx,cipher))
@@ -1374,7 +1517,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
        unsigned long l;
        SSL *con=NULL;
        BIO *sbio;
-#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5)
        struct timeval tv;
 #endif
 
@@ -1459,7 +1602,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                {
                con->debug=1;
                BIO_set_callback(SSL_get_rbio(con),bio_dump_callback);
-               BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out);
+               BIO_set_callback_arg(SSL_get_rbio(con),(char *)bio_s_out);
                }
        if (s_msg)
                {
@@ -1479,10 +1622,10 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                if (!read_from_sslcon)
                        {
                        FD_ZERO(&readfds);
-#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE)
-                       FD_SET(fileno(stdin),&readfds);
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_BEOS_R5)
+                       openssl_fdset(fileno(stdin),&readfds);
 #endif
-                       FD_SET(s,&readfds);
+                       openssl_fdset(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
@@ -1501,6 +1644,17 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                        if((i < 0) || (!i && !_kbhit() ) )continue;
                        if(_kbhit())
                                read_from_terminal = 1;
+#elif defined(OPENSSL_SYS_BEOS_R5)
+                       /* Under BeOS-R5 the situation is similar to DOS */
+                       tv.tv_sec = 1;
+                       tv.tv_usec = 0;
+                       (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
+                       i=select(width,(void *)&readfds,NULL,NULL,&tv);
+                       if ((i < 0) || (!i && read(fileno(stdin), buf, 0) < 0))
+                               continue;
+                       if (read(fileno(stdin), buf, 0) >= 0)
+                               read_from_terminal = 1;
+                       (void)fcntl(fileno(stdin), F_SETFL, 0);
 #else
                        i=select(width,(void *)&readfds,NULL,NULL,NULL);
                        if (i <= 0) continue;
@@ -1676,13 +1830,16 @@ again:
                        }
                }
 err:
-       BIO_printf(bio_s_out,"shutting down SSL\n");
+       if (con != NULL)
+               {
+               BIO_printf(bio_s_out,"shutting down SSL\n");
 #if 1
-       SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+               SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
 #else
-       SSL_shutdown(con);
+               SSL_shutdown(con);
 #endif
-       if (con != NULL) SSL_free(con);
+               SSL_free(con);
+               }
        BIO_printf(bio_s_out,"CONNECTION CLOSED\n");
        if (buf != NULL)
                {
@@ -1863,7 +2020,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                {
                con->debug=1;
                BIO_set_callback(SSL_get_rbio(con),bio_dump_callback);
-               BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out);
+               BIO_set_callback_arg(SSL_get_rbio(con),(char *)bio_s_out);
                }
        if (s_msg)
                {