xref: /openbsd-src/usr.bin/openssl/s_server.c (revision 23cc9d400791825fb9615b5c61d55ff2adb3056b)
1*23cc9d40Stb /* $OpenBSD: s_server.c,v 1.61 2025/01/02 13:10:03 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing /* ====================================================================
59dab3f910Sjsing  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60dab3f910Sjsing  *
61dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
62dab3f910Sjsing  * modification, are permitted provided that the following conditions
63dab3f910Sjsing  * are met:
64dab3f910Sjsing  *
65dab3f910Sjsing  * 1. Redistributions of source code must retain the above copyright
66dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
67dab3f910Sjsing  *
68dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
69dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in
70dab3f910Sjsing  *    the documentation and/or other materials provided with the
71dab3f910Sjsing  *    distribution.
72dab3f910Sjsing  *
73dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this
74dab3f910Sjsing  *    software must display the following acknowledgment:
75dab3f910Sjsing  *    "This product includes software developed by the OpenSSL Project
76dab3f910Sjsing  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77dab3f910Sjsing  *
78dab3f910Sjsing  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79dab3f910Sjsing  *    endorse or promote products derived from this software without
80dab3f910Sjsing  *    prior written permission. For written permission, please contact
81dab3f910Sjsing  *    openssl-core@openssl.org.
82dab3f910Sjsing  *
83dab3f910Sjsing  * 5. Products derived from this software may not be called "OpenSSL"
84dab3f910Sjsing  *    nor may "OpenSSL" appear in their names without prior written
85dab3f910Sjsing  *    permission of the OpenSSL Project.
86dab3f910Sjsing  *
87dab3f910Sjsing  * 6. Redistributions of any form whatsoever must retain the following
88dab3f910Sjsing  *    acknowledgment:
89dab3f910Sjsing  *    "This product includes software developed by the OpenSSL Project
90dab3f910Sjsing  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91dab3f910Sjsing  *
92dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93dab3f910Sjsing  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95dab3f910Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96dab3f910Sjsing  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97dab3f910Sjsing  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98dab3f910Sjsing  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99dab3f910Sjsing  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101dab3f910Sjsing  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102dab3f910Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103dab3f910Sjsing  * OF THE POSSIBILITY OF SUCH DAMAGE.
104dab3f910Sjsing  * ====================================================================
105dab3f910Sjsing  *
106dab3f910Sjsing  * This product includes cryptographic software written by Eric Young
107dab3f910Sjsing  * (eay@cryptsoft.com).  This product includes software written by Tim
108dab3f910Sjsing  * Hudson (tjh@cryptsoft.com).
109dab3f910Sjsing  *
110dab3f910Sjsing  */
111dab3f910Sjsing /* ====================================================================
112dab3f910Sjsing  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
113dab3f910Sjsing  * ECC cipher suite support in OpenSSL originally developed by
114dab3f910Sjsing  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115dab3f910Sjsing  */
116dab3f910Sjsing /* ====================================================================
117dab3f910Sjsing  * Copyright 2005 Nokia. All rights reserved.
118dab3f910Sjsing  *
119dab3f910Sjsing  * The portions of the attached software ("Contribution") is developed by
120dab3f910Sjsing  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
121dab3f910Sjsing  * license.
122dab3f910Sjsing  *
123dab3f910Sjsing  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
124dab3f910Sjsing  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
125dab3f910Sjsing  * support (see RFC 4279) to OpenSSL.
126dab3f910Sjsing  *
127dab3f910Sjsing  * No patent licenses or other rights except those expressly stated in
128dab3f910Sjsing  * the OpenSSL open source license shall be deemed granted or received
129dab3f910Sjsing  * expressly, by implication, estoppel, or otherwise.
130dab3f910Sjsing  *
131dab3f910Sjsing  * No assurances are provided by Nokia that the Contribution does not
132dab3f910Sjsing  * infringe the patent or other intellectual property rights of any third
133dab3f910Sjsing  * party or that the license provides you with all the necessary rights
134dab3f910Sjsing  * to make use of the Contribution.
135dab3f910Sjsing  *
136dab3f910Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
137dab3f910Sjsing  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
138dab3f910Sjsing  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
139dab3f910Sjsing  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
140dab3f910Sjsing  * OTHERWISE.
141dab3f910Sjsing  */
142dab3f910Sjsing 
143dab3f910Sjsing /* Until the key-gen callbacks are modified to use newer prototypes, we allow
144dab3f910Sjsing  * deprecated functions for openssl-internal code */
145dab3f910Sjsing #ifdef OPENSSL_NO_DEPRECATED
146dab3f910Sjsing #undef OPENSSL_NO_DEPRECATED
147dab3f910Sjsing #endif
148dab3f910Sjsing 
149dab3f910Sjsing #include <sys/types.h>
150dab3f910Sjsing #include <sys/socket.h>
151dab3f910Sjsing 
152dab3f910Sjsing #include <assert.h>
153dab3f910Sjsing #include <ctype.h>
154dab3f910Sjsing #include <stdio.h>
155dab3f910Sjsing #include <stdlib.h>
156dab3f910Sjsing #include <limits.h>
157dab3f910Sjsing #include <string.h>
158dab3f910Sjsing #include <unistd.h>
1599c8ea7b6Sderaadt #include <poll.h>
160dab3f910Sjsing 
161dab3f910Sjsing #include "apps.h"
162dab3f910Sjsing 
163dab3f910Sjsing #include <openssl/bn.h>
164dab3f910Sjsing #include <openssl/err.h>
165dab3f910Sjsing #include <openssl/lhash.h>
166dab3f910Sjsing #include <openssl/ocsp.h>
167dab3f910Sjsing #include <openssl/pem.h>
168dab3f910Sjsing #include <openssl/ssl.h>
169dab3f910Sjsing #include <openssl/x509.h>
170dab3f910Sjsing 
171dab3f910Sjsing #ifndef OPENSSL_NO_DH
172dab3f910Sjsing #include <openssl/dh.h>
173dab3f910Sjsing #endif
174dab3f910Sjsing 
175dab3f910Sjsing #include <openssl/rsa.h>
176dab3f910Sjsing 
17772a107cfSinoguchi static void s_server_init(void);
178dab3f910Sjsing static void sv_usage(void);
179dab3f910Sjsing static void print_stats(BIO *bp, SSL_CTX *ctx);
1807537a7c2Stb static int sv_body(int s, unsigned char *context);
18172a107cfSinoguchi static void close_accept_socket(void);
18272a107cfSinoguchi static int init_ssl_connection(SSL *s);
183dab3f910Sjsing #ifndef OPENSSL_NO_DH
184dab3f910Sjsing static DH *load_dh_param(const char *dhfile);
185dab3f910Sjsing #endif
1867537a7c2Stb static int www_body(int s, unsigned char *context);
18772a107cfSinoguchi static int generate_session_id(const SSL *ssl, unsigned char *id,
18872a107cfSinoguchi     unsigned int *id_len);
18972a107cfSinoguchi static int ssl_servername_cb(SSL *s, int *ad, void *arg);
19072a107cfSinoguchi static int cert_status_cb(SSL * s, void *arg);
19172a107cfSinoguchi static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
19272a107cfSinoguchi     const unsigned char *in, unsigned int inlen, void *arg);
193dab3f910Sjsing /* static int load_CA(SSL_CTX *ctx, char *file);*/
194dab3f910Sjsing 
195dab3f910Sjsing #define BUFSIZZ	16*1024
196dab3f910Sjsing static int bufsize = BUFSIZZ;
197dab3f910Sjsing static int accept_socket = -1;
198dab3f910Sjsing 
199dab3f910Sjsing #define TEST_CERT	"server.pem"
200dab3f910Sjsing #define TEST_CERT2	"server2.pem"
201dab3f910Sjsing 
202dab3f910Sjsing static int s_server_session_id_context = 1;	/* anything will do */
203dab3f910Sjsing static SSL_CTX *ctx = NULL;
204dab3f910Sjsing static SSL_CTX *ctx2 = NULL;
205dab3f910Sjsing static BIO *bio_s_out = NULL;
20672a107cfSinoguchi 
20772a107cfSinoguchi static int local_argc = 0;
20872a107cfSinoguchi static char **local_argv;
209dab3f910Sjsing 
210dab3f910Sjsing /* This is a context that we pass to callbacks */
211dab3f910Sjsing typedef struct tlsextctx_st {
212dab3f910Sjsing 	char *servername;
213dab3f910Sjsing 	BIO *biodebug;
214dab3f910Sjsing 	int extension_error;
215dab3f910Sjsing } tlsextctx;
216dab3f910Sjsing 
2175a233072Sinoguchi /* Structure passed to cert status callback */
2185a233072Sinoguchi typedef struct tlsextstatusctx_st {
2195a233072Sinoguchi 	/* Default responder to use */
2205a233072Sinoguchi 	char *host, *path, *port;
2215a233072Sinoguchi 	int use_ssl;
2225a233072Sinoguchi 	int timeout;
2235a233072Sinoguchi 	BIO *err;
2245a233072Sinoguchi 	int verbose;
2255a233072Sinoguchi } tlsextstatusctx;
2265a233072Sinoguchi 
22772a107cfSinoguchi /* This the context that we pass to alpn_cb */
22872a107cfSinoguchi typedef struct tlsextalpnctx_st {
22972a107cfSinoguchi 	unsigned char *data;
23072a107cfSinoguchi 	unsigned short len;
23172a107cfSinoguchi } tlsextalpnctx;
23272a107cfSinoguchi 
2335a233072Sinoguchi static struct {
2345a233072Sinoguchi 	char *alpn_in;
2355a233072Sinoguchi 	char *npn_in; /* Ignored. */
2365a233072Sinoguchi 	int bugs;
2375a233072Sinoguchi 	char *CAfile;
2385a233072Sinoguchi 	char *CApath;
23993dafd19Sjsing #ifndef OPENSSL_NO_DTLS
2405a233072Sinoguchi 	int cert_chain;
2415a233072Sinoguchi #endif
2420e15fe22Sinoguchi 	char *cert_file;
2430e15fe22Sinoguchi 	char *cert_file2;
2440e15fe22Sinoguchi 	int cert_format;
2455a233072Sinoguchi 	char *cipher;
2465a233072Sinoguchi 	unsigned char *context;
2470e15fe22Sinoguchi 	int crlf;
2480e15fe22Sinoguchi 	char *dcert_file;
2490e15fe22Sinoguchi 	int dcert_format;
2500e15fe22Sinoguchi 	int debug;
2515a233072Sinoguchi 	char *dhfile;
2520e15fe22Sinoguchi 	char *dkey_file;
2530e15fe22Sinoguchi 	int dkey_format;
2545a233072Sinoguchi 	char *dpassarg;
2555a233072Sinoguchi 	int enable_timeouts;
2565a233072Sinoguchi 	const char *errstr;
2575a233072Sinoguchi 	char *groups_in;
2580e15fe22Sinoguchi 	char *key_file;
2590e15fe22Sinoguchi 	char *key_file2;
2600e15fe22Sinoguchi 	int key_format;
2615a233072Sinoguchi 	char *keymatexportlabel;
2625a233072Sinoguchi 	int keymatexportlen;
2635a233072Sinoguchi 	uint16_t max_version;
2645a233072Sinoguchi 	uint16_t min_version;
2655a233072Sinoguchi 	const SSL_METHOD *meth;
2660e15fe22Sinoguchi 	int msg;
26713017aedStb 	int naccept;
2685a233072Sinoguchi 	char *named_curve;
2690e15fe22Sinoguchi 	int nbio;
2700e15fe22Sinoguchi 	int nbio_test;
2715a233072Sinoguchi 	int no_cache;
2725a233072Sinoguchi 	int nocert;
2735a233072Sinoguchi 	int no_dhe;
2745a233072Sinoguchi 	int no_ecdhe;
2755a233072Sinoguchi 	int no_tmp_rsa; /* No-op. */
2765a233072Sinoguchi 	int off;
2775a233072Sinoguchi 	char *passarg;
2785a233072Sinoguchi 	short port;
2790e15fe22Sinoguchi 	int quiet;
2800e15fe22Sinoguchi 	int server_verify;
2815a233072Sinoguchi 	char *session_id_prefix;
2825a233072Sinoguchi 	long socket_mtu;
2835a233072Sinoguchi 	int socket_type;
2845a233072Sinoguchi #ifndef OPENSSL_NO_SRTP
2855a233072Sinoguchi 	char *srtp_profiles;
2865a233072Sinoguchi #endif
2875a233072Sinoguchi 	int state;
2885a233072Sinoguchi 	tlsextstatusctx tlscstatp;
2895a233072Sinoguchi 	tlsextctx tlsextcbp;
2900e15fe22Sinoguchi 	int tlsextdebug;
2910e15fe22Sinoguchi 	int tlsextstatus;
2925a233072Sinoguchi 	X509_VERIFY_PARAM *vpm;
2935a233072Sinoguchi 	int www;
294e7718adaStb } cfg;
2955a233072Sinoguchi 
2965a233072Sinoguchi static int
2975a233072Sinoguchi s_server_opt_context(char *arg)
2985a233072Sinoguchi {
299e7718adaStb 	cfg.context = (unsigned char *) arg;
3005a233072Sinoguchi 	return (0);
3015a233072Sinoguchi }
3025a233072Sinoguchi 
3035a233072Sinoguchi static int
3045a233072Sinoguchi s_server_opt_keymatexportlen(char *arg)
3055a233072Sinoguchi {
306e7718adaStb 	cfg.keymatexportlen = strtonum(arg, 1, INT_MAX,
307e7718adaStb 	    &cfg.errstr);
308e7718adaStb 	if (cfg.errstr != NULL) {
3095a233072Sinoguchi 		BIO_printf(bio_err, "invalid argument %s: %s\n",
310e7718adaStb 		    arg, cfg.errstr);
3115a233072Sinoguchi 		return (1);
3125a233072Sinoguchi 	}
3135a233072Sinoguchi 	return (0);
3145a233072Sinoguchi }
3155a233072Sinoguchi 
31693dafd19Sjsing #ifndef OPENSSL_NO_DTLS
3175a233072Sinoguchi static int
3185a233072Sinoguchi s_server_opt_mtu(char *arg)
3195a233072Sinoguchi {
320e7718adaStb 	cfg.socket_mtu = strtonum(arg, 0, LONG_MAX,
321e7718adaStb 	    &cfg.errstr);
322e7718adaStb 	if (cfg.errstr != NULL) {
3235a233072Sinoguchi 		BIO_printf(bio_err, "invalid argument %s: %s\n",
324e7718adaStb 		    arg, cfg.errstr);
3255a233072Sinoguchi 		return (1);
3265a233072Sinoguchi 	}
3275a233072Sinoguchi 	return (0);
3285a233072Sinoguchi }
32993dafd19Sjsing #endif
3305a233072Sinoguchi 
33193dafd19Sjsing #ifndef OPENSSL_NO_DTLS
3325a233072Sinoguchi static int
33393dafd19Sjsing s_server_opt_protocol_version_dtls(void)
3345a233072Sinoguchi {
335e7718adaStb 	cfg.meth = DTLS_server_method();
336e7718adaStb 	cfg.socket_type = SOCK_DGRAM;
3375a233072Sinoguchi 	return (0);
3385a233072Sinoguchi }
3395a233072Sinoguchi #endif
3405a233072Sinoguchi 
34193dafd19Sjsing #ifndef OPENSSL_NO_DTLS1_2
34293dafd19Sjsing static int
34393dafd19Sjsing s_server_opt_protocol_version_dtls1_2(void)
34493dafd19Sjsing {
345e7718adaStb 	cfg.meth = DTLS_server_method();
346e7718adaStb 	cfg.min_version = DTLS1_2_VERSION;
347e7718adaStb 	cfg.max_version = DTLS1_2_VERSION;
348e7718adaStb 	cfg.socket_type = SOCK_DGRAM;
34993dafd19Sjsing 	return (0);
35093dafd19Sjsing }
35193dafd19Sjsing #endif
35293dafd19Sjsing 
3535a233072Sinoguchi static int
35435ffcbeaSjsing s_server_opt_protocol_version_tls1_2(void)
3555a233072Sinoguchi {
356e7718adaStb 	cfg.min_version = TLS1_2_VERSION;
357e7718adaStb 	cfg.max_version = TLS1_2_VERSION;
3585a233072Sinoguchi 	return (0);
3595a233072Sinoguchi }
3605a233072Sinoguchi 
3615a233072Sinoguchi static int
36235ffcbeaSjsing s_server_opt_protocol_version_tls1_3(void)
3635a233072Sinoguchi {
364e7718adaStb 	cfg.min_version = TLS1_3_VERSION;
365e7718adaStb 	cfg.max_version = TLS1_3_VERSION;
3665a233072Sinoguchi 	return (0);
3675a233072Sinoguchi }
3685a233072Sinoguchi 
3695a233072Sinoguchi static int
3705a233072Sinoguchi s_server_opt_nbio_test(void)
3715a233072Sinoguchi {
372e7718adaStb 	cfg.nbio = 1;
373e7718adaStb 	cfg.nbio_test = 1;
3745a233072Sinoguchi 	return (0);
3755a233072Sinoguchi }
3765a233072Sinoguchi 
3775a233072Sinoguchi static int
3785a233072Sinoguchi s_server_opt_port(char *arg)
3795a233072Sinoguchi {
380e7718adaStb 	if (!extract_port(arg, &cfg.port))
3815a233072Sinoguchi 		return (1);
3825a233072Sinoguchi 	return (0);
3835a233072Sinoguchi }
3845a233072Sinoguchi 
3855a233072Sinoguchi static int
3865a233072Sinoguchi s_server_opt_status_timeout(char *arg)
3875a233072Sinoguchi {
388e7718adaStb 	cfg.tlsextstatus = 1;
389e7718adaStb 	cfg.tlscstatp.timeout = strtonum(arg, 0, INT_MAX,
390e7718adaStb 	    &cfg.errstr);
391e7718adaStb 	if (cfg.errstr != NULL) {
3925a233072Sinoguchi 		BIO_printf(bio_err, "invalid argument %s: %s\n",
393e7718adaStb 		    arg, cfg.errstr);
3945a233072Sinoguchi 		return (1);
3955a233072Sinoguchi 	}
3965a233072Sinoguchi 	return (0);
3975a233072Sinoguchi }
3985a233072Sinoguchi 
3995a233072Sinoguchi static int
4005a233072Sinoguchi s_server_opt_status_url(char *arg)
4015a233072Sinoguchi {
402e7718adaStb 	cfg.tlsextstatus = 1;
403e7718adaStb 	if (!OCSP_parse_url(arg, &cfg.tlscstatp.host,
404e7718adaStb 	    &cfg.tlscstatp.port, &cfg.tlscstatp.path,
405e7718adaStb 	    &cfg.tlscstatp.use_ssl)) {
4065a233072Sinoguchi 		BIO_printf(bio_err, "Error parsing URL\n");
4075a233072Sinoguchi 		return (1);
4085a233072Sinoguchi 	}
4095a233072Sinoguchi 	return (0);
4105a233072Sinoguchi }
4115a233072Sinoguchi 
4125a233072Sinoguchi static int
4135a233072Sinoguchi s_server_opt_status_verbose(void)
4145a233072Sinoguchi {
415e7718adaStb 	cfg.tlsextstatus = 1;
416e7718adaStb 	cfg.tlscstatp.verbose = 1;
4175a233072Sinoguchi 	return (0);
4185a233072Sinoguchi }
4195a233072Sinoguchi 
4205a233072Sinoguchi static int
4215a233072Sinoguchi s_server_opt_verify(char *arg)
4225a233072Sinoguchi {
423e7718adaStb 	cfg.server_verify = SSL_VERIFY_PEER |
4245a233072Sinoguchi 	    SSL_VERIFY_CLIENT_ONCE;
425e7718adaStb 	verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr);
426e7718adaStb 	if (cfg.errstr != NULL) {
4275a233072Sinoguchi 		BIO_printf(bio_err, "invalid argument %s: %s\n",
428e7718adaStb 		    arg, cfg.errstr);
4295a233072Sinoguchi 		return (1);
4305a233072Sinoguchi 	}
4315a233072Sinoguchi 	BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
4325a233072Sinoguchi 	return (0);
4335a233072Sinoguchi }
4345a233072Sinoguchi 
4355a233072Sinoguchi static int
4365a233072Sinoguchi s_server_opt_verify_fail(char *arg)
4375a233072Sinoguchi {
438e7718adaStb 	cfg.server_verify = SSL_VERIFY_PEER |
4395a233072Sinoguchi 	    SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
440e7718adaStb 	verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr);
441e7718adaStb 	if (cfg.errstr != NULL) {
4425a233072Sinoguchi 		BIO_printf(bio_err, "invalid argument %s: %s\n",
443e7718adaStb 		    arg, cfg.errstr);
4445a233072Sinoguchi 		return (1);
4455a233072Sinoguchi 	}
4465a233072Sinoguchi 	BIO_printf(bio_err, "verify depth is %d, must return a certificate\n",
4475a233072Sinoguchi 	    verify_depth);
4485a233072Sinoguchi 	return (0);
4495a233072Sinoguchi }
4505a233072Sinoguchi 
4515a233072Sinoguchi static int
4525a233072Sinoguchi s_server_opt_verify_param(int argc, char **argv, int *argsused)
4535a233072Sinoguchi {
4545a233072Sinoguchi 	char **pargs = argv;
4555a233072Sinoguchi 	int pargc = argc;
4565a233072Sinoguchi 	int badarg = 0;
4575a233072Sinoguchi 
4585a233072Sinoguchi 	if (!args_verify(&pargs, &pargc, &badarg, bio_err,
459e7718adaStb 	    &cfg.vpm)) {
4605a233072Sinoguchi 		BIO_printf(bio_err, "unknown option %s\n", *argv);
4615a233072Sinoguchi 		return (1);
4625a233072Sinoguchi 	}
4635a233072Sinoguchi 	if (badarg)
4645a233072Sinoguchi 		return (1);
4655a233072Sinoguchi 
4665a233072Sinoguchi 	*argsused = argc - pargc;
4675a233072Sinoguchi 	return (0);
4685a233072Sinoguchi }
4695a233072Sinoguchi 
4705a233072Sinoguchi static const struct option s_server_options[] = {
4715a233072Sinoguchi 	{
47280b7bf82Stb 		.name = "4",
47380b7bf82Stb 		.type = OPTION_DISCARD,
47480b7bf82Stb 	},
47580b7bf82Stb 	{
47680b7bf82Stb 		.name = "6",
47780b7bf82Stb 		.type = OPTION_DISCARD,
47880b7bf82Stb 	},
47980b7bf82Stb 	{
4805a233072Sinoguchi 		.name = "accept",
4815a233072Sinoguchi 		.argname = "port",
4825a233072Sinoguchi 		.desc = "Port to accept on (default is 4433)",
4835a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
4845a233072Sinoguchi 		.opt.argfunc = s_server_opt_port,
4855a233072Sinoguchi 	},
4865a233072Sinoguchi 	{
4875a233072Sinoguchi 		.name = "alpn",
4885a233072Sinoguchi 		.argname = "protocols",
4895a233072Sinoguchi 		.desc = "Set the advertised protocols for the ALPN extension"
4905a233072Sinoguchi 			" (comma-separated list)",
4915a233072Sinoguchi 		.type = OPTION_ARG,
492e7718adaStb 		.opt.arg = &cfg.alpn_in,
4935a233072Sinoguchi 	},
4945a233072Sinoguchi 	{
4955a233072Sinoguchi 		.name = "bugs",
4965a233072Sinoguchi 		.desc = "Turn on SSL bug compatibility",
4975a233072Sinoguchi 		.type = OPTION_FLAG,
498e7718adaStb 		.opt.flag = &cfg.bugs,
4995a233072Sinoguchi 	},
5005a233072Sinoguchi 	{
5015a233072Sinoguchi 		.name = "CAfile",
5025a233072Sinoguchi 		.argname = "file",
5035a233072Sinoguchi 		.desc = "PEM format file of CA certificates",
5045a233072Sinoguchi 		.type = OPTION_ARG,
505e7718adaStb 		.opt.arg = &cfg.CAfile,
5065a233072Sinoguchi 	},
5075a233072Sinoguchi 	{
5085a233072Sinoguchi 		.name = "CApath",
5095a233072Sinoguchi 		.argname = "directory",
5105a233072Sinoguchi 		.desc = "PEM format directory of CA certificates",
5115a233072Sinoguchi 		.type = OPTION_ARG,
512e7718adaStb 		.opt.arg = &cfg.CApath,
5135a233072Sinoguchi 	},
5145a233072Sinoguchi 	{
5155a233072Sinoguchi 		.name = "cert",
5165a233072Sinoguchi 		.argname = "file",
5175a233072Sinoguchi 		.desc = "Certificate file to use\n"
5185a233072Sinoguchi 			"(default is " TEST_CERT ")",
5195a233072Sinoguchi 		.type = OPTION_ARG,
520e7718adaStb 		.opt.arg = &cfg.cert_file,
5215a233072Sinoguchi 	},
5225a233072Sinoguchi 	{
5235a233072Sinoguchi 		.name = "cert2",
5245a233072Sinoguchi 		.argname = "file",
5255a233072Sinoguchi 		.desc = "Certificate file to use for servername\n"
5265a233072Sinoguchi 			"(default is " TEST_CERT2 ")",
5275a233072Sinoguchi 		.type = OPTION_ARG,
528e7718adaStb 		.opt.arg = &cfg.cert_file2,
5295a233072Sinoguchi 	},
5305a233072Sinoguchi 	{
5315a233072Sinoguchi 		.name = "certform",
5325a233072Sinoguchi 		.argname = "fmt",
5335a233072Sinoguchi 		.desc = "Certificate format (PEM or DER) PEM default",
5345a233072Sinoguchi 		.type = OPTION_ARG_FORMAT,
535e7718adaStb 		.opt.value = &cfg.cert_format,
5365a233072Sinoguchi 	},
53793dafd19Sjsing #ifndef OPENSSL_NO_DTLS
5385a233072Sinoguchi 	{
5395a233072Sinoguchi 		.name = "chain",
5405a233072Sinoguchi 		.type = OPTION_FLAG,
541e7718adaStb 		.opt.flag = &cfg.cert_chain,
5425a233072Sinoguchi 	},
5435a233072Sinoguchi #endif
5445a233072Sinoguchi 	{
5455a233072Sinoguchi 		.name = "cipher",
5465a233072Sinoguchi 		.argname = "list",
5475a233072Sinoguchi 		.desc = "List of ciphers to enable (see `openssl ciphers`)",
5485a233072Sinoguchi 		.type = OPTION_ARG,
549e7718adaStb 		.opt.arg = &cfg.cipher,
5505a233072Sinoguchi 	},
5515a233072Sinoguchi 	{
5525a233072Sinoguchi 		.name = "context",
5535a233072Sinoguchi 		.argname = "id",
5545a233072Sinoguchi 		.desc = "Set session ID context",
5555a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
5565a233072Sinoguchi 		.opt.argfunc = s_server_opt_context,
5575a233072Sinoguchi 	},
5585a233072Sinoguchi 	{
5595a233072Sinoguchi 		.name = "crlf",
5605a233072Sinoguchi 		.desc = "Convert LF from terminal into CRLF",
5615a233072Sinoguchi 		.type = OPTION_FLAG,
562e7718adaStb 		.opt.flag = &cfg.crlf,
5635a233072Sinoguchi 	},
5645a233072Sinoguchi 	{
5655a233072Sinoguchi 		.name = "dcert",
5665a233072Sinoguchi 		.argname = "file",
5675a233072Sinoguchi 		.desc = "Second certificate file to use (usually for DSA)",
5685a233072Sinoguchi 		.type = OPTION_ARG,
569e7718adaStb 		.opt.arg = &cfg.dcert_file,
5705a233072Sinoguchi 	},
5715a233072Sinoguchi 	{
5725a233072Sinoguchi 		.name = "dcertform",
5735a233072Sinoguchi 		.argname = "fmt",
5745a233072Sinoguchi 		.desc = "Second certificate format (PEM or DER) PEM default",
5755a233072Sinoguchi 		.type = OPTION_ARG_FORMAT,
576e7718adaStb 		.opt.value = &cfg.dcert_format,
5775a233072Sinoguchi 	},
5785a233072Sinoguchi 	{
5795a233072Sinoguchi 		.name = "debug",
5805a233072Sinoguchi 		.desc = "Print more output",
5815a233072Sinoguchi 		.type = OPTION_FLAG,
582e7718adaStb 		.opt.flag = &cfg.debug,
5835a233072Sinoguchi 	},
5845a233072Sinoguchi 	{
5855a233072Sinoguchi 		.name = "dhparam",
5865a233072Sinoguchi 		.argname = "file",
5875a233072Sinoguchi 		.desc = "DH parameter file to use, in cert file if not specified",
5885a233072Sinoguchi 		.type = OPTION_ARG,
589e7718adaStb 		.opt.arg = &cfg.dhfile,
5905a233072Sinoguchi 	},
5915a233072Sinoguchi 	{
5925a233072Sinoguchi 		.name = "dkey",
5935a233072Sinoguchi 		.argname = "file",
5945a233072Sinoguchi 		.desc = "Second private key file to use (usually for DSA)",
5955a233072Sinoguchi 		.type = OPTION_ARG,
596e7718adaStb 		.opt.arg = &cfg.dkey_file,
5975a233072Sinoguchi 	},
5985a233072Sinoguchi 	{
5995a233072Sinoguchi 		.name = "dkeyform",
6005a233072Sinoguchi 		.argname = "fmt",
6015a233072Sinoguchi 		.desc = "Second key format (PEM or DER) PEM default",
6025a233072Sinoguchi 		.type = OPTION_ARG_FORMAT,
603e7718adaStb 		.opt.value = &cfg.dkey_format,
6045a233072Sinoguchi 	},
6055a233072Sinoguchi 	{
6065a233072Sinoguchi 		.name = "dpass",
6075a233072Sinoguchi 		.argname = "arg",
6085a233072Sinoguchi 		.desc = "Second private key file pass phrase source",
6095a233072Sinoguchi 		.type = OPTION_ARG,
610e7718adaStb 		.opt.arg = &cfg.dpassarg,
6115a233072Sinoguchi 	},
61293dafd19Sjsing #ifndef OPENSSL_NO_DTLS
61393dafd19Sjsing 	{
61493dafd19Sjsing 		.name = "dtls",
61593dafd19Sjsing 		.desc = "Use any version of DTLS",
61693dafd19Sjsing 		.type = OPTION_FUNC,
61793dafd19Sjsing 		.opt.func = s_server_opt_protocol_version_dtls,
61893dafd19Sjsing 	},
61993dafd19Sjsing #endif
62093dafd19Sjsing #ifndef OPENSSL_NO_DTLS1_2
62193dafd19Sjsing 	{
62293dafd19Sjsing 		.name = "dtls1_2",
62393dafd19Sjsing 		.desc = "Just use DTLSv1.2",
62493dafd19Sjsing 		.type = OPTION_FUNC,
62593dafd19Sjsing 		.opt.func = s_server_opt_protocol_version_dtls1_2,
6265a233072Sinoguchi 	},
6275a233072Sinoguchi #endif
6285a233072Sinoguchi 	{
6295a233072Sinoguchi 		.name = "groups",
6305a233072Sinoguchi 		.argname = "list",
6315a233072Sinoguchi 		.desc = "Specify EC groups (colon-separated list)",
6325a233072Sinoguchi 		.type = OPTION_ARG,
633e7718adaStb 		.opt.arg = &cfg.groups_in,
6345a233072Sinoguchi 	},
6355a233072Sinoguchi 	{
6365a233072Sinoguchi 		.name = "HTTP",
6375a233072Sinoguchi 		.desc = "Respond to a 'GET /<path> HTTP/1.0' with file ./<path>",
6385a233072Sinoguchi 		.type = OPTION_VALUE,
639e7718adaStb 		.opt.value = &cfg.www,
6405a233072Sinoguchi 		.value = 3,
6415a233072Sinoguchi 	},
6425a233072Sinoguchi 	{
6435a233072Sinoguchi 		.name = "id_prefix",
6445a233072Sinoguchi 		.argname = "arg",
6455a233072Sinoguchi 		.desc = "Generate SSL/TLS session IDs prefixed by 'arg'",
6465a233072Sinoguchi 		.type = OPTION_ARG,
647e7718adaStb 		.opt.arg = &cfg.session_id_prefix,
6485a233072Sinoguchi 	},
6495a233072Sinoguchi 	{
6505a233072Sinoguchi 		.name = "key",
6515a233072Sinoguchi 		.argname = "file",
6525a233072Sinoguchi 		.desc = "Private Key file to use, in cert file if\n"
6535a233072Sinoguchi 			"not specified (default is " TEST_CERT ")",
6545a233072Sinoguchi 		.type = OPTION_ARG,
655e7718adaStb 		.opt.arg = &cfg.key_file,
6565a233072Sinoguchi 	},
6575a233072Sinoguchi 	{
6585a233072Sinoguchi 		.name = "key2",
6595a233072Sinoguchi 		.argname = "file",
6605a233072Sinoguchi 		.desc = "Private Key file to use for servername, in cert file if\n"
6615a233072Sinoguchi 			"not specified (default is " TEST_CERT2 ")",
6625a233072Sinoguchi 		.type = OPTION_ARG,
663e7718adaStb 		.opt.arg = &cfg.key_file2,
6645a233072Sinoguchi 	},
6655a233072Sinoguchi 	{
6665a233072Sinoguchi 		.name = "keyform",
6675a233072Sinoguchi 		.argname = "fmt",
6685a233072Sinoguchi 		.desc = "Key format (PEM or DER) PEM default",
6695a233072Sinoguchi 		.type = OPTION_ARG_FORMAT,
670e7718adaStb 		.opt.value = &cfg.key_format,
6715a233072Sinoguchi 	},
6725a233072Sinoguchi 	{
6735a233072Sinoguchi 		.name = "keymatexport",
6745a233072Sinoguchi 		.argname = "label",
6755a233072Sinoguchi 		.desc = "Export keying material using label",
6765a233072Sinoguchi 		.type = OPTION_ARG,
677e7718adaStb 		.opt.arg = &cfg.keymatexportlabel,
6785a233072Sinoguchi 	},
6795a233072Sinoguchi 	{
6805a233072Sinoguchi 		.name = "keymatexportlen",
6815a233072Sinoguchi 		.argname = "len",
6825a233072Sinoguchi 		.desc = "Export len bytes of keying material (default 20)",
6835a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
6845a233072Sinoguchi 		.opt.argfunc = s_server_opt_keymatexportlen,
6855a233072Sinoguchi 	},
6865a233072Sinoguchi 	{
6875a233072Sinoguchi 		.name = "legacy_renegotiation",
6885a233072Sinoguchi 		.type = OPTION_DISCARD,
6895a233072Sinoguchi 	},
6905a233072Sinoguchi 	{
6915a233072Sinoguchi 		.name = "msg",
6925a233072Sinoguchi 		.desc = "Show protocol messages",
6935a233072Sinoguchi 		.type = OPTION_FLAG,
694e7718adaStb 		.opt.flag = &cfg.msg,
6955a233072Sinoguchi 	},
69693dafd19Sjsing #ifndef OPENSSL_NO_DTLS
6975a233072Sinoguchi 	{
6985a233072Sinoguchi 		.name = "mtu",
6995a233072Sinoguchi 		.argname = "mtu",
7005a233072Sinoguchi 		.desc = "Set link layer MTU",
7015a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
7025a233072Sinoguchi 		.opt.argfunc = s_server_opt_mtu,
7035a233072Sinoguchi 	},
7045a233072Sinoguchi #endif
7055a233072Sinoguchi 	{
70613017aedStb 		.name = "naccept",
70713017aedStb 		.argname = "num",
708a574f8cbStb 		.desc = "Terminate after num connections",
70913017aedStb 		.type = OPTION_ARG_INT,
710e7718adaStb 		.opt.value = &cfg.naccept
71113017aedStb 	},
71213017aedStb 	{
7135a233072Sinoguchi 		.name = "named_curve",
7145a233072Sinoguchi 		.argname = "arg",
7155a233072Sinoguchi 		.type = OPTION_ARG,
716e7718adaStb 		.opt.arg = &cfg.named_curve,
7175a233072Sinoguchi 	},
7185a233072Sinoguchi 	{
7195a233072Sinoguchi 		.name = "nbio",
7205a233072Sinoguchi 		.desc = "Run with non-blocking I/O",
7215a233072Sinoguchi 		.type = OPTION_FLAG,
722e7718adaStb 		.opt.flag = &cfg.nbio,
7235a233072Sinoguchi 	},
7245a233072Sinoguchi 	{
7255a233072Sinoguchi 		.name = "nbio_test",
7265a233072Sinoguchi 		.desc = "Test with the non-blocking test bio",
7275a233072Sinoguchi 		.type = OPTION_FUNC,
7285a233072Sinoguchi 		.opt.func = s_server_opt_nbio_test,
7295a233072Sinoguchi 	},
7305a233072Sinoguchi 	{
7315a233072Sinoguchi 		.name = "nextprotoneg",
7325a233072Sinoguchi 		.argname = "arg",
7335a233072Sinoguchi 		.type = OPTION_ARG,
734e7718adaStb 		.opt.arg = &cfg.npn_in, /* Ignored. */
7355a233072Sinoguchi 	},
7365a233072Sinoguchi 	{
7375a233072Sinoguchi 		.name = "no_cache",
7385a233072Sinoguchi 		.desc = "Disable session cache",
7395a233072Sinoguchi 		.type = OPTION_FLAG,
740e7718adaStb 		.opt.flag = &cfg.no_cache,
7415a233072Sinoguchi 	},
7425a233072Sinoguchi 	{
7435a233072Sinoguchi 		.name = "no_comp",
7445a233072Sinoguchi 		.desc = "Disable SSL/TLS compression",
7455a233072Sinoguchi 		.type = OPTION_VALUE_OR,
746e7718adaStb 		.opt.value = &cfg.off,
7475a233072Sinoguchi 		.value = SSL_OP_NO_COMPRESSION,
7485a233072Sinoguchi 	},
7495a233072Sinoguchi 	{
7505a233072Sinoguchi 		.name = "no_dhe",
7515a233072Sinoguchi 		.desc = "Disable ephemeral DH",
7525a233072Sinoguchi 		.type = OPTION_FLAG,
753e7718adaStb 		.opt.flag = &cfg.no_dhe,
7545a233072Sinoguchi 	},
7555a233072Sinoguchi 	{
7565a233072Sinoguchi 		.name = "no_ecdhe",
7575a233072Sinoguchi 		.desc = "Disable ephemeral ECDH",
7585a233072Sinoguchi 		.type = OPTION_FLAG,
759e7718adaStb 		.opt.flag = &cfg.no_ecdhe,
7605a233072Sinoguchi 	},
7615a233072Sinoguchi 	{
7625a233072Sinoguchi 		.name = "no_ticket",
7635a233072Sinoguchi 		.desc = "Disable use of RFC4507bis session tickets",
7645a233072Sinoguchi 		.type = OPTION_VALUE_OR,
765e7718adaStb 		.opt.value = &cfg.off,
7665a233072Sinoguchi 		.value = SSL_OP_NO_TICKET,
7675a233072Sinoguchi 	},
7685a233072Sinoguchi 	{
7695a233072Sinoguchi 		.name = "no_ssl2",
770b5c24d4fSbeck 		.type = OPTION_DISCARD,
7715a233072Sinoguchi 	},
7725a233072Sinoguchi 	{
7735a233072Sinoguchi 		.name = "no_ssl3",
774b5c24d4fSbeck 		.type = OPTION_DISCARD,
775b5c24d4fSbeck 	},
776b5c24d4fSbeck 	{
777b5c24d4fSbeck 		.name = "no_tls1",
778b5c24d4fSbeck 		.type = OPTION_DISCARD,
779b5c24d4fSbeck 	},
780b5c24d4fSbeck 	{
781b5c24d4fSbeck 		.name = "no_tls1_1",
782b5c24d4fSbeck 		.type = OPTION_DISCARD,
7835a233072Sinoguchi 	},
7845a233072Sinoguchi 	{
7855a233072Sinoguchi 		.name = "no_tls1_2",
7865a233072Sinoguchi 		.desc = "Just disable TLSv1.2",
7875a233072Sinoguchi 		.type = OPTION_VALUE_OR,
788e7718adaStb 		.opt.value = &cfg.off,
7895a233072Sinoguchi 		.value = SSL_OP_NO_TLSv1_2,
7905a233072Sinoguchi 	},
7915a233072Sinoguchi 	{
7925a233072Sinoguchi 		.name = "no_tls1_3",
7935a233072Sinoguchi 		.desc = "Just disable TLSv1.3",
7945a233072Sinoguchi 		.type = OPTION_VALUE_OR,
795e7718adaStb 		.opt.value = &cfg.off,
7965a233072Sinoguchi 		.value = SSL_OP_NO_TLSv1_3,
7975a233072Sinoguchi 	},
7985a233072Sinoguchi 	{
7995a233072Sinoguchi 		.name = "no_tmp_rsa",
8005a233072Sinoguchi 		.type = OPTION_DISCARD,
8015a233072Sinoguchi 	},
8025a233072Sinoguchi 	{
8035a233072Sinoguchi 		.name = "nocert",
8045a233072Sinoguchi 		.desc = "Don't use any certificates (Anon-DH)",
8055a233072Sinoguchi 		.type = OPTION_FLAG,
806e7718adaStb 		.opt.flag = &cfg.nocert,
8075a233072Sinoguchi 	},
8085a233072Sinoguchi 	{
8095a233072Sinoguchi 		.name = "pass",
8105a233072Sinoguchi 		.argname = "arg",
8115a233072Sinoguchi 		.desc = "Private key file pass phrase source",
8125a233072Sinoguchi 		.type = OPTION_ARG,
813e7718adaStb 		.opt.arg = &cfg.passarg,
8145a233072Sinoguchi 	},
8155a233072Sinoguchi 	{
8165a233072Sinoguchi 		.name = "port",
8175a233072Sinoguchi 		.argname = "port",
8185a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
8195a233072Sinoguchi 		.opt.argfunc = s_server_opt_port,
8205a233072Sinoguchi 	},
8215a233072Sinoguchi 	{
8225a233072Sinoguchi 		.name = "quiet",
8235a233072Sinoguchi 		.desc = "Inhibit printing of session and certificate information",
8245a233072Sinoguchi 		.type = OPTION_FLAG,
825e7718adaStb 		.opt.flag = &cfg.quiet,
8265a233072Sinoguchi 	},
8275a233072Sinoguchi 	{
8285a233072Sinoguchi 		.name = "servername",
8295a233072Sinoguchi 		.argname = "name",
8305a233072Sinoguchi 		.desc = "Servername for HostName TLS extension",
8315a233072Sinoguchi 		.type = OPTION_ARG,
832e7718adaStb 		.opt.arg = &cfg.tlsextcbp.servername,
8335a233072Sinoguchi 	},
8345a233072Sinoguchi 	{
8355a233072Sinoguchi 		.name = "servername_fatal",
8365a233072Sinoguchi 		.desc = "On mismatch send fatal alert (default warning alert)",
8375a233072Sinoguchi 		.type = OPTION_VALUE,
838e7718adaStb 		.opt.value = &cfg.tlsextcbp.extension_error,
8395a233072Sinoguchi 		.value = SSL_TLSEXT_ERR_ALERT_FATAL,
8405a233072Sinoguchi 	},
8415a233072Sinoguchi 	{
8425a233072Sinoguchi 		.name = "serverpref",
8435a233072Sinoguchi 		.desc = "Use server's cipher preferences",
8445a233072Sinoguchi 		.type = OPTION_VALUE_OR,
845e7718adaStb 		.opt.value = &cfg.off,
8465a233072Sinoguchi 		.value = SSL_OP_CIPHER_SERVER_PREFERENCE,
8475a233072Sinoguchi 	},
8485a233072Sinoguchi 	{
8495a233072Sinoguchi 		.name = "state",
8505a233072Sinoguchi 		.desc = "Print the SSL states",
8515a233072Sinoguchi 		.type = OPTION_FLAG,
852e7718adaStb 		.opt.flag = &cfg.state,
8535a233072Sinoguchi 	},
8545a233072Sinoguchi 	{
8555a233072Sinoguchi 		.name = "status",
8565a233072Sinoguchi 		.desc = "Respond to certificate status requests",
8575a233072Sinoguchi 		.type = OPTION_FLAG,
858e7718adaStb 		.opt.flag = &cfg.tlsextstatus,
8595a233072Sinoguchi 	},
8605a233072Sinoguchi 	{
8615a233072Sinoguchi 		.name = "status_timeout",
8625a233072Sinoguchi 		.argname = "nsec",
8635a233072Sinoguchi 		.desc = "Status request responder timeout",
8645a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
8655a233072Sinoguchi 		.opt.argfunc = s_server_opt_status_timeout,
8665a233072Sinoguchi 	},
8675a233072Sinoguchi 	{
8685a233072Sinoguchi 		.name = "status_url",
8695a233072Sinoguchi 		.argname = "url",
8705a233072Sinoguchi 		.desc = "Status request fallback URL",
8715a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
8725a233072Sinoguchi 		.opt.argfunc = s_server_opt_status_url,
8735a233072Sinoguchi 	},
8745a233072Sinoguchi 	{
8755a233072Sinoguchi 		.name = "status_verbose",
8765a233072Sinoguchi 		.desc = "Enable status request verbose printout",
8775a233072Sinoguchi 		.type = OPTION_FUNC,
8785a233072Sinoguchi 		.opt.func = s_server_opt_status_verbose,
8795a233072Sinoguchi 	},
88093dafd19Sjsing #ifndef OPENSSL_NO_DTLS
8815a233072Sinoguchi 	{
8825a233072Sinoguchi 		.name = "timeout",
8835a233072Sinoguchi 		.desc = "Enable timeouts",
8845a233072Sinoguchi 		.type = OPTION_FLAG,
885e7718adaStb 		.opt.flag = &cfg.enable_timeouts,
8865a233072Sinoguchi 	},
8875a233072Sinoguchi #endif
8885a233072Sinoguchi 	{
8895a233072Sinoguchi 		.name = "tls1_2",
8905a233072Sinoguchi 		.desc = "Just talk TLSv1.2",
8915a233072Sinoguchi 		.type = OPTION_FUNC,
89235ffcbeaSjsing 		.opt.func = s_server_opt_protocol_version_tls1_2,
8935a233072Sinoguchi 	},
8945a233072Sinoguchi 	{
8955a233072Sinoguchi 		.name = "tls1_3",
8965a233072Sinoguchi 		.desc = "Just talk TLSv1.3",
8975a233072Sinoguchi 		.type = OPTION_FUNC,
89835ffcbeaSjsing 		.opt.func = s_server_opt_protocol_version_tls1_3,
8995a233072Sinoguchi 	},
9005a233072Sinoguchi 	{
9015a233072Sinoguchi 		.name = "tlsextdebug",
9025a233072Sinoguchi 		.desc = "Hex dump of all TLS extensions received",
9035a233072Sinoguchi 		.type = OPTION_FLAG,
904e7718adaStb 		.opt.flag = &cfg.tlsextdebug,
9055a233072Sinoguchi 	},
9065a233072Sinoguchi #ifndef OPENSSL_NO_SRTP
9075a233072Sinoguchi 	{
9085a233072Sinoguchi 		.name = "use_srtp",
9095a233072Sinoguchi 		.argname = "profiles",
9105a233072Sinoguchi 		.desc = "Offer SRTP key management with a colon-separated profile list",
9115a233072Sinoguchi 		.type = OPTION_ARG,
912e7718adaStb 		.opt.arg = &cfg.srtp_profiles,
9135a233072Sinoguchi 	},
9145a233072Sinoguchi #endif
9155a233072Sinoguchi 	{
9165a233072Sinoguchi 		.name = "Verify",
9175a233072Sinoguchi 		.argname = "depth",
9185a233072Sinoguchi 		.desc = "Turn on peer certificate verification, must have a cert",
9195a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
9205a233072Sinoguchi 		.opt.argfunc = s_server_opt_verify_fail,
9215a233072Sinoguchi 	},
9225a233072Sinoguchi 	{
9235a233072Sinoguchi 		.name = "verify",
9245a233072Sinoguchi 		.argname = "depth",
9255a233072Sinoguchi 		.desc = "Turn on peer certificate verification",
9265a233072Sinoguchi 		.type = OPTION_ARG_FUNC,
9275a233072Sinoguchi 		.opt.argfunc = s_server_opt_verify,
9285a233072Sinoguchi 	},
9295a233072Sinoguchi 	{
9305a233072Sinoguchi 		.name = "verify_return_error",
9315a233072Sinoguchi 		.desc = "Return verification error",
9325a233072Sinoguchi 		.type = OPTION_FLAG,
9335a233072Sinoguchi 		.opt.flag = &verify_return_error,
9345a233072Sinoguchi 	},
9355a233072Sinoguchi 	{
9365a233072Sinoguchi 		.name = "WWW",
9375a233072Sinoguchi 		.desc = "Respond to a 'GET /<path> HTTP/1.0' with file ./<path>",
9385a233072Sinoguchi 		.type = OPTION_VALUE,
939e7718adaStb 		.opt.value = &cfg.www,
9405a233072Sinoguchi 		.value = 2,
9415a233072Sinoguchi 	},
9425a233072Sinoguchi 	{
9435a233072Sinoguchi 		.name = "www",
9445a233072Sinoguchi 		.desc = "Respond to a 'GET /' with a status page",
9455a233072Sinoguchi 		.type = OPTION_VALUE,
946e7718adaStb 		.opt.value = &cfg.www,
9475a233072Sinoguchi 		.value = 1,
9485a233072Sinoguchi 	},
9495a233072Sinoguchi 	{
9505a233072Sinoguchi 		.name = NULL,
9515a233072Sinoguchi 		.desc = "",
9525a233072Sinoguchi 		.type = OPTION_ARGV_FUNC,
9535a233072Sinoguchi 		.opt.argvfunc = s_server_opt_verify_param,
9545a233072Sinoguchi 	},
9555a233072Sinoguchi 	{ NULL },
9565a233072Sinoguchi };
9575a233072Sinoguchi 
9585a233072Sinoguchi static void
9595a233072Sinoguchi s_server_init(void)
9605a233072Sinoguchi {
9615a233072Sinoguchi 	accept_socket = -1;
962e7718adaStb 	cfg.cipher = NULL;
963e7718adaStb 	cfg.server_verify = SSL_VERIFY_NONE;
964e7718adaStb 	cfg.dcert_file = NULL;
965e7718adaStb 	cfg.dkey_file = NULL;
966e7718adaStb 	cfg.cert_file = TEST_CERT;
967e7718adaStb 	cfg.key_file = NULL;
968e7718adaStb 	cfg.cert_file2 = TEST_CERT2;
969e7718adaStb 	cfg.key_file2 = NULL;
9705a233072Sinoguchi 	ctx2 = NULL;
971e7718adaStb 	cfg.nbio = 0;
972e7718adaStb 	cfg.nbio_test = 0;
9735a233072Sinoguchi 	ctx = NULL;
974e7718adaStb 	cfg.www = 0;
9755a233072Sinoguchi 
9765a233072Sinoguchi 	bio_s_out = NULL;
977e7718adaStb 	cfg.debug = 0;
978e7718adaStb 	cfg.msg = 0;
979e7718adaStb 	cfg.quiet = 0;
9805a233072Sinoguchi }
9815a233072Sinoguchi 
9825a233072Sinoguchi static void
9835a233072Sinoguchi sv_usage(void)
9845a233072Sinoguchi {
9855a233072Sinoguchi 	fprintf(stderr, "usage: s_server "
9865a233072Sinoguchi 	    "[-accept port] [-alpn protocols] [-bugs] [-CAfile file]\n"
9875a233072Sinoguchi 	    "    [-CApath directory] [-cert file] [-cert2 file]\n"
9885a233072Sinoguchi 	    "    [-certform der | pem] [-cipher cipherlist]\n"
9895a233072Sinoguchi 	    "    [-context id] [-crl_check] [-crl_check_all] [-crlf]\n"
9905a233072Sinoguchi 	    "    [-dcert file] [-dcertform der | pem] [-debug]\n"
9915a233072Sinoguchi 	    "    [-dhparam file] [-dkey file] [-dkeyform der | pem]\n"
99291e7614aSbeck 	    "    [-dpass arg] [-dtls] [-dtls1_2] [-groups list] [-HTTP]\n"
9935a233072Sinoguchi 	    "    [-id_prefix arg] [-key keyfile] [-key2 keyfile]\n"
9945a233072Sinoguchi 	    "    [-keyform der | pem] [-keymatexport label]\n"
99513017aedStb 	    "    [-keymatexportlen len] [-msg] [-mtu mtu] [-naccept num]\n"
9965a233072Sinoguchi 	    "    [-named_curve arg] [-nbio] [-nbio_test] [-no_cache]\n"
99791e7614aSbeck 	    "    [-no_dhe] [-no_ecdhe] [-no_ticket] \n"
99891e7614aSbeck 	    "    [-no_tls1_2] [-no_tls1_3] [-no_tmp_rsa]\n"
9995a233072Sinoguchi 	    "    [-nocert] [-pass arg] [-quiet] [-servername name]\n"
10005a233072Sinoguchi 	    "    [-servername_fatal] [-serverpref] [-state] [-status]\n"
10015a233072Sinoguchi 	    "    [-status_timeout nsec] [-status_url url]\n"
100291e7614aSbeck 	    "    [-status_verbose] [-timeout] \n"
10035a233072Sinoguchi 	    "    [-tls1_2] [-tls1_3] [-tlsextdebug] [-use_srtp profiles]\n"
10045a233072Sinoguchi 	    "    [-Verify depth] [-verify depth] [-verify_return_error]\n"
10055a233072Sinoguchi 	    "    [-WWW] [-www]\n");
10065a233072Sinoguchi 	fprintf(stderr, "\n");
10075a233072Sinoguchi 	options_usage(s_server_options);
10085a233072Sinoguchi 	fprintf(stderr, "\n");
10095a233072Sinoguchi }
10105a233072Sinoguchi 
1011dab3f910Sjsing int
1012dab3f910Sjsing s_server_main(int argc, char *argv[])
1013dab3f910Sjsing {
1014dab3f910Sjsing 	int ret = 1;
10155a233072Sinoguchi 	char *pass = NULL;
10165a233072Sinoguchi 	char *dpass = NULL;
1017dab3f910Sjsing 	X509 *s_cert = NULL, *s_dcert = NULL;
1018dab3f910Sjsing 	EVP_PKEY *s_key = NULL, *s_dkey = NULL;
1019dab3f910Sjsing 	EVP_PKEY *s_key2 = NULL;
1020dab3f910Sjsing 	X509 *s_cert2 = NULL;
10211b4c9cadSjsing 	tlsextalpnctx alpn_ctx = { NULL, 0 };
10229bc487adSdoug 
102351811eadSderaadt 	if (pledge("stdio rpath inet dns tty", NULL) == -1) {
10249bc487adSdoug 		perror("pledge");
1025e370f0eeSdoug 		exit(1);
1026e370f0eeSdoug 	}
10279bc487adSdoug 
1028e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
1029e7718adaStb 	cfg.keymatexportlen = 20;
1030e7718adaStb 	cfg.meth = TLS_server_method();
1031e7718adaStb 	cfg.naccept = -1;
1032e7718adaStb 	cfg.port = PORT;
1033e7718adaStb 	cfg.cert_file = TEST_CERT;
1034e7718adaStb 	cfg.cert_file2 = TEST_CERT2;
1035e7718adaStb 	cfg.cert_format = FORMAT_PEM;
1036e7718adaStb 	cfg.dcert_format = FORMAT_PEM;
1037e7718adaStb 	cfg.dkey_format = FORMAT_PEM;
1038e7718adaStb 	cfg.key_format = FORMAT_PEM;
1039e7718adaStb 	cfg.server_verify = SSL_VERIFY_NONE;
1040e7718adaStb 	cfg.socket_type = SOCK_STREAM;
1041e7718adaStb 	cfg.tlscstatp.timeout = -1;
1042e7718adaStb 	cfg.tlsextcbp.extension_error =
10434da86b84Sinoguchi 	    SSL_TLSEXT_ERR_ALERT_WARNING;
1044dab3f910Sjsing 
1045dab3f910Sjsing 	local_argc = argc;
1046dab3f910Sjsing 	local_argv = argv;
1047dab3f910Sjsing 
1048dab3f910Sjsing 	s_server_init();
1049dab3f910Sjsing 
1050dab3f910Sjsing 	verify_depth = 0;
1051dab3f910Sjsing 
10525a233072Sinoguchi 	if (options_parse(argc, argv, s_server_options, NULL, NULL) != 0) {
1053e7718adaStb 		if (cfg.errstr == NULL)
1054dab3f910Sjsing 			sv_usage();
1055dab3f910Sjsing 		goto end;
1056dab3f910Sjsing 	}
1057dab3f910Sjsing 
1058e7718adaStb 	if (!app_passwd(bio_err, cfg.passarg,
1059e7718adaStb 	    cfg.dpassarg, &pass, &dpass)) {
1060dab3f910Sjsing 		BIO_printf(bio_err, "Error getting password\n");
1061dab3f910Sjsing 		goto end;
1062dab3f910Sjsing 	}
1063e7718adaStb 	if (cfg.key_file == NULL)
1064e7718adaStb 		cfg.key_file = cfg.cert_file;
1065e7718adaStb 	if (cfg.key_file2 == NULL)
1066e7718adaStb 		cfg.key_file2 = cfg.cert_file2;
1067dab3f910Sjsing 
1068e7718adaStb 	if (cfg.nocert == 0) {
1069e7718adaStb 		s_key = load_key(bio_err, cfg.key_file,
1070e7718adaStb 		    cfg.key_format, 0, pass,
1071dab3f910Sjsing 		    "server certificate private key file");
1072dab3f910Sjsing 		if (!s_key) {
1073dab3f910Sjsing 			ERR_print_errors(bio_err);
1074dab3f910Sjsing 			goto end;
1075dab3f910Sjsing 		}
1076e7718adaStb 		s_cert = load_cert(bio_err, cfg.cert_file,
1077e7718adaStb 		    cfg.cert_format,
10785284dfeaSbcook 		    NULL, "server certificate file");
1079dab3f910Sjsing 
1080dab3f910Sjsing 		if (!s_cert) {
1081dab3f910Sjsing 			ERR_print_errors(bio_err);
1082dab3f910Sjsing 			goto end;
1083dab3f910Sjsing 		}
1084e7718adaStb 		if (cfg.tlsextcbp.servername) {
1085e7718adaStb 			s_key2 = load_key(bio_err, cfg.key_file2,
1086e7718adaStb 			    cfg.key_format, 0, pass,
1087dab3f910Sjsing 			    "second server certificate private key file");
1088dab3f910Sjsing 			if (!s_key2) {
1089dab3f910Sjsing 				ERR_print_errors(bio_err);
1090dab3f910Sjsing 				goto end;
1091dab3f910Sjsing 			}
1092e7718adaStb 			s_cert2 = load_cert(bio_err, cfg.cert_file2,
1093e7718adaStb 			    cfg.cert_format,
10945284dfeaSbcook 			    NULL, "second server certificate file");
1095dab3f910Sjsing 
1096dab3f910Sjsing 			if (!s_cert2) {
1097dab3f910Sjsing 				ERR_print_errors(bio_err);
1098dab3f910Sjsing 				goto end;
1099dab3f910Sjsing 			}
1100dab3f910Sjsing 		}
1101dab3f910Sjsing 	}
11021b4c9cadSjsing 	alpn_ctx.data = NULL;
1103e7718adaStb 	if (cfg.alpn_in) {
11041b4c9cadSjsing 		unsigned short len;
11054da86b84Sinoguchi 		alpn_ctx.data = next_protos_parse(&len,
1106e7718adaStb 		    cfg.alpn_in);
11071b4c9cadSjsing 		if (alpn_ctx.data == NULL)
11081b4c9cadSjsing 			goto end;
11091b4c9cadSjsing 		alpn_ctx.len = len;
11101b4c9cadSjsing 	}
1111dab3f910Sjsing 
1112e7718adaStb 	if (cfg.dcert_file) {
1113dab3f910Sjsing 
1114e7718adaStb 		if (cfg.dkey_file == NULL)
1115e7718adaStb 			cfg.dkey_file = cfg.dcert_file;
1116dab3f910Sjsing 
1117e7718adaStb 		s_dkey = load_key(bio_err, cfg.dkey_file,
1118e7718adaStb 		    cfg.dkey_format,
11195284dfeaSbcook 		    0, dpass, "second certificate private key file");
1120dab3f910Sjsing 		if (!s_dkey) {
1121dab3f910Sjsing 			ERR_print_errors(bio_err);
1122dab3f910Sjsing 			goto end;
1123dab3f910Sjsing 		}
1124e7718adaStb 		s_dcert = load_cert(bio_err, cfg.dcert_file,
1125e7718adaStb 		    cfg.dcert_format,
11265284dfeaSbcook 		    NULL, "second server certificate file");
1127dab3f910Sjsing 
1128dab3f910Sjsing 		if (!s_dcert) {
1129dab3f910Sjsing 			ERR_print_errors(bio_err);
1130dab3f910Sjsing 			goto end;
1131dab3f910Sjsing 		}
1132dab3f910Sjsing 	}
1133dab3f910Sjsing 	if (bio_s_out == NULL) {
1134e7718adaStb 		if (cfg.quiet && !cfg.debug &&
1135e7718adaStb 		    !cfg.msg) {
1136dab3f910Sjsing 			bio_s_out = BIO_new(BIO_s_null());
1137dab3f910Sjsing 		} else {
1138dab3f910Sjsing 			if (bio_s_out == NULL)
1139dab3f910Sjsing 				bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE);
1140dab3f910Sjsing 		}
1141dab3f910Sjsing 	}
1142e7718adaStb 	if (cfg.nocert) {
1143e7718adaStb 		cfg.cert_file = NULL;
1144e7718adaStb 		cfg.key_file = NULL;
1145e7718adaStb 		cfg.dcert_file = NULL;
1146e7718adaStb 		cfg.dkey_file = NULL;
1147e7718adaStb 		cfg.cert_file2 = NULL;
1148e7718adaStb 		cfg.key_file2 = NULL;
1149dab3f910Sjsing 	}
1150e7718adaStb 	ctx = SSL_CTX_new(cfg.meth);
1151dab3f910Sjsing 	if (ctx == NULL) {
1152dab3f910Sjsing 		ERR_print_errors(bio_err);
1153dab3f910Sjsing 		goto end;
1154dab3f910Sjsing 	}
115595f83488Sinoguchi 
1156f4cc3564Stb 	SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
1157f4cc3564Stb 
1158e7718adaStb 	if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version))
115995f83488Sinoguchi 		goto end;
1160e7718adaStb 	if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version))
116195f83488Sinoguchi 		goto end;
116295f83488Sinoguchi 
1163e7718adaStb 	if (cfg.session_id_prefix) {
1164e7718adaStb 		if (strlen(cfg.session_id_prefix) >= 32)
1165dab3f910Sjsing 			BIO_printf(bio_err,
1166dab3f910Sjsing 			    "warning: id_prefix is too long, only one new session will be possible\n");
1167e7718adaStb 		else if (strlen(cfg.session_id_prefix) >= 16)
1168dab3f910Sjsing 			BIO_printf(bio_err,
1169dab3f910Sjsing 			    "warning: id_prefix is too long if you use SSLv2\n");
1170dab3f910Sjsing 		if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) {
1171dab3f910Sjsing 			BIO_printf(bio_err, "error setting 'id_prefix'\n");
1172dab3f910Sjsing 			ERR_print_errors(bio_err);
1173dab3f910Sjsing 			goto end;
1174dab3f910Sjsing 		}
11754da86b84Sinoguchi 		BIO_printf(bio_err, "id_prefix '%s' set.\n",
1176e7718adaStb 		    cfg.session_id_prefix);
1177dab3f910Sjsing 	}
1178dab3f910Sjsing 	SSL_CTX_set_quiet_shutdown(ctx, 1);
1179e7718adaStb 	if (cfg.bugs)
1180dab3f910Sjsing 		SSL_CTX_set_options(ctx, SSL_OP_ALL);
1181e7718adaStb 	SSL_CTX_set_options(ctx, cfg.off);
1182dab3f910Sjsing 
1183e7718adaStb 	if (cfg.state)
1184dab3f910Sjsing 		SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
1185e7718adaStb 	if (cfg.no_cache)
1186dab3f910Sjsing 		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
1187dab3f910Sjsing 	else
1188dab3f910Sjsing 		SSL_CTX_sess_set_cache_size(ctx, 128);
1189dab3f910Sjsing 
1190dab3f910Sjsing #ifndef OPENSSL_NO_SRTP
1191e7718adaStb 	if (cfg.srtp_profiles != NULL)
1192e7718adaStb 		SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles);
1193dab3f910Sjsing #endif
1194dab3f910Sjsing 
1195e7718adaStb 	if ((!SSL_CTX_load_verify_locations(ctx, cfg.CAfile,
1196e7718adaStb 	    cfg.CApath)) ||
1197dab3f910Sjsing 	    (!SSL_CTX_set_default_verify_paths(ctx))) {
1198dab3f910Sjsing 		/* BIO_printf(bio_err,"X509_load_verify_locations\n"); */
1199dab3f910Sjsing 		ERR_print_errors(bio_err);
1200dab3f910Sjsing 		/* goto end; */
1201dab3f910Sjsing 	}
1202e7718adaStb 	if (cfg.vpm)
1203e7718adaStb 		SSL_CTX_set1_param(ctx, cfg.vpm);
1204dab3f910Sjsing 
1205dab3f910Sjsing 	if (s_cert2) {
1206e7718adaStb 		ctx2 = SSL_CTX_new(cfg.meth);
1207dab3f910Sjsing 		if (ctx2 == NULL) {
1208dab3f910Sjsing 			ERR_print_errors(bio_err);
1209dab3f910Sjsing 			goto end;
1210dab3f910Sjsing 		}
121195f83488Sinoguchi 
12124da86b84Sinoguchi 		if (!SSL_CTX_set_min_proto_version(ctx2,
1213e7718adaStb 		    cfg.min_version))
121495f83488Sinoguchi 			goto end;
12154da86b84Sinoguchi 		if (!SSL_CTX_set_max_proto_version(ctx2,
1216e7718adaStb 		    cfg.max_version))
121795f83488Sinoguchi 			goto end;
1218a7150521Stb 		SSL_CTX_clear_mode(ctx2, SSL_MODE_AUTO_RETRY);
1219dab3f910Sjsing 	}
1220dab3f910Sjsing 	if (ctx2) {
1221dab3f910Sjsing 		BIO_printf(bio_s_out, "Setting secondary ctx parameters\n");
1222dab3f910Sjsing 
1223e7718adaStb 		if (cfg.session_id_prefix) {
1224e7718adaStb 			if (strlen(cfg.session_id_prefix) >= 32)
1225dab3f910Sjsing 				BIO_printf(bio_err,
1226dab3f910Sjsing 				    "warning: id_prefix is too long, only one new session will be possible\n");
1227e7718adaStb 			else if (strlen(cfg.session_id_prefix) >= 16)
1228dab3f910Sjsing 				BIO_printf(bio_err,
1229dab3f910Sjsing 				    "warning: id_prefix is too long if you use SSLv2\n");
12304da86b84Sinoguchi 			if (!SSL_CTX_set_generate_session_id(ctx2,
12314da86b84Sinoguchi 			    generate_session_id)) {
12324da86b84Sinoguchi 				BIO_printf(bio_err,
12334da86b84Sinoguchi 				    "error setting 'id_prefix'\n");
1234dab3f910Sjsing 				ERR_print_errors(bio_err);
1235dab3f910Sjsing 				goto end;
1236dab3f910Sjsing 			}
12374da86b84Sinoguchi 			BIO_printf(bio_err, "id_prefix '%s' set.\n",
1238e7718adaStb 			    cfg.session_id_prefix);
1239dab3f910Sjsing 		}
1240dab3f910Sjsing 		SSL_CTX_set_quiet_shutdown(ctx2, 1);
1241e7718adaStb 		if (cfg.bugs)
1242dab3f910Sjsing 			SSL_CTX_set_options(ctx2, SSL_OP_ALL);
1243e7718adaStb 		SSL_CTX_set_options(ctx2, cfg.off);
1244dab3f910Sjsing 
1245e7718adaStb 		if (cfg.state)
1246dab3f910Sjsing 			SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback);
1247dab3f910Sjsing 
1248e7718adaStb 		if (cfg.no_cache)
1249dab3f910Sjsing 			SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF);
1250dab3f910Sjsing 		else
1251dab3f910Sjsing 			SSL_CTX_sess_set_cache_size(ctx2, 128);
1252dab3f910Sjsing 
12534da86b84Sinoguchi 		if ((!SSL_CTX_load_verify_locations(ctx2,
1254e7718adaStb 		    cfg.CAfile, cfg.CApath)) ||
1255dab3f910Sjsing 		    (!SSL_CTX_set_default_verify_paths(ctx2))) {
1256dab3f910Sjsing 			ERR_print_errors(bio_err);
1257dab3f910Sjsing 		}
1258e7718adaStb 		if (cfg.vpm)
1259e7718adaStb 			SSL_CTX_set1_param(ctx2, cfg.vpm);
1260dab3f910Sjsing 	}
12611b4c9cadSjsing 	if (alpn_ctx.data)
12621b4c9cadSjsing 		SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
1263dab3f910Sjsing 
1264e7718adaStb 	if (cfg.groups_in != NULL) {
1265e7718adaStb 		if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) {
1266480d2676Sjsing 			BIO_printf(bio_err, "Failed to set groups '%s'\n",
1267e7718adaStb 			    cfg.groups_in);
1268480d2676Sjsing 			goto end;
1269480d2676Sjsing 		}
1270480d2676Sjsing 	}
1271480d2676Sjsing 
1272dab3f910Sjsing #ifndef OPENSSL_NO_DH
1273e7718adaStb 	if (!cfg.no_dhe) {
1274dab3f910Sjsing 		DH *dh = NULL;
1275dab3f910Sjsing 
1276e7718adaStb 		if (cfg.dhfile)
1277e7718adaStb 			dh = load_dh_param(cfg.dhfile);
1278e7718adaStb 		else if (cfg.cert_file)
1279e7718adaStb 			dh = load_dh_param(cfg.cert_file);
1280dab3f910Sjsing 
1281c66e7edeSjsing 		if (dh != NULL)
1282dab3f910Sjsing 			BIO_printf(bio_s_out, "Setting temp DH parameters\n");
1283c66e7edeSjsing 		else
1284c66e7edeSjsing 			BIO_printf(bio_s_out, "Using auto DH parameters\n");
1285dab3f910Sjsing 		(void) BIO_flush(bio_s_out);
1286dab3f910Sjsing 
1287c66e7edeSjsing 		if (dh == NULL)
1288c66e7edeSjsing 			SSL_CTX_set_dh_auto(ctx, 1);
1289c66e7edeSjsing 		else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
1290c66e7edeSjsing 			BIO_printf(bio_err,
1291c66e7edeSjsing 			    "Error setting temp DH parameters\n");
1292c66e7edeSjsing 			ERR_print_errors(bio_err);
1293c66e7edeSjsing 			DH_free(dh);
1294c66e7edeSjsing 			goto end;
1295c66e7edeSjsing 		}
1296c66e7edeSjsing 
1297dab3f910Sjsing 		if (ctx2) {
1298e7718adaStb 			if (!cfg.dhfile) {
1299073abcbeSdoug 				DH *dh2 = NULL;
1300073abcbeSdoug 
1301e7718adaStb 				if (cfg.cert_file2 != NULL)
13024da86b84Sinoguchi 					dh2 = load_dh_param(
1303e7718adaStb 					    cfg.cert_file2);
1304dab3f910Sjsing 				if (dh2 != NULL) {
13054da86b84Sinoguchi 					BIO_printf(bio_s_out,
13064da86b84Sinoguchi 					    "Setting temp DH parameters\n");
1307dab3f910Sjsing 					(void) BIO_flush(bio_s_out);
1308dab3f910Sjsing 
1309dab3f910Sjsing 					DH_free(dh);
1310dab3f910Sjsing 					dh = dh2;
1311dab3f910Sjsing 				}
1312dab3f910Sjsing 			}
1313c66e7edeSjsing 			if (dh == NULL)
1314c66e7edeSjsing 				SSL_CTX_set_dh_auto(ctx2, 1);
1315c66e7edeSjsing 			else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
1316c66e7edeSjsing 				BIO_printf(bio_err,
1317c66e7edeSjsing 				    "Error setting temp DH parameters\n");
1318c66e7edeSjsing 				ERR_print_errors(bio_err);
1319c66e7edeSjsing 				DH_free(dh);
1320c66e7edeSjsing 				goto end;
1321c66e7edeSjsing 			}
1322dab3f910Sjsing 		}
1323dab3f910Sjsing 		DH_free(dh);
1324dab3f910Sjsing 	}
1325dab3f910Sjsing #endif
1326dab3f910Sjsing 
1327e7718adaStb 	if (!cfg.no_ecdhe && cfg.named_curve != NULL) {
1328dab3f910Sjsing 		EC_KEY *ecdh = NULL;
1329480d2676Sjsing 		int nid;
1330dab3f910Sjsing 
1331e7718adaStb 		if ((nid = OBJ_sn2nid(cfg.named_curve)) == 0) {
1332dab3f910Sjsing 			BIO_printf(bio_err, "unknown curve name (%s)\n",
1333e7718adaStb 			    cfg.named_curve);
1334dab3f910Sjsing 			goto end;
1335dab3f910Sjsing  		}
1336480d2676Sjsing 		if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) {
1337dab3f910Sjsing 			BIO_printf(bio_err, "unable to create curve (%s)\n",
1338e7718adaStb 			    cfg.named_curve);
1339dab3f910Sjsing 			goto end;
1340dab3f910Sjsing  		}
1341dab3f910Sjsing 		BIO_printf(bio_s_out, "Setting temp ECDH parameters\n");
1342dab3f910Sjsing 		(void) BIO_flush(bio_s_out);
1343dab3f910Sjsing 
1344dab3f910Sjsing 		SSL_CTX_set_tmp_ecdh(ctx, ecdh);
1345dab3f910Sjsing 		if (ctx2)
1346dab3f910Sjsing 			SSL_CTX_set_tmp_ecdh(ctx2, ecdh);
1347dab3f910Sjsing 		EC_KEY_free(ecdh);
1348dab3f910Sjsing 	}
1349dab3f910Sjsing 
1350dab3f910Sjsing 	if (!set_cert_key_stuff(ctx, s_cert, s_key))
1351dab3f910Sjsing 		goto end;
1352dab3f910Sjsing 	if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2))
1353dab3f910Sjsing 		goto end;
1354dab3f910Sjsing 	if (s_dcert != NULL) {
1355dab3f910Sjsing 		if (!set_cert_key_stuff(ctx, s_dcert, s_dkey))
1356dab3f910Sjsing 			goto end;
1357dab3f910Sjsing 	}
1358dab3f910Sjsing 
1359e7718adaStb 	if (cfg.cipher != NULL) {
1360e7718adaStb 		if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) {
1361dab3f910Sjsing 			BIO_printf(bio_err, "error setting cipher list\n");
1362dab3f910Sjsing 			ERR_print_errors(bio_err);
1363dab3f910Sjsing 			goto end;
1364dab3f910Sjsing 		}
13654da86b84Sinoguchi 		if (ctx2 && !SSL_CTX_set_cipher_list(ctx2,
1366e7718adaStb 		    cfg.cipher)) {
1367dab3f910Sjsing 			BIO_printf(bio_err, "error setting cipher list\n");
1368dab3f910Sjsing 			ERR_print_errors(bio_err);
1369dab3f910Sjsing 			goto end;
1370dab3f910Sjsing 		}
1371dab3f910Sjsing 	}
1372e7718adaStb 	SSL_CTX_set_verify(ctx, cfg.server_verify, verify_callback);
13734da86b84Sinoguchi 	SSL_CTX_set_session_id_context(ctx,
13744da86b84Sinoguchi 	    (void *) &s_server_session_id_context,
1375dab3f910Sjsing 	    sizeof s_server_session_id_context);
1376dab3f910Sjsing 
1377dab3f910Sjsing 	/* Set DTLS cookie generation and verification callbacks */
1378dab3f910Sjsing 	SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
1379dab3f910Sjsing 	SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
1380dab3f910Sjsing 
1381dab3f910Sjsing 	if (ctx2) {
1382e7718adaStb 		SSL_CTX_set_verify(ctx2, cfg.server_verify,
13834da86b84Sinoguchi 		    verify_callback);
13844da86b84Sinoguchi 		SSL_CTX_set_session_id_context(ctx2,
13854da86b84Sinoguchi 		    (void *) &s_server_session_id_context,
1386dab3f910Sjsing 		    sizeof s_server_session_id_context);
1387dab3f910Sjsing 
1388e7718adaStb 		cfg.tlsextcbp.biodebug = bio_s_out;
1389dab3f910Sjsing 		SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
13904da86b84Sinoguchi 		SSL_CTX_set_tlsext_servername_arg(ctx2,
1391e7718adaStb 		    &cfg.tlsextcbp);
1392dab3f910Sjsing 		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
13934da86b84Sinoguchi 		SSL_CTX_set_tlsext_servername_arg(ctx,
1394e7718adaStb 		    &cfg.tlsextcbp);
1395dab3f910Sjsing 	}
1396dab3f910Sjsing 
1397e7718adaStb 	if (cfg.CAfile != NULL) {
13984da86b84Sinoguchi 		SSL_CTX_set_client_CA_list(ctx,
1399e7718adaStb 		    SSL_load_client_CA_file(cfg.CAfile));
1400dab3f910Sjsing 		if (ctx2)
14014da86b84Sinoguchi 			SSL_CTX_set_client_CA_list(ctx2,
1402e7718adaStb 			    SSL_load_client_CA_file(cfg.CAfile));
1403dab3f910Sjsing 	}
1404dab3f910Sjsing 	BIO_printf(bio_s_out, "ACCEPT\n");
1405dab3f910Sjsing 	(void) BIO_flush(bio_s_out);
1406e7718adaStb 	if (cfg.www)
1407e7718adaStb 		do_server(cfg.port, cfg.socket_type,
1408e7718adaStb 		    &accept_socket, www_body, cfg.context,
1409e7718adaStb 		    cfg.naccept);
1410dab3f910Sjsing 	else
1411e7718adaStb 		do_server(cfg.port, cfg.socket_type,
1412e7718adaStb 		    &accept_socket, sv_body, cfg.context,
1413e7718adaStb 		    cfg.naccept);
1414dab3f910Sjsing 	print_stats(bio_s_out, ctx);
1415dab3f910Sjsing 	ret = 0;
1416dab3f910Sjsing  end:
1417dab3f910Sjsing 	SSL_CTX_free(ctx);
1418dab3f910Sjsing 	X509_free(s_cert);
1419dab3f910Sjsing 	X509_free(s_dcert);
1420dab3f910Sjsing 	EVP_PKEY_free(s_key);
1421dab3f910Sjsing 	EVP_PKEY_free(s_dkey);
1422dab3f910Sjsing 	free(pass);
1423dab3f910Sjsing 	free(dpass);
1424e7718adaStb 	X509_VERIFY_PARAM_free(cfg.vpm);
1425e7718adaStb 	free(cfg.tlscstatp.host);
1426e7718adaStb 	free(cfg.tlscstatp.port);
1427e7718adaStb 	free(cfg.tlscstatp.path);
1428dab3f910Sjsing 	SSL_CTX_free(ctx2);
1429dab3f910Sjsing 	X509_free(s_cert2);
1430dab3f910Sjsing 	EVP_PKEY_free(s_key2);
14311b4c9cadSjsing 	free(alpn_ctx.data);
1432dab3f910Sjsing 	if (bio_s_out != NULL) {
1433dab3f910Sjsing 		BIO_free(bio_s_out);
1434dab3f910Sjsing 		bio_s_out = NULL;
1435dab3f910Sjsing 	}
1436dab3f910Sjsing 
1437dab3f910Sjsing 	return (ret);
1438dab3f910Sjsing }
1439dab3f910Sjsing 
1440dab3f910Sjsing static void
1441dab3f910Sjsing print_stats(BIO *bio, SSL_CTX *ssl_ctx)
1442dab3f910Sjsing {
1443dab3f910Sjsing 	BIO_printf(bio, "%4ld items in the session cache\n",
1444dab3f910Sjsing 	    SSL_CTX_sess_number(ssl_ctx));
1445dab3f910Sjsing 	BIO_printf(bio, "%4ld client connects (SSL_connect())\n",
1446dab3f910Sjsing 	    SSL_CTX_sess_connect(ssl_ctx));
1447dab3f910Sjsing 	BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n",
1448dab3f910Sjsing 	    SSL_CTX_sess_connect_renegotiate(ssl_ctx));
1449dab3f910Sjsing 	BIO_printf(bio, "%4ld client connects that finished\n",
1450dab3f910Sjsing 	    SSL_CTX_sess_connect_good(ssl_ctx));
1451dab3f910Sjsing 	BIO_printf(bio, "%4ld server accepts (SSL_accept())\n",
1452dab3f910Sjsing 	    SSL_CTX_sess_accept(ssl_ctx));
1453dab3f910Sjsing 	BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n",
1454dab3f910Sjsing 	    SSL_CTX_sess_accept_renegotiate(ssl_ctx));
1455dab3f910Sjsing 	BIO_printf(bio, "%4ld server accepts that finished\n",
1456dab3f910Sjsing 	    SSL_CTX_sess_accept_good(ssl_ctx));
14574da86b84Sinoguchi 	BIO_printf(bio, "%4ld session cache hits\n",
14584da86b84Sinoguchi 	    SSL_CTX_sess_hits(ssl_ctx));
14594da86b84Sinoguchi 	BIO_printf(bio, "%4ld session cache misses\n",
14604da86b84Sinoguchi 	    SSL_CTX_sess_misses(ssl_ctx));
14614da86b84Sinoguchi 	BIO_printf(bio, "%4ld session cache timeouts\n",
14624da86b84Sinoguchi 	    SSL_CTX_sess_timeouts(ssl_ctx));
14634da86b84Sinoguchi 	BIO_printf(bio, "%4ld callback cache hits\n",
14644da86b84Sinoguchi 	    SSL_CTX_sess_cb_hits(ssl_ctx));
1465dab3f910Sjsing 	BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n",
1466dab3f910Sjsing 	    SSL_CTX_sess_cache_full(ssl_ctx),
1467dab3f910Sjsing 	    SSL_CTX_sess_get_cache_size(ssl_ctx));
1468dab3f910Sjsing }
1469dab3f910Sjsing 
1470dab3f910Sjsing static int
14717537a7c2Stb sv_body(int s, unsigned char *context)
1472dab3f910Sjsing {
1473dab3f910Sjsing 	char *buf = NULL;
14749c8ea7b6Sderaadt 	int ret = 1;
1475dab3f910Sjsing 	int k, i;
1476dab3f910Sjsing 	unsigned long l;
1477dab3f910Sjsing 	SSL *con = NULL;
1478dab3f910Sjsing 	BIO *sbio;
1479dab3f910Sjsing 	struct timeval timeout;
1480dab3f910Sjsing 
1481dab3f910Sjsing 	if ((buf = malloc(bufsize)) == NULL) {
1482dab3f910Sjsing 		BIO_printf(bio_err, "out of memory\n");
1483dab3f910Sjsing 		goto err;
1484dab3f910Sjsing 	}
1485e7718adaStb 	if (cfg.nbio) {
1486e7718adaStb 		if (!cfg.quiet)
1487dab3f910Sjsing 			BIO_printf(bio_err, "turning on non blocking io\n");
1488fcc700e7Sbcook 		if (!BIO_socket_nbio(s, 1))
1489dab3f910Sjsing 			ERR_print_errors(bio_err);
1490dab3f910Sjsing 	}
1491dab3f910Sjsing 
1492dab3f910Sjsing 	if (con == NULL) {
1493dab3f910Sjsing 		con = SSL_new(ctx);
1494e7718adaStb 		if (cfg.tlsextdebug) {
1495dab3f910Sjsing 			SSL_set_tlsext_debug_callback(con, tlsext_cb);
1496dab3f910Sjsing 			SSL_set_tlsext_debug_arg(con, bio_s_out);
1497dab3f910Sjsing 		}
1498e7718adaStb 		if (cfg.tlsextstatus) {
1499dab3f910Sjsing 			SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
1500e7718adaStb 			cfg.tlscstatp.err = bio_err;
15014da86b84Sinoguchi 			SSL_CTX_set_tlsext_status_arg(ctx,
1502e7718adaStb 			    &cfg.tlscstatp);
1503dab3f910Sjsing 		}
1504dab3f910Sjsing 		if (context)
1505dab3f910Sjsing 			SSL_set_session_id_context(con, context,
1506dab3f910Sjsing 			    strlen((char *) context));
1507dab3f910Sjsing 	}
1508dab3f910Sjsing 	SSL_clear(con);
1509dab3f910Sjsing 
151093dafd19Sjsing 	if (SSL_is_dtls(con)) {
1511dab3f910Sjsing 		sbio = BIO_new_dgram(s, BIO_NOCLOSE);
1512dab3f910Sjsing 
1513e7718adaStb 		if (cfg.enable_timeouts) {
1514dab3f910Sjsing 			timeout.tv_sec = 0;
1515dab3f910Sjsing 			timeout.tv_usec = DGRAM_RCV_TIMEOUT;
15164da86b84Sinoguchi 			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0,
15174da86b84Sinoguchi 			    &timeout);
1518dab3f910Sjsing 
1519dab3f910Sjsing 			timeout.tv_sec = 0;
1520dab3f910Sjsing 			timeout.tv_usec = DGRAM_SND_TIMEOUT;
15214da86b84Sinoguchi 			BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0,
15224da86b84Sinoguchi 			    &timeout);
1523dab3f910Sjsing 		}
1524e7718adaStb 		if (cfg.socket_mtu > 28) {
1525dab3f910Sjsing 			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
1526e7718adaStb 			SSL_set_mtu(con, cfg.socket_mtu - 28);
1527dab3f910Sjsing 		} else
1528dab3f910Sjsing 			/* want to do MTU discovery */
1529dab3f910Sjsing 			BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
1530dab3f910Sjsing 
1531dab3f910Sjsing 		/* turn on cookie exchange */
1532dab3f910Sjsing 		SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
1533dab3f910Sjsing 	} else
1534dab3f910Sjsing 		sbio = BIO_new_socket(s, BIO_NOCLOSE);
1535dab3f910Sjsing 
1536e7718adaStb 	if (cfg.nbio_test) {
1537dab3f910Sjsing 		BIO *test;
1538dab3f910Sjsing 
1539dab3f910Sjsing 		test = BIO_new(BIO_f_nbio_test());
1540dab3f910Sjsing 		sbio = BIO_push(test, sbio);
1541dab3f910Sjsing 	}
1542dab3f910Sjsing 
1543dab3f910Sjsing 	SSL_set_bio(con, sbio, sbio);
1544dab3f910Sjsing 	SSL_set_accept_state(con);
1545dab3f910Sjsing 	/* SSL_set_fd(con,s); */
1546dab3f910Sjsing 
1547e7718adaStb 	if (cfg.debug) {
1548dab3f910Sjsing 		BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
1549dab3f910Sjsing 		BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out);
1550dab3f910Sjsing 	}
1551e7718adaStb 	if (cfg.msg) {
1552dab3f910Sjsing 		SSL_set_msg_callback(con, msg_cb);
1553dab3f910Sjsing 		SSL_set_msg_callback_arg(con, bio_s_out);
1554dab3f910Sjsing 	}
1555e7718adaStb 	if (cfg.tlsextdebug) {
1556dab3f910Sjsing 		SSL_set_tlsext_debug_callback(con, tlsext_cb);
1557dab3f910Sjsing 		SSL_set_tlsext_debug_arg(con, bio_s_out);
1558dab3f910Sjsing 	}
1559dab3f910Sjsing 
1560dab3f910Sjsing 	for (;;) {
1561dab3f910Sjsing 		int read_from_terminal;
1562dab3f910Sjsing 		int read_from_sslcon;
15639c8ea7b6Sderaadt 		struct pollfd pfd[2];
15649c8ea7b6Sderaadt 		int ptimeout;
1565dab3f910Sjsing 
1566dab3f910Sjsing 		read_from_terminal = 0;
1567dab3f910Sjsing 		read_from_sslcon = SSL_pending(con);
1568dab3f910Sjsing 
1569dab3f910Sjsing 		if (!read_from_sslcon) {
15709c8ea7b6Sderaadt 			pfd[0].fd = fileno(stdin);
15719c8ea7b6Sderaadt 			pfd[0].events = POLLIN;
15729c8ea7b6Sderaadt 			pfd[1].fd = s;
15739c8ea7b6Sderaadt 			pfd[1].events = POLLIN;
15749c8ea7b6Sderaadt 
157593dafd19Sjsing 			if (SSL_is_dtls(con) &&
1576dab3f910Sjsing 			    DTLSv1_get_timeout(con, &timeout))
15779c8ea7b6Sderaadt 				ptimeout = timeout.tv_sec * 1000 +
15789c8ea7b6Sderaadt 				    timeout.tv_usec / 1000;
1579dab3f910Sjsing 			else
15809c8ea7b6Sderaadt 				ptimeout = -1;
1581dab3f910Sjsing 
15829c8ea7b6Sderaadt 			i = poll(pfd, 2, ptimeout);
1583dab3f910Sjsing 
158493dafd19Sjsing 			if (SSL_is_dtls(con) &&
158593dafd19Sjsing 			    DTLSv1_handle_timeout(con) > 0)
1586dab3f910Sjsing 				BIO_printf(bio_err, "TIMEOUT occured\n");
1587dab3f910Sjsing 			if (i <= 0)
1588dab3f910Sjsing 				continue;
15899c8ea7b6Sderaadt 			if (pfd[0].revents) {
15909c8ea7b6Sderaadt 				if ((pfd[0].revents & (POLLERR|POLLNVAL)))
15919c8ea7b6Sderaadt 					continue;
1592dab3f910Sjsing 				read_from_terminal = 1;
15939c8ea7b6Sderaadt 			}
15949c8ea7b6Sderaadt 			if (pfd[1].revents) {
15959c8ea7b6Sderaadt 				if ((pfd[1].revents & (POLLERR|POLLNVAL)))
15969c8ea7b6Sderaadt 					continue;
1597dab3f910Sjsing 				read_from_sslcon = 1;
1598dab3f910Sjsing 			}
15999c8ea7b6Sderaadt 		}
1600dab3f910Sjsing 		if (read_from_terminal) {
1601e7718adaStb 			if (cfg.crlf) {
1602dab3f910Sjsing 				int j, lf_num;
1603dab3f910Sjsing 
1604dab3f910Sjsing 				i = read(fileno(stdin), buf, bufsize / 2);
1605dab3f910Sjsing 				lf_num = 0;
1606dab3f910Sjsing 				/* both loops are skipped when i <= 0 */
1607dab3f910Sjsing 				for (j = 0; j < i; j++)
1608dab3f910Sjsing 					if (buf[j] == '\n')
1609dab3f910Sjsing 						lf_num++;
1610dab3f910Sjsing 				for (j = i - 1; j >= 0; j--) {
1611dab3f910Sjsing 					buf[j + lf_num] = buf[j];
1612dab3f910Sjsing 					if (buf[j] == '\n') {
1613dab3f910Sjsing 						lf_num--;
1614dab3f910Sjsing 						i++;
1615dab3f910Sjsing 						buf[j + lf_num] = '\r';
1616dab3f910Sjsing 					}
1617dab3f910Sjsing 				}
1618dab3f910Sjsing 				assert(lf_num == 0);
1619dab3f910Sjsing 			} else
1620dab3f910Sjsing 				i = read(fileno(stdin), buf, bufsize);
1621e7718adaStb 			if (!cfg.quiet) {
1622dab3f910Sjsing 				if ((i <= 0) || (buf[0] == 'Q')) {
1623dab3f910Sjsing 					BIO_printf(bio_s_out, "DONE\n");
1624dab3f910Sjsing 					shutdown(s, SHUT_RD);
1625dab3f910Sjsing 					close(s);
1626dab3f910Sjsing 					close_accept_socket();
1627dab3f910Sjsing 					ret = -11;
1628dab3f910Sjsing 					goto err;
1629dab3f910Sjsing 				}
1630dab3f910Sjsing 				if ((i <= 0) || (buf[0] == 'q')) {
1631dab3f910Sjsing 					BIO_printf(bio_s_out, "DONE\n");
163293dafd19Sjsing 					if (!SSL_is_dtls(con)) {
1633dab3f910Sjsing 						shutdown(s, SHUT_RD);
1634dab3f910Sjsing 						close(s);
1635dab3f910Sjsing 					}
1636dab3f910Sjsing 					/*
1637dab3f910Sjsing 					 * close_accept_socket(); ret= -11;
1638dab3f910Sjsing 					 */
1639dab3f910Sjsing 					goto err;
1640dab3f910Sjsing 				}
1641dab3f910Sjsing 				if ((buf[0] == 'r') &&
1642dab3f910Sjsing 				    ((buf[1] == '\n') || (buf[1] == '\r'))) {
1643dab3f910Sjsing 					SSL_renegotiate(con);
1644dab3f910Sjsing 					i = SSL_do_handshake(con);
1645dab3f910Sjsing 					printf("SSL_do_handshake -> %d\n", i);
1646dab3f910Sjsing 					i = 0;	/* 13; */
1647dab3f910Sjsing 					continue;
1648dab3f910Sjsing 					/*
1649dab3f910Sjsing 					 * RE-NEGOTIATE\n");
1650dab3f910Sjsing 					 */
1651dab3f910Sjsing 				}
1652dab3f910Sjsing 				if ((buf[0] == 'R') &&
1653dab3f910Sjsing 				    ((buf[1] == '\n') || (buf[1] == '\r'))) {
1654dab3f910Sjsing 					SSL_set_verify(con,
16554da86b84Sinoguchi 					    SSL_VERIFY_PEER |
16564da86b84Sinoguchi 					    SSL_VERIFY_CLIENT_ONCE,
16574da86b84Sinoguchi 					    NULL);
1658dab3f910Sjsing 					SSL_renegotiate(con);
1659dab3f910Sjsing 					i = SSL_do_handshake(con);
1660dab3f910Sjsing 					printf("SSL_do_handshake -> %d\n", i);
1661dab3f910Sjsing 					i = 0;	/* 13; */
1662dab3f910Sjsing 					continue;
1663dab3f910Sjsing 					/*
1664dab3f910Sjsing 					 * RE-NEGOTIATE asking for client
1665dab3f910Sjsing 					 * cert\n");
1666dab3f910Sjsing 					 */
1667dab3f910Sjsing 				}
1668dab3f910Sjsing 				if (buf[0] == 'P') {
16694da86b84Sinoguchi 					static const char *str =
16704da86b84Sinoguchi 					    "Lets print some clear text\n";
16714da86b84Sinoguchi 					BIO_write(SSL_get_wbio(con), str,
16724da86b84Sinoguchi 					    strlen(str));
1673dab3f910Sjsing 				}
1674dab3f910Sjsing 				if (buf[0] == 'S') {
16754da86b84Sinoguchi 					print_stats(bio_s_out,
16764da86b84Sinoguchi 					    SSL_get_SSL_CTX(con));
1677dab3f910Sjsing 				}
1678dab3f910Sjsing 			}
1679dab3f910Sjsing 			l = k = 0;
1680dab3f910Sjsing 			for (;;) {
1681dab3f910Sjsing 				/* should do a select for the write */
1682dab3f910Sjsing #ifdef RENEG
1683dab3f910Sjsing 				{
1684dab3f910Sjsing 					static count = 0;
1685dab3f910Sjsing 					if (++count == 100) {
1686dab3f910Sjsing 						count = 0;
1687dab3f910Sjsing 						SSL_renegotiate(con);
1688dab3f910Sjsing 					}
1689dab3f910Sjsing 				}
1690dab3f910Sjsing #endif
1691dab3f910Sjsing 				k = SSL_write(con, &(buf[l]), (unsigned int) i);
1692dab3f910Sjsing 				switch (SSL_get_error(con, k)) {
1693dab3f910Sjsing 				case SSL_ERROR_NONE:
1694dab3f910Sjsing 					break;
1695dab3f910Sjsing 				case SSL_ERROR_WANT_WRITE:
1696dab3f910Sjsing 				case SSL_ERROR_WANT_READ:
1697dab3f910Sjsing 				case SSL_ERROR_WANT_X509_LOOKUP:
1698dab3f910Sjsing 					BIO_printf(bio_s_out, "Write BLOCK\n");
1699dab3f910Sjsing 					break;
1700dab3f910Sjsing 				case SSL_ERROR_SYSCALL:
1701dab3f910Sjsing 				case SSL_ERROR_SSL:
1702dab3f910Sjsing 					BIO_printf(bio_s_out, "ERROR\n");
1703dab3f910Sjsing 					ERR_print_errors(bio_err);
1704dab3f910Sjsing 					ret = 1;
1705dab3f910Sjsing 					goto err;
1706dab3f910Sjsing 					/* break; */
1707dab3f910Sjsing 				case SSL_ERROR_ZERO_RETURN:
1708dab3f910Sjsing 					BIO_printf(bio_s_out, "DONE\n");
1709dab3f910Sjsing 					ret = 1;
1710dab3f910Sjsing 					goto err;
1711dab3f910Sjsing 				}
17125285fdefStb 				if (k <= 0)
17135285fdefStb 					continue;
1714dab3f910Sjsing 				l += k;
1715dab3f910Sjsing 				i -= k;
1716dab3f910Sjsing 				if (i <= 0)
1717dab3f910Sjsing 					break;
1718dab3f910Sjsing 			}
1719dab3f910Sjsing 		}
1720dab3f910Sjsing 		if (read_from_sslcon) {
1721dab3f910Sjsing 			if (!SSL_is_init_finished(con)) {
1722dab3f910Sjsing 				i = init_ssl_connection(con);
1723dab3f910Sjsing 
1724dab3f910Sjsing 				if (i < 0) {
1725dab3f910Sjsing 					ret = 0;
1726dab3f910Sjsing 					goto err;
1727dab3f910Sjsing 				} else if (i == 0) {
1728dab3f910Sjsing 					ret = 1;
1729dab3f910Sjsing 					goto err;
1730dab3f910Sjsing 				}
1731dab3f910Sjsing 			} else {
1732dab3f910Sjsing 		again:
1733dab3f910Sjsing 				i = SSL_read(con, (char *) buf, bufsize);
1734dab3f910Sjsing 				switch (SSL_get_error(con, i)) {
1735dab3f910Sjsing 				case SSL_ERROR_NONE: {
1736dab3f910Sjsing 						int len, n;
1737dab3f910Sjsing 						for (len = 0; len < i;) {
1738dab3f910Sjsing 							do {
1739dab3f910Sjsing 								n = write(fileno(stdout), buf + len, i - len);
1740dab3f910Sjsing 							} while (n == -1 && errno == EINTR);
1741dab3f910Sjsing 
17423aaa63ebSderaadt 							if (n == -1) {
1743dab3f910Sjsing 								BIO_printf(bio_s_out, "ERROR\n");
1744dab3f910Sjsing 								goto err;
1745dab3f910Sjsing 							}
1746dab3f910Sjsing 							len += n;
1747dab3f910Sjsing 						}
1748dab3f910Sjsing 					}
1749dab3f910Sjsing 					if (SSL_pending(con))
1750dab3f910Sjsing 						goto again;
1751dab3f910Sjsing 					break;
1752dab3f910Sjsing 				case SSL_ERROR_WANT_WRITE:
1753dab3f910Sjsing 				case SSL_ERROR_WANT_READ:
1754dab3f910Sjsing 					BIO_printf(bio_s_out, "Read BLOCK\n");
1755dab3f910Sjsing 					break;
1756dab3f910Sjsing 				case SSL_ERROR_SYSCALL:
1757dab3f910Sjsing 				case SSL_ERROR_SSL:
1758dab3f910Sjsing 					BIO_printf(bio_s_out, "ERROR\n");
1759dab3f910Sjsing 					ERR_print_errors(bio_err);
1760dab3f910Sjsing 					ret = 1;
1761dab3f910Sjsing 					goto err;
1762dab3f910Sjsing 				case SSL_ERROR_ZERO_RETURN:
1763dab3f910Sjsing 					BIO_printf(bio_s_out, "DONE\n");
1764dab3f910Sjsing 					ret = 1;
1765dab3f910Sjsing 					goto err;
1766dab3f910Sjsing 				}
1767dab3f910Sjsing 			}
1768dab3f910Sjsing 		}
1769dab3f910Sjsing 	}
1770dab3f910Sjsing  err:
1771dab3f910Sjsing 	if (con != NULL) {
1772dab3f910Sjsing 		BIO_printf(bio_s_out, "shutting down SSL\n");
17734da86b84Sinoguchi 		SSL_set_shutdown(con,
17744da86b84Sinoguchi 		    SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
1775dab3f910Sjsing 		SSL_free(con);
1776dab3f910Sjsing 	}
1777dab3f910Sjsing 	BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
1778cf4db30dSderaadt 	freezero(buf, bufsize);
1779dab3f910Sjsing 	if (ret >= 0)
1780dab3f910Sjsing 		BIO_printf(bio_s_out, "ACCEPT\n");
1781dab3f910Sjsing 	return (ret);
1782dab3f910Sjsing }
1783dab3f910Sjsing 
1784dab3f910Sjsing static void
1785dab3f910Sjsing close_accept_socket(void)
1786dab3f910Sjsing {
1787dab3f910Sjsing 	BIO_printf(bio_err, "shutdown accept socket\n");
1788dab3f910Sjsing 	if (accept_socket >= 0) {
1789dab3f910Sjsing 		shutdown(accept_socket, SHUT_RDWR);
1790dab3f910Sjsing 		close(accept_socket);
1791dab3f910Sjsing 	}
1792dab3f910Sjsing }
1793dab3f910Sjsing 
1794dab3f910Sjsing static int
1795dab3f910Sjsing init_ssl_connection(SSL *con)
1796dab3f910Sjsing {
1797dab3f910Sjsing 	int i;
1798dab3f910Sjsing 	const char *str;
1799dab3f910Sjsing 	X509 *peer;
1800dab3f910Sjsing 	long verify_error;
1801dab3f910Sjsing 	char buf[BUFSIZ];
1802dab3f910Sjsing 	unsigned char *exportedkeymat;
1803dab3f910Sjsing 
1804dab3f910Sjsing 	i = SSL_accept(con);
1805dab3f910Sjsing 	if (i <= 0) {
1806dab3f910Sjsing 		if (BIO_sock_should_retry(i)) {
1807dab3f910Sjsing 			BIO_printf(bio_s_out, "DELAY\n");
1808dab3f910Sjsing 			return (1);
1809dab3f910Sjsing 		}
1810dab3f910Sjsing 		BIO_printf(bio_err, "ERROR\n");
1811dab3f910Sjsing 		verify_error = SSL_get_verify_result(con);
1812dab3f910Sjsing 		if (verify_error != X509_V_OK) {
1813dab3f910Sjsing 			BIO_printf(bio_err, "verify error:%s\n",
1814dab3f910Sjsing 			    X509_verify_cert_error_string(verify_error));
1815dab3f910Sjsing 		} else
1816dab3f910Sjsing 			ERR_print_errors(bio_err);
1817dab3f910Sjsing 		return (0);
1818dab3f910Sjsing 	}
1819dab3f910Sjsing 	PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
1820dab3f910Sjsing 
1821dab3f910Sjsing 	peer = SSL_get_peer_certificate(con);
1822dab3f910Sjsing 	if (peer != NULL) {
1823dab3f910Sjsing 		BIO_printf(bio_s_out, "Client certificate\n");
1824dab3f910Sjsing 		PEM_write_bio_X509(bio_s_out, peer);
1825dab3f910Sjsing 		X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf);
1826dab3f910Sjsing 		BIO_printf(bio_s_out, "subject=%s\n", buf);
1827dab3f910Sjsing 		X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf);
1828dab3f910Sjsing 		BIO_printf(bio_s_out, "issuer=%s\n", buf);
1829dab3f910Sjsing 		X509_free(peer);
1830dab3f910Sjsing 	}
1831dab3f910Sjsing 	if (SSL_get_shared_ciphers(con, buf, sizeof buf) != NULL)
1832dab3f910Sjsing 		BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
1833dab3f910Sjsing 	str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
1834dab3f910Sjsing 	BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
1835dab3f910Sjsing 
1836dab3f910Sjsing #ifndef OPENSSL_NO_SRTP
1837dab3f910Sjsing 	{
1838dab3f910Sjsing 		SRTP_PROTECTION_PROFILE *srtp_profile
1839dab3f910Sjsing 		= SSL_get_selected_srtp_profile(con);
1840dab3f910Sjsing 
1841dab3f910Sjsing 		if (srtp_profile)
18424da86b84Sinoguchi 			BIO_printf(bio_s_out,
18434da86b84Sinoguchi 			    "SRTP Extension negotiated, profile=%s\n",
1844dab3f910Sjsing 			    srtp_profile->name);
1845dab3f910Sjsing 	}
1846dab3f910Sjsing #endif
1847dab3f910Sjsing 	if (SSL_cache_hit(con))
1848dab3f910Sjsing 		BIO_printf(bio_s_out, "Reused session-id\n");
1849dab3f910Sjsing 	BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
1850dab3f910Sjsing 	    SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
1851e7718adaStb 	if (cfg.keymatexportlabel != NULL) {
1852dab3f910Sjsing 		BIO_printf(bio_s_out, "Keying material exporter:\n");
18534da86b84Sinoguchi 		BIO_printf(bio_s_out, "    Label: '%s'\n",
1854e7718adaStb 		    cfg.keymatexportlabel);
1855dab3f910Sjsing 		BIO_printf(bio_s_out, "    Length: %i bytes\n",
1856e7718adaStb 		    cfg.keymatexportlen);
1857e7718adaStb 		exportedkeymat = malloc(cfg.keymatexportlen);
1858dab3f910Sjsing 		if (exportedkeymat != NULL) {
1859dab3f910Sjsing 			if (!SSL_export_keying_material(con, exportedkeymat,
1860e7718adaStb 				cfg.keymatexportlen,
1861e7718adaStb 				cfg.keymatexportlabel,
1862e7718adaStb 				strlen(cfg.keymatexportlabel),
1863dab3f910Sjsing 				NULL, 0, 0)) {
1864dab3f910Sjsing 				BIO_printf(bio_s_out, "    Error\n");
1865dab3f910Sjsing 			} else {
1866dab3f910Sjsing 				BIO_printf(bio_s_out, "    Keying material: ");
1867e7718adaStb 				for (i = 0; i < cfg.keymatexportlen; i++)
1868dab3f910Sjsing 					BIO_printf(bio_s_out, "%02X",
1869dab3f910Sjsing 					    exportedkeymat[i]);
1870dab3f910Sjsing 				BIO_printf(bio_s_out, "\n");
1871dab3f910Sjsing 			}
1872dab3f910Sjsing 			free(exportedkeymat);
1873dab3f910Sjsing 		}
1874dab3f910Sjsing 	}
1875dab3f910Sjsing 	return (1);
1876dab3f910Sjsing }
1877dab3f910Sjsing 
1878dab3f910Sjsing #ifndef OPENSSL_NO_DH
1879dab3f910Sjsing static DH *
1880dab3f910Sjsing load_dh_param(const char *dhfile)
1881dab3f910Sjsing {
1882dab3f910Sjsing 	DH *ret = NULL;
1883dab3f910Sjsing 	BIO *bio;
1884dab3f910Sjsing 
1885dab3f910Sjsing 	if ((bio = BIO_new_file(dhfile, "r")) == NULL)
1886dab3f910Sjsing 		goto err;
1887dab3f910Sjsing 	ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1888dab3f910Sjsing  err:
1889dab3f910Sjsing 	BIO_free(bio);
1890dab3f910Sjsing 	return (ret);
1891dab3f910Sjsing }
1892dab3f910Sjsing #endif
1893dab3f910Sjsing 
1894dab3f910Sjsing static int
18957537a7c2Stb www_body(int s, unsigned char *context)
1896dab3f910Sjsing {
1897dab3f910Sjsing 	char *buf = NULL;
1898dab3f910Sjsing 	int ret = 1;
1899dab3f910Sjsing 	int i, j, k, dot;
1900dab3f910Sjsing 	SSL *con;
1901dab3f910Sjsing 	const SSL_CIPHER *c;
1902dab3f910Sjsing 	BIO *io, *ssl_bio, *sbio;
1903dab3f910Sjsing 
1904dab3f910Sjsing 	buf = malloc(bufsize);
1905dab3f910Sjsing 	if (buf == NULL)
1906dab3f910Sjsing 		return (0);
1907dab3f910Sjsing 	io = BIO_new(BIO_f_buffer());
1908dab3f910Sjsing 	ssl_bio = BIO_new(BIO_f_ssl());
1909dab3f910Sjsing 	if ((io == NULL) || (ssl_bio == NULL))
1910dab3f910Sjsing 		goto err;
1911dab3f910Sjsing 
1912e7718adaStb 	if (cfg.nbio) {
1913e7718adaStb 		if (!cfg.quiet)
1914dab3f910Sjsing 			BIO_printf(bio_err, "turning on non blocking io\n");
1915fcc700e7Sbcook 		if (!BIO_socket_nbio(s, 1))
1916dab3f910Sjsing 			ERR_print_errors(bio_err);
1917dab3f910Sjsing 	}
1918dab3f910Sjsing 
1919dab3f910Sjsing 	/* lets make the output buffer a reasonable size */
1920dab3f910Sjsing 	if (!BIO_set_write_buffer_size(io, bufsize))
1921dab3f910Sjsing 		goto err;
1922dab3f910Sjsing 
1923dab3f910Sjsing 	if ((con = SSL_new(ctx)) == NULL)
1924dab3f910Sjsing 		goto err;
1925e7718adaStb 	if (cfg.tlsextdebug) {
1926dab3f910Sjsing 		SSL_set_tlsext_debug_callback(con, tlsext_cb);
1927dab3f910Sjsing 		SSL_set_tlsext_debug_arg(con, bio_s_out);
1928dab3f910Sjsing 	}
1929dab3f910Sjsing 	if (context)
1930dab3f910Sjsing 		SSL_set_session_id_context(con, context,
1931dab3f910Sjsing 		    strlen((char *) context));
1932dab3f910Sjsing 
1933dab3f910Sjsing 	sbio = BIO_new_socket(s, BIO_NOCLOSE);
1934e7718adaStb 	if (cfg.nbio_test) {
1935dab3f910Sjsing 		BIO *test;
1936dab3f910Sjsing 
1937dab3f910Sjsing 		test = BIO_new(BIO_f_nbio_test());
1938dab3f910Sjsing 		sbio = BIO_push(test, sbio);
1939dab3f910Sjsing 	}
1940dab3f910Sjsing 	SSL_set_bio(con, sbio, sbio);
1941dab3f910Sjsing 	SSL_set_accept_state(con);
1942dab3f910Sjsing 
1943dab3f910Sjsing 	/* SSL_set_fd(con,s); */
1944dab3f910Sjsing 	BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
1945dab3f910Sjsing 	BIO_push(io, ssl_bio);
1946dab3f910Sjsing 
1947e7718adaStb 	if (cfg.debug) {
1948dab3f910Sjsing 		BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
1949dab3f910Sjsing 		BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out);
1950dab3f910Sjsing 	}
1951e7718adaStb 	if (cfg.msg) {
1952dab3f910Sjsing 		SSL_set_msg_callback(con, msg_cb);
1953dab3f910Sjsing 		SSL_set_msg_callback_arg(con, bio_s_out);
1954dab3f910Sjsing 	}
1955dab3f910Sjsing 	for (;;) {
1956dab3f910Sjsing 		i = BIO_gets(io, buf, bufsize - 1);
1957dab3f910Sjsing 		if (i < 0) {	/* error */
1958dab3f910Sjsing 			if (!BIO_should_retry(io)) {
1959e7718adaStb 				if (!cfg.quiet)
1960dab3f910Sjsing 					ERR_print_errors(bio_err);
1961dab3f910Sjsing 				goto err;
1962dab3f910Sjsing 			} else {
1963e7718adaStb 				if (cfg.debug)  {
1964dab3f910Sjsing 					BIO_printf(bio_s_out, "read R BLOCK\n");
1965dab3f910Sjsing 					sleep(1);
196630d5484aSbeck 				}
1967dab3f910Sjsing 				continue;
1968dab3f910Sjsing 			}
1969dab3f910Sjsing 		} else if (i == 0) {	/* end of input */
1970dab3f910Sjsing 			ret = 1;
1971dab3f910Sjsing 			goto end;
1972dab3f910Sjsing 		}
1973dab3f910Sjsing 		/* else we have data */
1974e7718adaStb 		if (((cfg.www == 1) &&
19754da86b84Sinoguchi 		    (strncmp("GET ", buf, 4) == 0)) ||
1976e7718adaStb 		    ((cfg.www == 2) &&
19774da86b84Sinoguchi 		    (strncmp("GET /stats ", buf, 11) == 0))) {
1978dab3f910Sjsing 			char *p;
1979dab3f910Sjsing 			X509 *peer;
1980dab3f910Sjsing 			STACK_OF(SSL_CIPHER) *sk;
1981dab3f910Sjsing 			static const char *space = "                          ";
1982dab3f910Sjsing 
1983dab3f910Sjsing 			BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
1984dab3f910Sjsing 			BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n");
1985dab3f910Sjsing 			BIO_puts(io, "<pre>\n");
1986dab3f910Sjsing /*			BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
1987dab3f910Sjsing 			BIO_puts(io, "\n");
1988dab3f910Sjsing 			for (i = 0; i < local_argc; i++) {
1989dab3f910Sjsing 				BIO_puts(io, local_argv[i]);
1990dab3f910Sjsing 				BIO_write(io, " ", 1);
1991dab3f910Sjsing 			}
1992dab3f910Sjsing 			BIO_puts(io, "\n");
1993dab3f910Sjsing 
1994dab3f910Sjsing 			BIO_printf(io,
1995dab3f910Sjsing 			    "Secure Renegotiation IS%s supported\n",
1996dab3f910Sjsing 			    SSL_get_secure_renegotiation_support(con) ?
1997dab3f910Sjsing 			    "" : " NOT");
1998dab3f910Sjsing 
1999dab3f910Sjsing 			/*
2000dab3f910Sjsing 			 * The following is evil and should not really be
2001dab3f910Sjsing 			 * done
2002dab3f910Sjsing 			 */
20034da86b84Sinoguchi 			BIO_printf(io,
20044da86b84Sinoguchi 			    "Ciphers supported in s_server binary\n");
2005dab3f910Sjsing 			sk = SSL_get_ciphers(con);
2006dab3f910Sjsing 			j = sk_SSL_CIPHER_num(sk);
2007dab3f910Sjsing 			for (i = 0; i < j; i++) {
2008dab3f910Sjsing 				c = sk_SSL_CIPHER_value(sk, i);
2009dab3f910Sjsing 				BIO_printf(io, "%-11s:%-25s",
2010dab3f910Sjsing 				    SSL_CIPHER_get_version(c),
2011dab3f910Sjsing 				    SSL_CIPHER_get_name(c));
2012dab3f910Sjsing 				if ((((i + 1) % 2) == 0) && (i + 1 != j))
2013dab3f910Sjsing 					BIO_puts(io, "\n");
2014dab3f910Sjsing 			}
2015dab3f910Sjsing 			BIO_puts(io, "\n");
2016dab3f910Sjsing 			p = SSL_get_shared_ciphers(con, buf, bufsize);
2017dab3f910Sjsing 			if (p != NULL) {
20184da86b84Sinoguchi 				BIO_printf(io,
20194da86b84Sinoguchi 				    "---\nCiphers common between both SSL end points:\n");
2020dab3f910Sjsing 				j = i = 0;
2021dab3f910Sjsing 				while (*p) {
2022dab3f910Sjsing 					if (*p == ':') {
2023dab3f910Sjsing 						BIO_write(io, space, 26 - j);
2024dab3f910Sjsing 						i++;
2025dab3f910Sjsing 						j = 0;
20264da86b84Sinoguchi 						BIO_write(io,
20274da86b84Sinoguchi 						    ((i % 3) ?  " " : "\n"), 1);
2028dab3f910Sjsing 					} else {
2029dab3f910Sjsing 						BIO_write(io, p, 1);
2030dab3f910Sjsing 						j++;
2031dab3f910Sjsing 					}
2032dab3f910Sjsing 					p++;
2033dab3f910Sjsing 				}
2034dab3f910Sjsing 				BIO_puts(io, "\n");
2035dab3f910Sjsing 			}
2036dab3f910Sjsing 			BIO_printf(io, (SSL_cache_hit(con)
2037dab3f910Sjsing 				? "---\nReused, "
2038dab3f910Sjsing 				: "---\nNew, "));
2039dab3f910Sjsing 			c = SSL_get_current_cipher(con);
2040dab3f910Sjsing 			BIO_printf(io, "%s, Cipher is %s\n",
2041dab3f910Sjsing 			    SSL_CIPHER_get_version(c),
2042dab3f910Sjsing 			    SSL_CIPHER_get_name(c));
2043dab3f910Sjsing 			SSL_SESSION_print(io, SSL_get_session(con));
2044dab3f910Sjsing 			BIO_printf(io, "---\n");
2045dab3f910Sjsing 			print_stats(io, SSL_get_SSL_CTX(con));
2046dab3f910Sjsing 			BIO_printf(io, "---\n");
2047dab3f910Sjsing 			peer = SSL_get_peer_certificate(con);
2048dab3f910Sjsing 			if (peer != NULL) {
2049dab3f910Sjsing 				BIO_printf(io, "Client certificate\n");
2050dab3f910Sjsing 				X509_print(io, peer);
2051dab3f910Sjsing 				PEM_write_bio_X509(io, peer);
2052dab3f910Sjsing 			} else
20534da86b84Sinoguchi 				BIO_puts(io,
20544da86b84Sinoguchi 				    "no client certificate available\n");
2055dab3f910Sjsing 			BIO_puts(io, "</BODY></HTML>\r\n\r\n");
2056dab3f910Sjsing 			break;
2057e7718adaStb 		} else if ((cfg.www == 2 ||
2058e7718adaStb 		    cfg.www == 3) &&
20594da86b84Sinoguchi 		    (strncmp("GET /", buf, 5) == 0)) {
2060dab3f910Sjsing 			BIO *file;
2061dab3f910Sjsing 			char *p, *e;
2062dab3f910Sjsing 			static const char *text = "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
2063dab3f910Sjsing 
2064dab3f910Sjsing 			/* skip the '/' */
2065dab3f910Sjsing 			p = &(buf[5]);
2066dab3f910Sjsing 
2067dab3f910Sjsing 			dot = 1;
2068dab3f910Sjsing 			for (e = p; *e != '\0'; e++) {
2069dab3f910Sjsing 				if (e[0] == ' ')
2070dab3f910Sjsing 					break;
2071dab3f910Sjsing 
2072dab3f910Sjsing 				switch (dot) {
2073dab3f910Sjsing 				case 1:
2074dab3f910Sjsing 					dot = (e[0] == '.') ? 2 : 0;
2075dab3f910Sjsing 					break;
2076dab3f910Sjsing 				case 2:
2077dab3f910Sjsing 					dot = (e[0] == '.') ? 3 : 0;
2078dab3f910Sjsing 					break;
2079dab3f910Sjsing 				case 3:
20804da86b84Sinoguchi 					dot = (e[0] == '/' || e[0] == '\\') ?
20814da86b84Sinoguchi 					    -1 : 0;
2082dab3f910Sjsing 					break;
2083dab3f910Sjsing 				}
2084dab3f910Sjsing 				if (dot == 0)
20854da86b84Sinoguchi 					dot = (e[0] == '/' || e[0] == '\\') ?
20864da86b84Sinoguchi 					    1 : 0;
2087dab3f910Sjsing 			}
2088dab3f910Sjsing 			dot = (dot == 3) || (dot == -1);  /* filename contains
2089dab3f910Sjsing 							   * ".." component */
2090dab3f910Sjsing 
2091dab3f910Sjsing 			if (*e == '\0') {
2092dab3f910Sjsing 				BIO_puts(io, text);
20934da86b84Sinoguchi 				BIO_printf(io,
20944da86b84Sinoguchi 				    "'%s' is an invalid file name\r\n", p);
2095dab3f910Sjsing 				break;
2096dab3f910Sjsing 			}
2097dab3f910Sjsing 			*e = '\0';
2098dab3f910Sjsing 
2099dab3f910Sjsing 			if (dot) {
2100dab3f910Sjsing 				BIO_puts(io, text);
21014da86b84Sinoguchi 				BIO_printf(io,
21024da86b84Sinoguchi 				    "'%s' contains '..' reference\r\n", p);
2103dab3f910Sjsing 				break;
2104dab3f910Sjsing 			}
2105dab3f910Sjsing 			if (*p == '/') {
2106dab3f910Sjsing 				BIO_puts(io, text);
21074da86b84Sinoguchi 				BIO_printf(io,
21084da86b84Sinoguchi 				    "'%s' is an invalid path\r\n", p);
2109dab3f910Sjsing 				break;
2110dab3f910Sjsing 			}
2111dab3f910Sjsing 			/* if a directory, do the index thang */
2112dab3f910Sjsing 			if (app_isdir(p) > 0) {
2113dab3f910Sjsing 				BIO_puts(io, text);
2114dab3f910Sjsing 				BIO_printf(io, "'%s' is a directory\r\n", p);
2115dab3f910Sjsing 				break;
2116dab3f910Sjsing 			}
2117dab3f910Sjsing 			if ((file = BIO_new_file(p, "r")) == NULL) {
2118dab3f910Sjsing 				BIO_puts(io, text);
2119dab3f910Sjsing 				BIO_printf(io, "Error opening '%s'\r\n", p);
2120dab3f910Sjsing 				ERR_print_errors(io);
2121dab3f910Sjsing 				break;
2122dab3f910Sjsing 			}
2123e7718adaStb 			if (!cfg.quiet)
2124dab3f910Sjsing 				BIO_printf(bio_err, "FILE:%s\n", p);
2125dab3f910Sjsing 
2126e7718adaStb 			if (cfg.www == 2) {
2127dab3f910Sjsing 				i = strlen(p);
2128dab3f910Sjsing 				if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) ||
2129dab3f910Sjsing 				    ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) ||
2130dab3f910Sjsing 				    ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0)))
2131dab3f910Sjsing 					BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
2132dab3f910Sjsing 				else
2133dab3f910Sjsing 					BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
2134dab3f910Sjsing 			}
2135dab3f910Sjsing 			/* send the file */
2136dab3f910Sjsing 			for (;;) {
2137dab3f910Sjsing 				i = BIO_read(file, buf, bufsize);
2138dab3f910Sjsing 				if (i <= 0)
2139dab3f910Sjsing 					break;
2140dab3f910Sjsing 
2141dab3f910Sjsing #ifdef RENEG
2142dab3f910Sjsing 				total_bytes += i;
2143dab3f910Sjsing 				fprintf(stderr, "%d\n", i);
2144dab3f910Sjsing 				if (total_bytes > 3 * 1024) {
2145dab3f910Sjsing 					total_bytes = 0;
2146dab3f910Sjsing 					fprintf(stderr, "RENEGOTIATE\n");
2147dab3f910Sjsing 					SSL_renegotiate(con);
2148dab3f910Sjsing 				}
2149dab3f910Sjsing #endif
2150dab3f910Sjsing 
2151dab3f910Sjsing 				for (j = 0; j < i;) {
2152dab3f910Sjsing #ifdef RENEG
2153dab3f910Sjsing 					{
2154dab3f910Sjsing 						static count = 0;
2155dab3f910Sjsing 						if (++count == 13) {
2156dab3f910Sjsing 							SSL_renegotiate(con);
2157dab3f910Sjsing 						}
2158dab3f910Sjsing 					}
2159dab3f910Sjsing #endif
2160dab3f910Sjsing 					k = BIO_write(io, &(buf[j]), i - j);
2161dab3f910Sjsing 					if (k <= 0) {
2162dab3f910Sjsing 						if (!BIO_should_retry(io))
2163dab3f910Sjsing 							goto write_error;
2164dab3f910Sjsing 						else {
21654da86b84Sinoguchi 							BIO_printf(bio_s_out,
21664da86b84Sinoguchi 							    "rwrite W BLOCK\n");
2167dab3f910Sjsing 						}
2168dab3f910Sjsing 					} else {
2169dab3f910Sjsing 						j += k;
2170dab3f910Sjsing 					}
2171dab3f910Sjsing 				}
2172dab3f910Sjsing 			}
2173dab3f910Sjsing 	write_error:
2174dab3f910Sjsing 			BIO_free(file);
2175dab3f910Sjsing 			break;
2176dab3f910Sjsing 		}
2177dab3f910Sjsing 	}
2178dab3f910Sjsing 
2179dab3f910Sjsing 	for (;;) {
2180dab3f910Sjsing 		i = (int) BIO_flush(io);
2181dab3f910Sjsing 		if (i <= 0) {
2182dab3f910Sjsing 			if (!BIO_should_retry(io))
2183dab3f910Sjsing 				break;
2184dab3f910Sjsing 		} else
2185dab3f910Sjsing 			break;
2186dab3f910Sjsing 	}
2187dab3f910Sjsing  end:
2188dab3f910Sjsing 	/* make sure we re-use sessions */
2189dab3f910Sjsing 	SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
2190dab3f910Sjsing 
2191dab3f910Sjsing  err:
2192dab3f910Sjsing 
2193dab3f910Sjsing 	if (ret >= 0)
2194dab3f910Sjsing 		BIO_printf(bio_s_out, "ACCEPT\n");
2195dab3f910Sjsing 
2196dab3f910Sjsing 	free(buf);
2197dab3f910Sjsing 	BIO_free_all(io);
2198dab3f910Sjsing /*	if (ssl_bio != NULL) BIO_free(ssl_bio);*/
2199dab3f910Sjsing 	return (ret);
2200dab3f910Sjsing }
2201dab3f910Sjsing 
2202dab3f910Sjsing #define MAX_SESSION_ID_ATTEMPTS 10
2203dab3f910Sjsing static int
220472a107cfSinoguchi generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len)
2205dab3f910Sjsing {
2206dab3f910Sjsing 	unsigned int count = 0;
2207dab3f910Sjsing 	do {
2208fd6ab616Sjsing 		arc4random_buf(id, *id_len);
2209dab3f910Sjsing 		/*
2210dab3f910Sjsing 		 * Prefix the session_id with the required prefix. NB: If our
2211dab3f910Sjsing 		 * prefix is too long, clip it - but there will be worse
2212dab3f910Sjsing 		 * effects anyway, eg. the server could only possibly create
2213dab3f910Sjsing 		 * 1 session ID (ie. the prefix!) so all future session
2214dab3f910Sjsing 		 * negotiations will fail due to conflicts.
2215dab3f910Sjsing 		 */
2216e7718adaStb 		memcpy(id, cfg.session_id_prefix,
2217e7718adaStb 		    (strlen(cfg.session_id_prefix) < *id_len) ?
2218e7718adaStb 		    strlen(cfg.session_id_prefix) : *id_len);
2219dab3f910Sjsing 	}
2220dab3f910Sjsing 	while (SSL_has_matching_session_id(ssl, id, *id_len) &&
2221dab3f910Sjsing 	    (++count < MAX_SESSION_ID_ATTEMPTS));
2222dab3f910Sjsing 	if (count >= MAX_SESSION_ID_ATTEMPTS)
2223dab3f910Sjsing 		return 0;
2224dab3f910Sjsing 	return 1;
2225dab3f910Sjsing }
222672a107cfSinoguchi 
222772a107cfSinoguchi static int
222872a107cfSinoguchi ssl_servername_cb(SSL *s, int *ad, void *arg)
222972a107cfSinoguchi {
223072a107cfSinoguchi 	tlsextctx *p = (tlsextctx *) arg;
22314da86b84Sinoguchi 	const char *servername = SSL_get_servername(s,
22324da86b84Sinoguchi 	    TLSEXT_NAMETYPE_host_name);
22334da86b84Sinoguchi 
223472a107cfSinoguchi 	if (servername && p->biodebug)
22354da86b84Sinoguchi 		BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n",
22364da86b84Sinoguchi 		    servername);
223772a107cfSinoguchi 
223872a107cfSinoguchi 	if (!p->servername)
223972a107cfSinoguchi 		return SSL_TLSEXT_ERR_NOACK;
224072a107cfSinoguchi 
224172a107cfSinoguchi 	if (servername) {
224272a107cfSinoguchi 		if (strcmp(servername, p->servername))
224372a107cfSinoguchi 			return p->extension_error;
224472a107cfSinoguchi 		if (ctx2) {
224572a107cfSinoguchi 			BIO_printf(p->biodebug, "Switching server context.\n");
224672a107cfSinoguchi 			SSL_set_SSL_CTX(s, ctx2);
224772a107cfSinoguchi 		}
224872a107cfSinoguchi 	}
224972a107cfSinoguchi 	return SSL_TLSEXT_ERR_OK;
225072a107cfSinoguchi }
225172a107cfSinoguchi 
225272a107cfSinoguchi /* Certificate Status callback. This is called when a client includes a
225372a107cfSinoguchi  * certificate status request extension.
225472a107cfSinoguchi  *
225572a107cfSinoguchi  * This is a simplified version. It examines certificates each time and
225672a107cfSinoguchi  * makes one OCSP responder query for each request.
225772a107cfSinoguchi  *
225872a107cfSinoguchi  * A full version would store details such as the OCSP certificate IDs and
225972a107cfSinoguchi  * minimise the number of OCSP responses by caching them until they were
226072a107cfSinoguchi  * considered "expired".
226172a107cfSinoguchi  */
226272a107cfSinoguchi 
226372a107cfSinoguchi static int
226472a107cfSinoguchi cert_status_cb(SSL *s, void *arg)
226572a107cfSinoguchi {
226672a107cfSinoguchi 	tlsextstatusctx *srctx = arg;
226772a107cfSinoguchi 	BIO *err = srctx->err;
226872a107cfSinoguchi 	char *host = NULL, *port = NULL, *path = NULL;
226972a107cfSinoguchi 	int use_ssl;
227072a107cfSinoguchi 	unsigned char *rspder = NULL;
227172a107cfSinoguchi 	int rspderlen;
227272a107cfSinoguchi 	STACK_OF(OPENSSL_STRING) *aia = NULL;
227372a107cfSinoguchi 	X509 *x = NULL;
2274dfa067d0Stb 	X509_STORE_CTX *inctx = NULL;
22753d522683Stb 	X509_OBJECT *obj = NULL;
227672a107cfSinoguchi 	OCSP_REQUEST *req = NULL;
227772a107cfSinoguchi 	OCSP_RESPONSE *resp = NULL;
227872a107cfSinoguchi 	OCSP_CERTID *id = NULL;
227972a107cfSinoguchi 	STACK_OF(X509_EXTENSION) *exts;
228072a107cfSinoguchi 	int ret = SSL_TLSEXT_ERR_NOACK;
228172a107cfSinoguchi 	int i;
228272a107cfSinoguchi 
228372a107cfSinoguchi 	if (srctx->verbose)
228472a107cfSinoguchi 		BIO_puts(err, "cert_status: callback called\n");
228572a107cfSinoguchi 	/* Build up OCSP query from server certificate */
228672a107cfSinoguchi 	x = SSL_get_certificate(s);
228772a107cfSinoguchi 	aia = X509_get1_ocsp(x);
228872a107cfSinoguchi 	if (aia) {
228972a107cfSinoguchi 		if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
229072a107cfSinoguchi 		    &host, &port, &path, &use_ssl)) {
229172a107cfSinoguchi 			BIO_puts(err, "cert_status: can't parse AIA URL\n");
229272a107cfSinoguchi 			goto err;
229372a107cfSinoguchi 		}
229472a107cfSinoguchi 		if (srctx->verbose)
229572a107cfSinoguchi 			BIO_printf(err, "cert_status: AIA URL: %s\n",
229672a107cfSinoguchi 			    sk_OPENSSL_STRING_value(aia, 0));
229772a107cfSinoguchi 	} else {
229872a107cfSinoguchi 		if (!srctx->host) {
22994da86b84Sinoguchi 			BIO_puts(srctx->err,
23004da86b84Sinoguchi 			    "cert_status: no AIA and no default responder URL\n");
230172a107cfSinoguchi 			goto done;
230272a107cfSinoguchi 		}
230372a107cfSinoguchi 		host = srctx->host;
230472a107cfSinoguchi 		path = srctx->path;
230572a107cfSinoguchi 		port = srctx->port;
230672a107cfSinoguchi 		use_ssl = srctx->use_ssl;
230772a107cfSinoguchi 	}
230872a107cfSinoguchi 
2309dfa067d0Stb 	if ((inctx = X509_STORE_CTX_new()) == NULL)
2310dfa067d0Stb 		goto err;
2311dfa067d0Stb 
2312dfa067d0Stb 	if (!X509_STORE_CTX_init(inctx,
231372a107cfSinoguchi 	    SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
231472a107cfSinoguchi 		NULL, NULL))
231572a107cfSinoguchi 		goto err;
23163d522683Stb 	if ((obj = X509_OBJECT_new()) == NULL)
23173d522683Stb 		goto done;
2318dfa067d0Stb 	if (X509_STORE_get_by_subject(inctx, X509_LU_X509,
23193d522683Stb 	    X509_get_issuer_name(x), obj) <= 0) {
23204da86b84Sinoguchi 		BIO_puts(err,
23214da86b84Sinoguchi 		    "cert_status: Can't retrieve issuer certificate.\n");
2322dfa067d0Stb 		X509_STORE_CTX_cleanup(inctx);
232372a107cfSinoguchi 		goto done;
232472a107cfSinoguchi 	}
232572a107cfSinoguchi 	req = OCSP_REQUEST_new();
232672a107cfSinoguchi 	if (!req)
232772a107cfSinoguchi 		goto err;
23283d522683Stb 	id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
23293d522683Stb 	X509_OBJECT_free(obj);
23303d522683Stb 	obj = NULL;
2331dfa067d0Stb 	X509_STORE_CTX_free(inctx);
2332dfa067d0Stb 	inctx = NULL;
233372a107cfSinoguchi 	if (!id)
233472a107cfSinoguchi 		goto err;
233572a107cfSinoguchi 	if (!OCSP_request_add0_id(req, id))
233672a107cfSinoguchi 		goto err;
233772a107cfSinoguchi 	id = NULL;
233872a107cfSinoguchi 	/* Add any extensions to the request */
233972a107cfSinoguchi 	SSL_get_tlsext_status_exts(s, &exts);
234072a107cfSinoguchi 	for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
234172a107cfSinoguchi 		X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
234272a107cfSinoguchi 		if (!OCSP_REQUEST_add_ext(req, ext, -1))
234372a107cfSinoguchi 			goto err;
234472a107cfSinoguchi 	}
234572a107cfSinoguchi 	resp = process_responder(err, req, host, path, port, use_ssl, NULL,
234672a107cfSinoguchi 	    srctx->timeout);
234772a107cfSinoguchi 	if (!resp) {
234872a107cfSinoguchi 		BIO_puts(err, "cert_status: error querying responder\n");
234972a107cfSinoguchi 		goto done;
235072a107cfSinoguchi 	}
235172a107cfSinoguchi 	rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
235272a107cfSinoguchi 	if (rspderlen <= 0)
235372a107cfSinoguchi 		goto err;
235472a107cfSinoguchi 	SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
235572a107cfSinoguchi 	if (srctx->verbose) {
235672a107cfSinoguchi 		BIO_puts(err, "cert_status: ocsp response sent:\n");
235772a107cfSinoguchi 		OCSP_RESPONSE_print(err, resp, 2);
235872a107cfSinoguchi 	}
235972a107cfSinoguchi 	ret = SSL_TLSEXT_ERR_OK;
236072a107cfSinoguchi  done:
2361dfa067d0Stb 	X509_STORE_CTX_free(inctx);
23623d522683Stb 	X509_OBJECT_free(obj);
236372a107cfSinoguchi 	if (ret != SSL_TLSEXT_ERR_OK)
236472a107cfSinoguchi 		ERR_print_errors(err);
236572a107cfSinoguchi 	if (aia) {
236672a107cfSinoguchi 		free(host);
236772a107cfSinoguchi 		free(path);
236872a107cfSinoguchi 		free(port);
236972a107cfSinoguchi 		X509_email_free(aia);
237072a107cfSinoguchi 	}
237172a107cfSinoguchi 	if (id)
237272a107cfSinoguchi 		OCSP_CERTID_free(id);
237372a107cfSinoguchi 	if (req)
237472a107cfSinoguchi 		OCSP_REQUEST_free(req);
237572a107cfSinoguchi 	if (resp)
237672a107cfSinoguchi 		OCSP_RESPONSE_free(resp);
237772a107cfSinoguchi 	return ret;
237872a107cfSinoguchi  err:
237972a107cfSinoguchi 	ret = SSL_TLSEXT_ERR_ALERT_FATAL;
238072a107cfSinoguchi 	goto done;
238172a107cfSinoguchi }
238272a107cfSinoguchi 
238372a107cfSinoguchi static int
238472a107cfSinoguchi alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
238572a107cfSinoguchi     const unsigned char *in, unsigned int inlen, void *arg)
238672a107cfSinoguchi {
238772a107cfSinoguchi 	tlsextalpnctx *alpn_ctx = arg;
238872a107cfSinoguchi 
2389e7718adaStb 	if (!cfg.quiet) {
239072a107cfSinoguchi 		/* We can assume that in is syntactically valid. */
239172a107cfSinoguchi 		unsigned i;
239272a107cfSinoguchi 
239372a107cfSinoguchi 		BIO_printf(bio_s_out,
239472a107cfSinoguchi 		    "ALPN protocols advertised by the client: ");
239572a107cfSinoguchi 		for (i = 0; i < inlen; ) {
239672a107cfSinoguchi 			if (i)
239772a107cfSinoguchi 				BIO_write(bio_s_out, ", ", 2);
239872a107cfSinoguchi 			BIO_write(bio_s_out, &in[i + 1], in[i]);
239972a107cfSinoguchi 			i += in[i] + 1;
240072a107cfSinoguchi 		}
240172a107cfSinoguchi 		BIO_write(bio_s_out, "\n", 1);
240272a107cfSinoguchi 	}
240372a107cfSinoguchi 
240472a107cfSinoguchi 	if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data,
240572a107cfSinoguchi 	    alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED)
240672a107cfSinoguchi 		return (SSL_TLSEXT_ERR_NOACK);
240772a107cfSinoguchi 
2408e7718adaStb 	if (!cfg.quiet) {
240972a107cfSinoguchi 		BIO_printf(bio_s_out, "ALPN protocols selected: ");
241072a107cfSinoguchi 		BIO_write(bio_s_out, *out, *outlen);
241172a107cfSinoguchi 		BIO_write(bio_s_out, "\n", 1);
241272a107cfSinoguchi 	}
241372a107cfSinoguchi 
241472a107cfSinoguchi 	return (SSL_TLSEXT_ERR_OK);
241572a107cfSinoguchi }
2416