make update
[oweals/openssl.git] / apps / s_server.c
index 7c5775f81c15c3831dd27f083874952c06ab676c..1f1f317d419ac2df29be38117bdd03994fbfb21a 100644 (file)
@@ -153,6 +153,7 @@ typedef unsigned int u_int;
 #include <openssl/x509.h>
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
@@ -269,6 +270,8 @@ static BIO *bio_s_out=NULL;
 static int s_debug=0;
 #ifndef OPENSSL_NO_TLSEXT
 static int s_tlsextdebug=0;
+static int s_tlsextstatus=0;
+static int cert_status_cb(SSL *s, void *arg);
 #endif
 static int s_msg=0;
 static int s_quiet=0;
@@ -280,11 +283,10 @@ static char *engine_id=NULL;
 static const char *session_id_prefix=NULL;
 
 static int enable_timeouts = 0;
-#ifdef mtu
-#undef mtu
-#endif
-static long mtu;
+static long socket_mtu;
+#ifndef OPENSSL_NO_DTLS1
 static int cert_chain = 0;
+#endif
 
 
 #ifdef MONOLITH
@@ -330,6 +332,11 @@ static void sv_usage(void)
        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\n");
        BIO_printf(bio_err,"                 (default is %s)\n",TEST_CERT);
+       BIO_printf(bio_err," -crl_check    - check the peer certificate has not been revoked by its CA.\n" \
+                          "                 The CRL(s) are appended to the certificate file\n");
+       BIO_printf(bio_err," -crl_check_all - check the peer certificate has not been revoked by its CA\n" \
+                          "                 or any other CRL in the CA chain. CRL(s) are appened to the\n" \
+                          "                 the certificate file.\n");
        BIO_printf(bio_err," -certform arg - certificate format (PEM or DER) PEM default\n");
        BIO_printf(bio_err," -key arg      - Private Key file to use, in cert file if\n");
        BIO_printf(bio_err,"                 not specified (default is %s)\n",TEST_CERT);
@@ -367,7 +374,7 @@ static void sv_usage(void)
        BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
        BIO_printf(bio_err," -dtls1        - Just talk DTLSv1\n");
        BIO_printf(bio_err," -timeout      - Enable timeouts\n");
-       BIO_printf(bio_err," -mtu          - Set MTU\n");
+       BIO_printf(bio_err," -mtu          - Set link layer MTU\n");
        BIO_printf(bio_err," -chain        - Read a certificate chain\n");
        BIO_printf(bio_err," -no_ssl2      - Just disable SSLv2\n");
        BIO_printf(bio_err," -no_ssl3      - Just disable SSLv3\n");
@@ -397,6 +404,7 @@ static void sv_usage(void)
        BIO_printf(bio_err,"                 not specified (default is %s)\n",TEST_CERT2);
        BIO_printf(bio_err," -tlsextdebug  - hex dump of all TLS extensions received\n");
        BIO_printf(bio_err," -no_ticket    - disable use of RFC4507bis session tickets\n");
+       BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
 #endif
        }
 
@@ -585,9 +593,159 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
                }
        return SSL_TLSEXT_ERR_OK;
 }
+
+/* Structure passed to cert status callback */
+
+typedef struct tlsextstatusctx_st {
+   /* Default responder to use */
+   char *host, *path, *port;
+   int use_ssl;
+   int timeout;
+   BIO *err;
+   int verbose;
+} tlsextstatusctx;
+
+static tlsextstatusctx tlscstatp = {NULL, NULL, NULL, 0, -1, NULL, 0};
+
+/* Certificate Status callback. This is called when a client includes a
+ * certificate status request extension.
+ *
+ * This is a simplified version. It examines certificates each time and
+ * makes one OCSP responder query for each request.
+ *
+ * A full version would store details such as the OCSP certificate IDs and
+ * minimise the number of OCSP responses by caching them until they were
+ * considered "expired".
+ */
+
+static int cert_status_cb(SSL *s, void *arg)
+       {
+       tlsextstatusctx *srctx = arg;
+       BIO *err = srctx->err;
+       char *host, *port, *path;
+       int use_ssl;
+       unsigned char *rspder = NULL;
+       int rspderlen;
+       STACK *aia = NULL;
+       X509 *x = NULL;
+       X509_STORE_CTX inctx;
+       X509_OBJECT obj;
+       OCSP_REQUEST *req = NULL;
+       OCSP_RESPONSE *resp = NULL;
+       OCSP_CERTID *id = NULL;
+       STACK_OF(X509_EXTENSION) *exts;
+       int ret = SSL_TLSEXT_ERR_NOACK;
+       int i;
+#if 0
+STACK_OF(OCSP_RESPID) *ids;
+SSL_get_tlsext_status_ids(s, &ids);
+BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids));
+#endif
+       if (srctx->verbose)
+               BIO_puts(err, "cert_status: callback called\n");
+       /* Build up OCSP query from server certificate */
+       x = SSL_get_certificate(s);
+       aia = X509_get1_ocsp(x);
+       if (aia)
+               {
+               if (!OCSP_parse_url(sk_value(aia, 0),
+                       &host, &port, &path, &use_ssl))
+                       {
+                       BIO_puts(err, "cert_status: can't parse AIA URL\n");
+                       goto err;
+                       }
+               if (srctx->verbose)
+                       BIO_printf(err, "cert_status: AIA URL: %s\n",
+                                       sk_value(aia, 0));
+               }
+       else
+               {
+               if (!srctx->host)
+                       {
+                       BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n");
+                       goto done;
+                       }
+               host = srctx->host;
+               path = srctx->path;
+               port = srctx->port;
+               use_ssl = srctx->use_ssl;
+               }
+               
+       if (!X509_STORE_CTX_init(&inctx,
+                               SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
+                               NULL, NULL))
+               goto err;
+       if (X509_STORE_get_by_subject(&inctx,X509_LU_X509,
+                               X509_get_issuer_name(x),&obj) <= 0)
+               {
+               BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n");
+               X509_STORE_CTX_cleanup(&inctx);
+               goto done;
+               }
+       req = OCSP_REQUEST_new();
+       if (!req)
+               goto err;
+       id = OCSP_cert_to_id(NULL, x, obj.data.x509);
+       X509_free(obj.data.x509);
+       X509_STORE_CTX_cleanup(&inctx);
+       if (!id)
+               goto err;
+       if (!OCSP_request_add0_id(req, id))
+               goto err;
+       id = NULL;
+       /* Add any extensions to the request */
+       SSL_get_tlsext_status_exts(s, &exts);
+       for (i = 0; i < sk_X509_EXTENSION_num(exts); i++)
+               {
+               X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+               if (!OCSP_REQUEST_add_ext(req, ext, -1))
+                       goto err;
+               }
+       resp = process_responder(err, req, host, path, port, use_ssl,
+                                       srctx->timeout);
+       if (!resp)
+               {
+               BIO_puts(err, "cert_status: error querying responder\n");
+               goto done;
+               }
+       rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
+       if (rspderlen <= 0)
+               goto err;
+       SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
+       if (srctx->verbose)
+               {
+               BIO_puts(err, "cert_status: ocsp response sent:\n");
+               OCSP_RESPONSE_print(err, resp, 2);
+               }
+       ret = SSL_TLSEXT_ERR_OK;
+       done:
+       if (ret != SSL_TLSEXT_ERR_OK)
+               ERR_print_errors(err);
+       if (aia)
+               {
+               OPENSSL_free(host);
+               OPENSSL_free(path);
+               OPENSSL_free(port);
+               X509_email_free(aia);
+               }
+       if (id)
+               OCSP_CERTID_free(id);
+       if (req)
+               OCSP_REQUEST_free(req);
+       if (resp)
+               OCSP_RESPONSE_free(resp);
+       return ret;
+       err:
+       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+       goto done;
+       }
 #endif
 int MAIN(int, char **);
 
+#ifndef OPENSSL_NO_JPAKE
+static char *jpake_secret = NULL;
+#endif
+
 int MAIN(int argc, char *argv[])
        {
        X509_STORE *store = NULL;
@@ -606,9 +764,7 @@ int MAIN(int argc, char *argv[])
        int state=0;
        SSL_METHOD *meth=NULL;
         int socket_type=SOCK_STREAM;
-#ifndef OPENSSL_NO_ENGINE
        ENGINE *e=NULL;
-#endif
        char *inrand=NULL;
        int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
        char *passarg = NULL, *pass = NULL;
@@ -616,22 +772,16 @@ int MAIN(int argc, char *argv[])
        int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
        X509 *s_cert = NULL, *s_dcert = NULL;
        EVP_PKEY *s_key = NULL, *s_dkey = NULL;
+       int no_cache = 0;
 #ifndef OPENSSL_NO_TLSEXT
        EVP_PKEY *s_key2 = NULL;
        X509 *s_cert2 = NULL;
 #endif
-
 #ifndef OPENSSL_NO_TLSEXT
         tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING};
 #endif
 
-#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
-#elif !defined(OPENSSL_NO_SSL3)
-       meth=SSLv3_server_method();
-#elif !defined(OPENSSL_NO_SSL2)
-       meth=SSLv2_server_method();
-#endif
 
        local_argc=argc;
        local_argv=argv;
@@ -756,16 +906,20 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        CApath= *(++argv);
                        }
+               else if (strcmp(*argv,"-no_cache") == 0)
+                       no_cache = 1;
                else if (strcmp(*argv,"-crl_check") == 0)
                        {
                        vflags |= X509_V_FLAG_CRL_CHECK;
                        }
-               else if (strcmp(*argv,"-crl_check") == 0)
+               else if (strcmp(*argv,"-crl_check_all") == 0)
                        {
                        vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
                        }
                else if (strcmp(*argv,"-serverpref") == 0)
                        { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; }
+               else if (strcmp(*argv,"-legacy_renegotiation") == 0)
+                       off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
                else if (strcmp(*argv,"-cipher") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -792,6 +946,33 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLSEXT
                else if (strcmp(*argv,"-tlsextdebug") == 0)
                        s_tlsextdebug=1;
+               else if (strcmp(*argv,"-status") == 0)
+                       s_tlsextstatus=1;
+               else if (strcmp(*argv,"-status_verbose") == 0)
+                       {
+                       s_tlsextstatus=1;
+                       tlscstatp.verbose = 1;
+                       }
+               else if (!strcmp(*argv, "-status_timeout"))
+                       {
+                       s_tlsextstatus=1;
+                        if (--argc < 1) goto bad;
+                       tlscstatp.timeout = atoi(*(++argv));
+                       }
+               else if (!strcmp(*argv, "-status_url"))
+                       {
+                       s_tlsextstatus=1;
+                        if (--argc < 1) goto bad;
+                       if (!OCSP_parse_url(*(++argv),
+                                       &tlscstatp.host,
+                                       &tlscstatp.port,
+                                       &tlscstatp.path,
+                                       &tlscstatp.use_ssl))
+                               {
+                               BIO_printf(bio_err, "Error parsing URL\n");
+                               goto bad;
+                               }
+                       }
 #endif
                else if (strcmp(*argv,"-msg") == 0)
                        { s_msg=1; }
@@ -850,7 +1031,7 @@ int MAIN(int argc, char *argv[])
                else if (strcmp(*argv,"-mtu") == 0)
                        {
                        if (--argc < 1) goto bad;
-                       mtu = atol(*(++argv));
+                       socket_mtu = atol(*(++argv));
                        }
                else if (strcmp(*argv, "-chain") == 0)
                        cert_chain = 1;
@@ -890,6 +1071,14 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        s_key_file2= *(++argv);
                        }
+                       
+#endif
+#ifndef OPENSSL_NO_JPAKE
+               else if (strcmp(*argv,"-jpake") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       jpake_secret = *(++argv);
+                       }
 #endif
                else
                        {
@@ -1063,8 +1252,10 @@ bad:
        if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
 
        if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
-
-       SSL_CTX_sess_set_cache_size(ctx,128);
+       if (no_cache)
+               SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+       else
+               SSL_CTX_sess_set_cache_size(ctx,128);
 
 #if 0
        if (cipher == NULL) cipher=getenv("SSL_CIPHER");
@@ -1131,7 +1322,10 @@ bad:
 
                if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback);
 
-               SSL_CTX_sess_set_cache_size(ctx2,128);
+               if (no_cache)
+                       SSL_CTX_set_session_cache_mode(ctx2,SSL_SESS_CACHE_OFF);
+               else
+                       SSL_CTX_sess_set_cache_size(ctx2,128);
 
                if ((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) ||
                        (!SSL_CTX_set_default_verify_paths(ctx2)))
@@ -1308,6 +1502,10 @@ bad:
        SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context,
                sizeof s_server_session_id_context);
 
+       /* Set DTLS cookie generation and verification callbacks */
+       SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
+       SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
+
 #ifndef OPENSSL_NO_TLSEXT
        if (ctx2)
                {
@@ -1352,6 +1550,12 @@ end:
        if (dpass)
                OPENSSL_free(dpass);
 #ifndef OPENSSL_NO_TLSEXT
+       if (tlscstatp.host)
+               OPENSSL_free(tlscstatp.host);
+       if (tlscstatp.port)
+               OPENSSL_free(tlscstatp.port);
+       if (tlscstatp.path)
+               OPENSSL_free(tlscstatp.path);
        if (ctx2 != NULL) SSL_CTX_free(ctx2);
        if (s_cert2)
                X509_free(s_cert2);
@@ -1401,8 +1605,11 @@ static int sv_body(char *hostname, int s, unsigned char *context)
        unsigned long l;
        SSL *con=NULL;
        BIO *sbio;
+       struct timeval timeout;
 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
        struct timeval tv;
+#else
+       struct timeval *timeoutp;
 #endif
 
        if ((buf=OPENSSL_malloc(bufsize)) == NULL)
@@ -1430,6 +1637,12 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                SSL_set_tlsext_debug_callback(con, tlsext_cb);
                SSL_set_tlsext_debug_arg(con, bio_s_out);
                }
+       if (s_tlsextstatus)
+               {
+               SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
+               tlscstatp.err = bio_err;
+               SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp);
+               }
 #endif
 #ifndef OPENSSL_NO_KRB5
                if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
@@ -1448,7 +1661,6 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 
        if (SSL_version(con) == DTLS1_VERSION)
                {
-               struct timeval timeout;
 
                sbio=BIO_new_dgram(s,BIO_NOCLOSE);
 
@@ -1464,10 +1676,10 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                        }
 
                
-               if ( mtu > 0)
+               if (socket_mtu > 28)
                        {
                        SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
-                       SSL_set_mtu(con, mtu);
+                       SSL_set_mtu(con, socket_mtu - 28);
                        }
                else
                        /* want to do MTU discovery */
@@ -1486,6 +1698,11 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                test=BIO_new(BIO_f_nbio_test());
                sbio=BIO_push(test,sbio);
                }
+#ifndef OPENSSL_NO_JPAKE
+       if(jpake_secret)
+               jpake_server_auth(bio_s_out, sbio, jpake_secret);
+#endif
+
        SSL_set_bio(con,sbio,sbio);
        SSL_set_accept_state(con);
        /* SSL_set_fd(con,s); */
@@ -1544,7 +1761,19 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                        if(_kbhit())
                                read_from_terminal = 1;
 #else
-                       i=select(width,(void *)&readfds,NULL,NULL,NULL);
+                       if ((SSL_version(con) == DTLS1_VERSION) &&
+                               DTLSv1_get_timeout(con, &timeout))
+                               timeoutp = &timeout;
+                       else
+                               timeoutp = NULL;
+
+                       i=select(width,(void *)&readfds,NULL,NULL,timeoutp);
+
+                       if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0)
+                               {
+                               BIO_printf(bio_err,"TIMEOUT occured\n");
+                               }
+
                        if (i <= 0) continue;
                        if (FD_ISSET(fileno(stdin),&readfds))
                                read_from_terminal = 1;
@@ -1801,6 +2030,8 @@ static int init_ssl_connection(SSL *con)
                        con->kssl_ctx->client_princ);
                }
 #endif /* OPENSSL_NO_KRB5 */
+       BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
+                     SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
        return(1);
        }
 
@@ -1844,12 +2075,14 @@ static int www_body(char *hostname, int s, unsigned char *context)
        {
        char *buf=NULL;
        int ret=1;
-       int i,j,k,blank,dot;
+       int i,j,k,dot;
        struct stat st_buf;
        SSL *con;
        SSL_CIPHER *c;
        BIO *io,*ssl_bio,*sbio;
+#ifdef RENEG
        long total_bytes;
+#endif
 
        buf=OPENSSL_malloc(bufsize);
        if (buf == NULL) return(0);
@@ -1920,7 +2153,6 @@ static int www_body(char *hostname, int s, unsigned char *context)
                SSL_set_msg_callback_arg(con, bio_s_out);
                }
 
-       blank=0;
        for (;;)
                {
                if (hack)
@@ -2157,7 +2389,9 @@ static int www_body(char *hostname, int s, unsigned char *context)
                                         BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
                                 }
                        /* send the file */
+#ifdef RENEG
                        total_bytes=0;
+#endif
                        for (;;)
                                {
                                i=BIO_read(file,buf,bufsize);