diff options
Diffstat (limited to 'src/usr.bin/openssl/s_server.c')
-rw-r--r-- | src/usr.bin/openssl/s_server.c | 2415 |
1 files changed, 0 insertions, 2415 deletions
diff --git a/src/usr.bin/openssl/s_server.c b/src/usr.bin/openssl/s_server.c deleted file mode 100644 index f56042a4b4..0000000000 --- a/src/usr.bin/openssl/s_server.c +++ /dev/null | |||
@@ -1,2415 +0,0 @@ | |||
1 | /* $OpenBSD: s_server.c,v 1.61 2025/01/02 13:10:03 tb Exp $ */ | ||
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This package is an SSL implementation written | ||
6 | * by Eric Young (eay@cryptsoft.com). | ||
7 | * The implementation was written so as to conform with Netscapes SSL. | ||
8 | * | ||
9 | * This library is free for commercial and non-commercial use as long as | ||
10 | * the following conditions are aheared to. The following conditions | ||
11 | * apply to all code found in this distribution, be it the RC4, RSA, | ||
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | ||
13 | * included with this distribution is covered by the same copyright terms | ||
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | ||
15 | * | ||
16 | * Copyright remains Eric Young's, and as such any Copyright notices in | ||
17 | * the code are not to be removed. | ||
18 | * If this package is used in a product, Eric Young should be given attribution | ||
19 | * as the author of the parts of the library used. | ||
20 | * This can be in the form of a textual message at program startup or | ||
21 | * in documentation (online or textual) provided with the package. | ||
22 | * | ||
23 | * Redistribution and use in source and binary forms, with or without | ||
24 | * modification, are permitted provided that the following conditions | ||
25 | * are met: | ||
26 | * 1. Redistributions of source code must retain the copyright | ||
27 | * notice, this list of conditions and the following disclaimer. | ||
28 | * 2. Redistributions in binary form must reproduce the above copyright | ||
29 | * notice, this list of conditions and the following disclaimer in the | ||
30 | * documentation and/or other materials provided with the distribution. | ||
31 | * 3. All advertising materials mentioning features or use of this software | ||
32 | * must display the following acknowledgement: | ||
33 | * "This product includes cryptographic software written by | ||
34 | * Eric Young (eay@cryptsoft.com)" | ||
35 | * The word 'cryptographic' can be left out if the rouines from the library | ||
36 | * being used are not cryptographic related :-). | ||
37 | * 4. If you include any Windows specific code (or a derivative thereof) from | ||
38 | * the apps directory (application code) you must include an acknowledgement: | ||
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | ||
40 | * | ||
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | ||
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
51 | * SUCH DAMAGE. | ||
52 | * | ||
53 | * The licence and distribution terms for any publically available version or | ||
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be | ||
55 | * copied and put under another distribution licence | ||
56 | * [including the GNU Public Licence.] | ||
57 | */ | ||
58 | /* ==================================================================== | ||
59 | * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. | ||
60 | * | ||
61 | * Redistribution and use in source and binary forms, with or without | ||
62 | * modification, are permitted provided that the following conditions | ||
63 | * are met: | ||
64 | * | ||
65 | * 1. Redistributions of source code must retain the above copyright | ||
66 | * notice, this list of conditions and the following disclaimer. | ||
67 | * | ||
68 | * 2. Redistributions in binary form must reproduce the above copyright | ||
69 | * notice, this list of conditions and the following disclaimer in | ||
70 | * the documentation and/or other materials provided with the | ||
71 | * distribution. | ||
72 | * | ||
73 | * 3. All advertising materials mentioning features or use of this | ||
74 | * software must display the following acknowledgment: | ||
75 | * "This product includes software developed by the OpenSSL Project | ||
76 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | ||
77 | * | ||
78 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
79 | * endorse or promote products derived from this software without | ||
80 | * prior written permission. For written permission, please contact | ||
81 | * openssl-core@openssl.org. | ||
82 | * | ||
83 | * 5. Products derived from this software may not be called "OpenSSL" | ||
84 | * nor may "OpenSSL" appear in their names without prior written | ||
85 | * permission of the OpenSSL Project. | ||
86 | * | ||
87 | * 6. Redistributions of any form whatsoever must retain the following | ||
88 | * acknowledgment: | ||
89 | * "This product includes software developed by the OpenSSL Project | ||
90 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | ||
91 | * | ||
92 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
93 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
94 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
95 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
96 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
97 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
98 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
99 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
100 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
101 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
102 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
103 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
104 | * ==================================================================== | ||
105 | * | ||
106 | * This product includes cryptographic software written by Eric Young | ||
107 | * (eay@cryptsoft.com). This product includes software written by Tim | ||
108 | * Hudson (tjh@cryptsoft.com). | ||
109 | * | ||
110 | */ | ||
111 | /* ==================================================================== | ||
112 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | ||
113 | * ECC cipher suite support in OpenSSL originally developed by | ||
114 | * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. | ||
115 | */ | ||
116 | /* ==================================================================== | ||
117 | * Copyright 2005 Nokia. All rights reserved. | ||
118 | * | ||
119 | * The portions of the attached software ("Contribution") is developed by | ||
120 | * Nokia Corporation and is licensed pursuant to the OpenSSL open source | ||
121 | * license. | ||
122 | * | ||
123 | * The Contribution, originally written by Mika Kousa and Pasi Eronen of | ||
124 | * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites | ||
125 | * support (see RFC 4279) to OpenSSL. | ||
126 | * | ||
127 | * No patent licenses or other rights except those expressly stated in | ||
128 | * the OpenSSL open source license shall be deemed granted or received | ||
129 | * expressly, by implication, estoppel, or otherwise. | ||
130 | * | ||
131 | * No assurances are provided by Nokia that the Contribution does not | ||
132 | * infringe the patent or other intellectual property rights of any third | ||
133 | * party or that the license provides you with all the necessary rights | ||
134 | * to make use of the Contribution. | ||
135 | * | ||
136 | * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN | ||
137 | * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA | ||
138 | * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY | ||
139 | * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | ||
140 | * OTHERWISE. | ||
141 | */ | ||
142 | |||
143 | /* Until the key-gen callbacks are modified to use newer prototypes, we allow | ||
144 | * deprecated functions for openssl-internal code */ | ||
145 | #ifdef OPENSSL_NO_DEPRECATED | ||
146 | #undef OPENSSL_NO_DEPRECATED | ||
147 | #endif | ||
148 | |||
149 | #include <sys/types.h> | ||
150 | #include <sys/socket.h> | ||
151 | |||
152 | #include <assert.h> | ||
153 | #include <ctype.h> | ||
154 | #include <stdio.h> | ||
155 | #include <stdlib.h> | ||
156 | #include <limits.h> | ||
157 | #include <string.h> | ||
158 | #include <unistd.h> | ||
159 | #include <poll.h> | ||
160 | |||
161 | #include "apps.h" | ||
162 | |||
163 | #include <openssl/bn.h> | ||
164 | #include <openssl/err.h> | ||
165 | #include <openssl/lhash.h> | ||
166 | #include <openssl/ocsp.h> | ||
167 | #include <openssl/pem.h> | ||
168 | #include <openssl/ssl.h> | ||
169 | #include <openssl/x509.h> | ||
170 | |||
171 | #ifndef OPENSSL_NO_DH | ||
172 | #include <openssl/dh.h> | ||
173 | #endif | ||
174 | |||
175 | #include <openssl/rsa.h> | ||
176 | |||
177 | static void s_server_init(void); | ||
178 | static void sv_usage(void); | ||
179 | static void print_stats(BIO *bp, SSL_CTX *ctx); | ||
180 | static int sv_body(int s, unsigned char *context); | ||
181 | static void close_accept_socket(void); | ||
182 | static int init_ssl_connection(SSL *s); | ||
183 | #ifndef OPENSSL_NO_DH | ||
184 | static DH *load_dh_param(const char *dhfile); | ||
185 | #endif | ||
186 | static int www_body(int s, unsigned char *context); | ||
187 | static int generate_session_id(const SSL *ssl, unsigned char *id, | ||
188 | unsigned int *id_len); | ||
189 | static int ssl_servername_cb(SSL *s, int *ad, void *arg); | ||
190 | static int cert_status_cb(SSL * s, void *arg); | ||
191 | static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
192 | const unsigned char *in, unsigned int inlen, void *arg); | ||
193 | /* static int load_CA(SSL_CTX *ctx, char *file);*/ | ||
194 | |||
195 | #define BUFSIZZ 16*1024 | ||
196 | static int bufsize = BUFSIZZ; | ||
197 | static int accept_socket = -1; | ||
198 | |||
199 | #define TEST_CERT "server.pem" | ||
200 | #define TEST_CERT2 "server2.pem" | ||
201 | |||
202 | static int s_server_session_id_context = 1; /* anything will do */ | ||
203 | static SSL_CTX *ctx = NULL; | ||
204 | static SSL_CTX *ctx2 = NULL; | ||
205 | static BIO *bio_s_out = NULL; | ||
206 | |||
207 | static int local_argc = 0; | ||
208 | static char **local_argv; | ||
209 | |||
210 | /* This is a context that we pass to callbacks */ | ||
211 | typedef struct tlsextctx_st { | ||
212 | char *servername; | ||
213 | BIO *biodebug; | ||
214 | int extension_error; | ||
215 | } tlsextctx; | ||
216 | |||
217 | /* Structure passed to cert status callback */ | ||
218 | typedef struct tlsextstatusctx_st { | ||
219 | /* Default responder to use */ | ||
220 | char *host, *path, *port; | ||
221 | int use_ssl; | ||
222 | int timeout; | ||
223 | BIO *err; | ||
224 | int verbose; | ||
225 | } tlsextstatusctx; | ||
226 | |||
227 | /* This the context that we pass to alpn_cb */ | ||
228 | typedef struct tlsextalpnctx_st { | ||
229 | unsigned char *data; | ||
230 | unsigned short len; | ||
231 | } tlsextalpnctx; | ||
232 | |||
233 | static struct { | ||
234 | char *alpn_in; | ||
235 | char *npn_in; /* Ignored. */ | ||
236 | int bugs; | ||
237 | char *CAfile; | ||
238 | char *CApath; | ||
239 | #ifndef OPENSSL_NO_DTLS | ||
240 | int cert_chain; | ||
241 | #endif | ||
242 | char *cert_file; | ||
243 | char *cert_file2; | ||
244 | int cert_format; | ||
245 | char *cipher; | ||
246 | unsigned char *context; | ||
247 | int crlf; | ||
248 | char *dcert_file; | ||
249 | int dcert_format; | ||
250 | int debug; | ||
251 | char *dhfile; | ||
252 | char *dkey_file; | ||
253 | int dkey_format; | ||
254 | char *dpassarg; | ||
255 | int enable_timeouts; | ||
256 | const char *errstr; | ||
257 | char *groups_in; | ||
258 | char *key_file; | ||
259 | char *key_file2; | ||
260 | int key_format; | ||
261 | char *keymatexportlabel; | ||
262 | int keymatexportlen; | ||
263 | uint16_t max_version; | ||
264 | uint16_t min_version; | ||
265 | const SSL_METHOD *meth; | ||
266 | int msg; | ||
267 | int naccept; | ||
268 | char *named_curve; | ||
269 | int nbio; | ||
270 | int nbio_test; | ||
271 | int no_cache; | ||
272 | int nocert; | ||
273 | int no_dhe; | ||
274 | int no_ecdhe; | ||
275 | int no_tmp_rsa; /* No-op. */ | ||
276 | int off; | ||
277 | char *passarg; | ||
278 | short port; | ||
279 | int quiet; | ||
280 | int server_verify; | ||
281 | char *session_id_prefix; | ||
282 | long socket_mtu; | ||
283 | int socket_type; | ||
284 | #ifndef OPENSSL_NO_SRTP | ||
285 | char *srtp_profiles; | ||
286 | #endif | ||
287 | int state; | ||
288 | tlsextstatusctx tlscstatp; | ||
289 | tlsextctx tlsextcbp; | ||
290 | int tlsextdebug; | ||
291 | int tlsextstatus; | ||
292 | X509_VERIFY_PARAM *vpm; | ||
293 | int www; | ||
294 | } cfg; | ||
295 | |||
296 | static int | ||
297 | s_server_opt_context(char *arg) | ||
298 | { | ||
299 | cfg.context = (unsigned char *) arg; | ||
300 | return (0); | ||
301 | } | ||
302 | |||
303 | static int | ||
304 | s_server_opt_keymatexportlen(char *arg) | ||
305 | { | ||
306 | cfg.keymatexportlen = strtonum(arg, 1, INT_MAX, | ||
307 | &cfg.errstr); | ||
308 | if (cfg.errstr != NULL) { | ||
309 | BIO_printf(bio_err, "invalid argument %s: %s\n", | ||
310 | arg, cfg.errstr); | ||
311 | return (1); | ||
312 | } | ||
313 | return (0); | ||
314 | } | ||
315 | |||
316 | #ifndef OPENSSL_NO_DTLS | ||
317 | static int | ||
318 | s_server_opt_mtu(char *arg) | ||
319 | { | ||
320 | cfg.socket_mtu = strtonum(arg, 0, LONG_MAX, | ||
321 | &cfg.errstr); | ||
322 | if (cfg.errstr != NULL) { | ||
323 | BIO_printf(bio_err, "invalid argument %s: %s\n", | ||
324 | arg, cfg.errstr); | ||
325 | return (1); | ||
326 | } | ||
327 | return (0); | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | #ifndef OPENSSL_NO_DTLS | ||
332 | static int | ||
333 | s_server_opt_protocol_version_dtls(void) | ||
334 | { | ||
335 | cfg.meth = DTLS_server_method(); | ||
336 | cfg.socket_type = SOCK_DGRAM; | ||
337 | return (0); | ||
338 | } | ||
339 | #endif | ||
340 | |||
341 | #ifndef OPENSSL_NO_DTLS1_2 | ||
342 | static int | ||
343 | s_server_opt_protocol_version_dtls1_2(void) | ||
344 | { | ||
345 | cfg.meth = DTLS_server_method(); | ||
346 | cfg.min_version = DTLS1_2_VERSION; | ||
347 | cfg.max_version = DTLS1_2_VERSION; | ||
348 | cfg.socket_type = SOCK_DGRAM; | ||
349 | return (0); | ||
350 | } | ||
351 | #endif | ||
352 | |||
353 | static int | ||
354 | s_server_opt_protocol_version_tls1_2(void) | ||
355 | { | ||
356 | cfg.min_version = TLS1_2_VERSION; | ||
357 | cfg.max_version = TLS1_2_VERSION; | ||
358 | return (0); | ||
359 | } | ||
360 | |||
361 | static int | ||
362 | s_server_opt_protocol_version_tls1_3(void) | ||
363 | { | ||
364 | cfg.min_version = TLS1_3_VERSION; | ||
365 | cfg.max_version = TLS1_3_VERSION; | ||
366 | return (0); | ||
367 | } | ||
368 | |||
369 | static int | ||
370 | s_server_opt_nbio_test(void) | ||
371 | { | ||
372 | cfg.nbio = 1; | ||
373 | cfg.nbio_test = 1; | ||
374 | return (0); | ||
375 | } | ||
376 | |||
377 | static int | ||
378 | s_server_opt_port(char *arg) | ||
379 | { | ||
380 | if (!extract_port(arg, &cfg.port)) | ||
381 | return (1); | ||
382 | return (0); | ||
383 | } | ||
384 | |||
385 | static int | ||
386 | s_server_opt_status_timeout(char *arg) | ||
387 | { | ||
388 | cfg.tlsextstatus = 1; | ||
389 | cfg.tlscstatp.timeout = strtonum(arg, 0, INT_MAX, | ||
390 | &cfg.errstr); | ||
391 | if (cfg.errstr != NULL) { | ||
392 | BIO_printf(bio_err, "invalid argument %s: %s\n", | ||
393 | arg, cfg.errstr); | ||
394 | return (1); | ||
395 | } | ||
396 | return (0); | ||
397 | } | ||
398 | |||
399 | static int | ||
400 | s_server_opt_status_url(char *arg) | ||
401 | { | ||
402 | cfg.tlsextstatus = 1; | ||
403 | if (!OCSP_parse_url(arg, &cfg.tlscstatp.host, | ||
404 | &cfg.tlscstatp.port, &cfg.tlscstatp.path, | ||
405 | &cfg.tlscstatp.use_ssl)) { | ||
406 | BIO_printf(bio_err, "Error parsing URL\n"); | ||
407 | return (1); | ||
408 | } | ||
409 | return (0); | ||
410 | } | ||
411 | |||
412 | static int | ||
413 | s_server_opt_status_verbose(void) | ||
414 | { | ||
415 | cfg.tlsextstatus = 1; | ||
416 | cfg.tlscstatp.verbose = 1; | ||
417 | return (0); | ||
418 | } | ||
419 | |||
420 | static int | ||
421 | s_server_opt_verify(char *arg) | ||
422 | { | ||
423 | cfg.server_verify = SSL_VERIFY_PEER | | ||
424 | SSL_VERIFY_CLIENT_ONCE; | ||
425 | verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); | ||
426 | if (cfg.errstr != NULL) { | ||
427 | BIO_printf(bio_err, "invalid argument %s: %s\n", | ||
428 | arg, cfg.errstr); | ||
429 | return (1); | ||
430 | } | ||
431 | BIO_printf(bio_err, "verify depth is %d\n", verify_depth); | ||
432 | return (0); | ||
433 | } | ||
434 | |||
435 | static int | ||
436 | s_server_opt_verify_fail(char *arg) | ||
437 | { | ||
438 | cfg.server_verify = SSL_VERIFY_PEER | | ||
439 | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; | ||
440 | verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); | ||
441 | if (cfg.errstr != NULL) { | ||
442 | BIO_printf(bio_err, "invalid argument %s: %s\n", | ||
443 | arg, cfg.errstr); | ||
444 | return (1); | ||
445 | } | ||
446 | BIO_printf(bio_err, "verify depth is %d, must return a certificate\n", | ||
447 | verify_depth); | ||
448 | return (0); | ||
449 | } | ||
450 | |||
451 | static int | ||
452 | s_server_opt_verify_param(int argc, char **argv, int *argsused) | ||
453 | { | ||
454 | char **pargs = argv; | ||
455 | int pargc = argc; | ||
456 | int badarg = 0; | ||
457 | |||
458 | if (!args_verify(&pargs, &pargc, &badarg, bio_err, | ||
459 | &cfg.vpm)) { | ||
460 | BIO_printf(bio_err, "unknown option %s\n", *argv); | ||
461 | return (1); | ||
462 | } | ||
463 | if (badarg) | ||
464 | return (1); | ||
465 | |||
466 | *argsused = argc - pargc; | ||
467 | return (0); | ||
468 | } | ||
469 | |||
470 | static const struct option s_server_options[] = { | ||
471 | { | ||
472 | .name = "4", | ||
473 | .type = OPTION_DISCARD, | ||
474 | }, | ||
475 | { | ||
476 | .name = "6", | ||
477 | .type = OPTION_DISCARD, | ||
478 | }, | ||
479 | { | ||
480 | .name = "accept", | ||
481 | .argname = "port", | ||
482 | .desc = "Port to accept on (default is 4433)", | ||
483 | .type = OPTION_ARG_FUNC, | ||
484 | .opt.argfunc = s_server_opt_port, | ||
485 | }, | ||
486 | { | ||
487 | .name = "alpn", | ||
488 | .argname = "protocols", | ||
489 | .desc = "Set the advertised protocols for the ALPN extension" | ||
490 | " (comma-separated list)", | ||
491 | .type = OPTION_ARG, | ||
492 | .opt.arg = &cfg.alpn_in, | ||
493 | }, | ||
494 | { | ||
495 | .name = "bugs", | ||
496 | .desc = "Turn on SSL bug compatibility", | ||
497 | .type = OPTION_FLAG, | ||
498 | .opt.flag = &cfg.bugs, | ||
499 | }, | ||
500 | { | ||
501 | .name = "CAfile", | ||
502 | .argname = "file", | ||
503 | .desc = "PEM format file of CA certificates", | ||
504 | .type = OPTION_ARG, | ||
505 | .opt.arg = &cfg.CAfile, | ||
506 | }, | ||
507 | { | ||
508 | .name = "CApath", | ||
509 | .argname = "directory", | ||
510 | .desc = "PEM format directory of CA certificates", | ||
511 | .type = OPTION_ARG, | ||
512 | .opt.arg = &cfg.CApath, | ||
513 | }, | ||
514 | { | ||
515 | .name = "cert", | ||
516 | .argname = "file", | ||
517 | .desc = "Certificate file to use\n" | ||
518 | "(default is " TEST_CERT ")", | ||
519 | .type = OPTION_ARG, | ||
520 | .opt.arg = &cfg.cert_file, | ||
521 | }, | ||
522 | { | ||
523 | .name = "cert2", | ||
524 | .argname = "file", | ||
525 | .desc = "Certificate file to use for servername\n" | ||
526 | "(default is " TEST_CERT2 ")", | ||
527 | .type = OPTION_ARG, | ||
528 | .opt.arg = &cfg.cert_file2, | ||
529 | }, | ||
530 | { | ||
531 | .name = "certform", | ||
532 | .argname = "fmt", | ||
533 | .desc = "Certificate format (PEM or DER) PEM default", | ||
534 | .type = OPTION_ARG_FORMAT, | ||
535 | .opt.value = &cfg.cert_format, | ||
536 | }, | ||
537 | #ifndef OPENSSL_NO_DTLS | ||
538 | { | ||
539 | .name = "chain", | ||
540 | .type = OPTION_FLAG, | ||
541 | .opt.flag = &cfg.cert_chain, | ||
542 | }, | ||
543 | #endif | ||
544 | { | ||
545 | .name = "cipher", | ||
546 | .argname = "list", | ||
547 | .desc = "List of ciphers to enable (see `openssl ciphers`)", | ||
548 | .type = OPTION_ARG, | ||
549 | .opt.arg = &cfg.cipher, | ||
550 | }, | ||
551 | { | ||
552 | .name = "context", | ||
553 | .argname = "id", | ||
554 | .desc = "Set session ID context", | ||
555 | .type = OPTION_ARG_FUNC, | ||
556 | .opt.argfunc = s_server_opt_context, | ||
557 | }, | ||
558 | { | ||
559 | .name = "crlf", | ||
560 | .desc = "Convert LF from terminal into CRLF", | ||
561 | .type = OPTION_FLAG, | ||
562 | .opt.flag = &cfg.crlf, | ||
563 | }, | ||
564 | { | ||
565 | .name = "dcert", | ||
566 | .argname = "file", | ||
567 | .desc = "Second certificate file to use (usually for DSA)", | ||
568 | .type = OPTION_ARG, | ||
569 | .opt.arg = &cfg.dcert_file, | ||
570 | }, | ||
571 | { | ||
572 | .name = "dcertform", | ||
573 | .argname = "fmt", | ||
574 | .desc = "Second certificate format (PEM or DER) PEM default", | ||
575 | .type = OPTION_ARG_FORMAT, | ||
576 | .opt.value = &cfg.dcert_format, | ||
577 | }, | ||
578 | { | ||
579 | .name = "debug", | ||
580 | .desc = "Print more output", | ||
581 | .type = OPTION_FLAG, | ||
582 | .opt.flag = &cfg.debug, | ||
583 | }, | ||
584 | { | ||
585 | .name = "dhparam", | ||
586 | .argname = "file", | ||
587 | .desc = "DH parameter file to use, in cert file if not specified", | ||
588 | .type = OPTION_ARG, | ||
589 | .opt.arg = &cfg.dhfile, | ||
590 | }, | ||
591 | { | ||
592 | .name = "dkey", | ||
593 | .argname = "file", | ||
594 | .desc = "Second private key file to use (usually for DSA)", | ||
595 | .type = OPTION_ARG, | ||
596 | .opt.arg = &cfg.dkey_file, | ||
597 | }, | ||
598 | { | ||
599 | .name = "dkeyform", | ||
600 | .argname = "fmt", | ||
601 | .desc = "Second key format (PEM or DER) PEM default", | ||
602 | .type = OPTION_ARG_FORMAT, | ||
603 | .opt.value = &cfg.dkey_format, | ||
604 | }, | ||
605 | { | ||
606 | .name = "dpass", | ||
607 | .argname = "arg", | ||
608 | .desc = "Second private key file pass phrase source", | ||
609 | .type = OPTION_ARG, | ||
610 | .opt.arg = &cfg.dpassarg, | ||
611 | }, | ||
612 | #ifndef OPENSSL_NO_DTLS | ||
613 | { | ||
614 | .name = "dtls", | ||
615 | .desc = "Use any version of DTLS", | ||
616 | .type = OPTION_FUNC, | ||
617 | .opt.func = s_server_opt_protocol_version_dtls, | ||
618 | }, | ||
619 | #endif | ||
620 | #ifndef OPENSSL_NO_DTLS1_2 | ||
621 | { | ||
622 | .name = "dtls1_2", | ||
623 | .desc = "Just use DTLSv1.2", | ||
624 | .type = OPTION_FUNC, | ||
625 | .opt.func = s_server_opt_protocol_version_dtls1_2, | ||
626 | }, | ||
627 | #endif | ||
628 | { | ||
629 | .name = "groups", | ||
630 | .argname = "list", | ||
631 | .desc = "Specify EC groups (colon-separated list)", | ||
632 | .type = OPTION_ARG, | ||
633 | .opt.arg = &cfg.groups_in, | ||
634 | }, | ||
635 | { | ||
636 | .name = "HTTP", | ||
637 | .desc = "Respond to a 'GET /<path> HTTP/1.0' with file ./<path>", | ||
638 | .type = OPTION_VALUE, | ||
639 | .opt.value = &cfg.www, | ||
640 | .value = 3, | ||
641 | }, | ||
642 | { | ||
643 | .name = "id_prefix", | ||
644 | .argname = "arg", | ||
645 | .desc = "Generate SSL/TLS session IDs prefixed by 'arg'", | ||
646 | .type = OPTION_ARG, | ||
647 | .opt.arg = &cfg.session_id_prefix, | ||
648 | }, | ||
649 | { | ||
650 | .name = "key", | ||
651 | .argname = "file", | ||
652 | .desc = "Private Key file to use, in cert file if\n" | ||
653 | "not specified (default is " TEST_CERT ")", | ||
654 | .type = OPTION_ARG, | ||
655 | .opt.arg = &cfg.key_file, | ||
656 | }, | ||
657 | { | ||
658 | .name = "key2", | ||
659 | .argname = "file", | ||
660 | .desc = "Private Key file to use for servername, in cert file if\n" | ||
661 | "not specified (default is " TEST_CERT2 ")", | ||
662 | .type = OPTION_ARG, | ||
663 | .opt.arg = &cfg.key_file2, | ||
664 | }, | ||
665 | { | ||
666 | .name = "keyform", | ||
667 | .argname = "fmt", | ||
668 | .desc = "Key format (PEM or DER) PEM default", | ||
669 | .type = OPTION_ARG_FORMAT, | ||
670 | .opt.value = &cfg.key_format, | ||
671 | }, | ||
672 | { | ||
673 | .name = "keymatexport", | ||
674 | .argname = "label", | ||
675 | .desc = "Export keying material using label", | ||
676 | .type = OPTION_ARG, | ||
677 | .opt.arg = &cfg.keymatexportlabel, | ||
678 | }, | ||
679 | { | ||
680 | .name = "keymatexportlen", | ||
681 | .argname = "len", | ||
682 | .desc = "Export len bytes of keying material (default 20)", | ||
683 | .type = OPTION_ARG_FUNC, | ||
684 | .opt.argfunc = s_server_opt_keymatexportlen, | ||
685 | }, | ||
686 | { | ||
687 | .name = "legacy_renegotiation", | ||
688 | .type = OPTION_DISCARD, | ||
689 | }, | ||
690 | { | ||
691 | .name = "msg", | ||
692 | .desc = "Show protocol messages", | ||
693 | .type = OPTION_FLAG, | ||
694 | .opt.flag = &cfg.msg, | ||
695 | }, | ||
696 | #ifndef OPENSSL_NO_DTLS | ||
697 | { | ||
698 | .name = "mtu", | ||
699 | .argname = "mtu", | ||
700 | .desc = "Set link layer MTU", | ||
701 | .type = OPTION_ARG_FUNC, | ||
702 | .opt.argfunc = s_server_opt_mtu, | ||
703 | }, | ||
704 | #endif | ||
705 | { | ||
706 | .name = "naccept", | ||
707 | .argname = "num", | ||
708 | .desc = "Terminate after num connections", | ||
709 | .type = OPTION_ARG_INT, | ||
710 | .opt.value = &cfg.naccept | ||
711 | }, | ||
712 | { | ||
713 | .name = "named_curve", | ||
714 | .argname = "arg", | ||
715 | .type = OPTION_ARG, | ||
716 | .opt.arg = &cfg.named_curve, | ||
717 | }, | ||
718 | { | ||
719 | .name = "nbio", | ||
720 | .desc = "Run with non-blocking I/O", | ||
721 | .type = OPTION_FLAG, | ||
722 | .opt.flag = &cfg.nbio, | ||
723 | }, | ||
724 | { | ||
725 | .name = "nbio_test", | ||
726 | .desc = "Test with the non-blocking test bio", | ||
727 | .type = OPTION_FUNC, | ||
728 | .opt.func = s_server_opt_nbio_test, | ||
729 | }, | ||
730 | { | ||
731 | .name = "nextprotoneg", | ||
732 | .argname = "arg", | ||
733 | .type = OPTION_ARG, | ||
734 | .opt.arg = &cfg.npn_in, /* Ignored. */ | ||
735 | }, | ||
736 | { | ||
737 | .name = "no_cache", | ||
738 | .desc = "Disable session cache", | ||
739 | .type = OPTION_FLAG, | ||
740 | .opt.flag = &cfg.no_cache, | ||
741 | }, | ||
742 | { | ||
743 | .name = "no_comp", | ||
744 | .desc = "Disable SSL/TLS compression", | ||
745 | .type = OPTION_VALUE_OR, | ||
746 | .opt.value = &cfg.off, | ||
747 | .value = SSL_OP_NO_COMPRESSION, | ||
748 | }, | ||
749 | { | ||
750 | .name = "no_dhe", | ||
751 | .desc = "Disable ephemeral DH", | ||
752 | .type = OPTION_FLAG, | ||
753 | .opt.flag = &cfg.no_dhe, | ||
754 | }, | ||
755 | { | ||
756 | .name = "no_ecdhe", | ||
757 | .desc = "Disable ephemeral ECDH", | ||
758 | .type = OPTION_FLAG, | ||
759 | .opt.flag = &cfg.no_ecdhe, | ||
760 | }, | ||
761 | { | ||
762 | .name = "no_ticket", | ||
763 | .desc = "Disable use of RFC4507bis session tickets", | ||
764 | .type = OPTION_VALUE_OR, | ||
765 | .opt.value = &cfg.off, | ||
766 | .value = SSL_OP_NO_TICKET, | ||
767 | }, | ||
768 | { | ||
769 | .name = "no_ssl2", | ||
770 | .type = OPTION_DISCARD, | ||
771 | }, | ||
772 | { | ||
773 | .name = "no_ssl3", | ||
774 | .type = OPTION_DISCARD, | ||
775 | }, | ||
776 | { | ||
777 | .name = "no_tls1", | ||
778 | .type = OPTION_DISCARD, | ||
779 | }, | ||
780 | { | ||
781 | .name = "no_tls1_1", | ||
782 | .type = OPTION_DISCARD, | ||
783 | }, | ||
784 | { | ||
785 | .name = "no_tls1_2", | ||
786 | .desc = "Just disable TLSv1.2", | ||
787 | .type = OPTION_VALUE_OR, | ||
788 | .opt.value = &cfg.off, | ||
789 | .value = SSL_OP_NO_TLSv1_2, | ||
790 | }, | ||
791 | { | ||
792 | .name = "no_tls1_3", | ||
793 | .desc = "Just disable TLSv1.3", | ||
794 | .type = OPTION_VALUE_OR, | ||
795 | .opt.value = &cfg.off, | ||
796 | .value = SSL_OP_NO_TLSv1_3, | ||
797 | }, | ||
798 | { | ||
799 | .name = "no_tmp_rsa", | ||
800 | .type = OPTION_DISCARD, | ||
801 | }, | ||
802 | { | ||
803 | .name = "nocert", | ||
804 | .desc = "Don't use any certificates (Anon-DH)", | ||
805 | .type = OPTION_FLAG, | ||
806 | .opt.flag = &cfg.nocert, | ||
807 | }, | ||
808 | { | ||
809 | .name = "pass", | ||
810 | .argname = "arg", | ||
811 | .desc = "Private key file pass phrase source", | ||
812 | .type = OPTION_ARG, | ||
813 | .opt.arg = &cfg.passarg, | ||
814 | }, | ||
815 | { | ||
816 | .name = "port", | ||
817 | .argname = "port", | ||
818 | .type = OPTION_ARG_FUNC, | ||
819 | .opt.argfunc = s_server_opt_port, | ||
820 | }, | ||
821 | { | ||
822 | .name = "quiet", | ||
823 | .desc = "Inhibit printing of session and certificate information", | ||
824 | .type = OPTION_FLAG, | ||
825 | .opt.flag = &cfg.quiet, | ||
826 | }, | ||
827 | { | ||
828 | .name = "servername", | ||
829 | .argname = "name", | ||
830 | .desc = "Servername for HostName TLS extension", | ||
831 | .type = OPTION_ARG, | ||
832 | .opt.arg = &cfg.tlsextcbp.servername, | ||
833 | }, | ||
834 | { | ||
835 | .name = "servername_fatal", | ||
836 | .desc = "On mismatch send fatal alert (default warning alert)", | ||
837 | .type = OPTION_VALUE, | ||
838 | .opt.value = &cfg.tlsextcbp.extension_error, | ||
839 | .value = SSL_TLSEXT_ERR_ALERT_FATAL, | ||
840 | }, | ||
841 | { | ||
842 | .name = "serverpref", | ||
843 | .desc = "Use server's cipher preferences", | ||
844 | .type = OPTION_VALUE_OR, | ||
845 | .opt.value = &cfg.off, | ||
846 | .value = SSL_OP_CIPHER_SERVER_PREFERENCE, | ||
847 | }, | ||
848 | { | ||
849 | .name = "state", | ||
850 | .desc = "Print the SSL states", | ||
851 | .type = OPTION_FLAG, | ||
852 | .opt.flag = &cfg.state, | ||
853 | }, | ||
854 | { | ||
855 | .name = "status", | ||
856 | .desc = "Respond to certificate status requests", | ||
857 | .type = OPTION_FLAG, | ||
858 | .opt.flag = &cfg.tlsextstatus, | ||
859 | }, | ||
860 | { | ||
861 | .name = "status_timeout", | ||
862 | .argname = "nsec", | ||
863 | .desc = "Status request responder timeout", | ||
864 | .type = OPTION_ARG_FUNC, | ||
865 | .opt.argfunc = s_server_opt_status_timeout, | ||
866 | }, | ||
867 | { | ||
868 | .name = "status_url", | ||
869 | .argname = "url", | ||
870 | .desc = "Status request fallback URL", | ||
871 | .type = OPTION_ARG_FUNC, | ||
872 | .opt.argfunc = s_server_opt_status_url, | ||
873 | }, | ||
874 | { | ||
875 | .name = "status_verbose", | ||
876 | .desc = "Enable status request verbose printout", | ||
877 | .type = OPTION_FUNC, | ||
878 | .opt.func = s_server_opt_status_verbose, | ||
879 | }, | ||
880 | #ifndef OPENSSL_NO_DTLS | ||
881 | { | ||
882 | .name = "timeout", | ||
883 | .desc = "Enable timeouts", | ||
884 | .type = OPTION_FLAG, | ||
885 | .opt.flag = &cfg.enable_timeouts, | ||
886 | }, | ||
887 | #endif | ||
888 | { | ||
889 | .name = "tls1_2", | ||
890 | .desc = "Just talk TLSv1.2", | ||
891 | .type = OPTION_FUNC, | ||
892 | .opt.func = s_server_opt_protocol_version_tls1_2, | ||
893 | }, | ||
894 | { | ||
895 | .name = "tls1_3", | ||
896 | .desc = "Just talk TLSv1.3", | ||
897 | .type = OPTION_FUNC, | ||
898 | .opt.func = s_server_opt_protocol_version_tls1_3, | ||
899 | }, | ||
900 | { | ||
901 | .name = "tlsextdebug", | ||
902 | .desc = "Hex dump of all TLS extensions received", | ||
903 | .type = OPTION_FLAG, | ||
904 | .opt.flag = &cfg.tlsextdebug, | ||
905 | }, | ||
906 | #ifndef OPENSSL_NO_SRTP | ||
907 | { | ||
908 | .name = "use_srtp", | ||
909 | .argname = "profiles", | ||
910 | .desc = "Offer SRTP key management with a colon-separated profile list", | ||
911 | .type = OPTION_ARG, | ||
912 | .opt.arg = &cfg.srtp_profiles, | ||
913 | }, | ||
914 | #endif | ||
915 | { | ||
916 | .name = "Verify", | ||
917 | .argname = "depth", | ||
918 | .desc = "Turn on peer certificate verification, must have a cert", | ||
919 | .type = OPTION_ARG_FUNC, | ||
920 | .opt.argfunc = s_server_opt_verify_fail, | ||
921 | }, | ||
922 | { | ||
923 | .name = "verify", | ||
924 | .argname = "depth", | ||
925 | .desc = "Turn on peer certificate verification", | ||
926 | .type = OPTION_ARG_FUNC, | ||
927 | .opt.argfunc = s_server_opt_verify, | ||
928 | }, | ||
929 | { | ||
930 | .name = "verify_return_error", | ||
931 | .desc = "Return verification error", | ||
932 | .type = OPTION_FLAG, | ||
933 | .opt.flag = &verify_return_error, | ||
934 | }, | ||
935 | { | ||
936 | .name = "WWW", | ||
937 | .desc = "Respond to a 'GET /<path> HTTP/1.0' with file ./<path>", | ||
938 | .type = OPTION_VALUE, | ||
939 | .opt.value = &cfg.www, | ||
940 | .value = 2, | ||
941 | }, | ||
942 | { | ||
943 | .name = "www", | ||
944 | .desc = "Respond to a 'GET /' with a status page", | ||
945 | .type = OPTION_VALUE, | ||
946 | .opt.value = &cfg.www, | ||
947 | .value = 1, | ||
948 | }, | ||
949 | { | ||
950 | .name = NULL, | ||
951 | .desc = "", | ||
952 | .type = OPTION_ARGV_FUNC, | ||
953 | .opt.argvfunc = s_server_opt_verify_param, | ||
954 | }, | ||
955 | { NULL }, | ||
956 | }; | ||
957 | |||
958 | static void | ||
959 | s_server_init(void) | ||
960 | { | ||
961 | accept_socket = -1; | ||
962 | cfg.cipher = NULL; | ||
963 | cfg.server_verify = SSL_VERIFY_NONE; | ||
964 | cfg.dcert_file = NULL; | ||
965 | cfg.dkey_file = NULL; | ||
966 | cfg.cert_file = TEST_CERT; | ||
967 | cfg.key_file = NULL; | ||
968 | cfg.cert_file2 = TEST_CERT2; | ||
969 | cfg.key_file2 = NULL; | ||
970 | ctx2 = NULL; | ||
971 | cfg.nbio = 0; | ||
972 | cfg.nbio_test = 0; | ||
973 | ctx = NULL; | ||
974 | cfg.www = 0; | ||
975 | |||
976 | bio_s_out = NULL; | ||
977 | cfg.debug = 0; | ||
978 | cfg.msg = 0; | ||
979 | cfg.quiet = 0; | ||
980 | } | ||
981 | |||
982 | static void | ||
983 | sv_usage(void) | ||
984 | { | ||
985 | fprintf(stderr, "usage: s_server " | ||
986 | "[-accept port] [-alpn protocols] [-bugs] [-CAfile file]\n" | ||
987 | " [-CApath directory] [-cert file] [-cert2 file]\n" | ||
988 | " [-certform der | pem] [-cipher cipherlist]\n" | ||
989 | " [-context id] [-crl_check] [-crl_check_all] [-crlf]\n" | ||
990 | " [-dcert file] [-dcertform der | pem] [-debug]\n" | ||
991 | " [-dhparam file] [-dkey file] [-dkeyform der | pem]\n" | ||
992 | " [-dpass arg] [-dtls] [-dtls1_2] [-groups list] [-HTTP]\n" | ||
993 | " [-id_prefix arg] [-key keyfile] [-key2 keyfile]\n" | ||
994 | " [-keyform der | pem] [-keymatexport label]\n" | ||
995 | " [-keymatexportlen len] [-msg] [-mtu mtu] [-naccept num]\n" | ||
996 | " [-named_curve arg] [-nbio] [-nbio_test] [-no_cache]\n" | ||
997 | " [-no_dhe] [-no_ecdhe] [-no_ticket] \n" | ||
998 | " [-no_tls1_2] [-no_tls1_3] [-no_tmp_rsa]\n" | ||
999 | " [-nocert] [-pass arg] [-quiet] [-servername name]\n" | ||
1000 | " [-servername_fatal] [-serverpref] [-state] [-status]\n" | ||
1001 | " [-status_timeout nsec] [-status_url url]\n" | ||
1002 | " [-status_verbose] [-timeout] \n" | ||
1003 | " [-tls1_2] [-tls1_3] [-tlsextdebug] [-use_srtp profiles]\n" | ||
1004 | " [-Verify depth] [-verify depth] [-verify_return_error]\n" | ||
1005 | " [-WWW] [-www]\n"); | ||
1006 | fprintf(stderr, "\n"); | ||
1007 | options_usage(s_server_options); | ||
1008 | fprintf(stderr, "\n"); | ||
1009 | } | ||
1010 | |||
1011 | int | ||
1012 | s_server_main(int argc, char *argv[]) | ||
1013 | { | ||
1014 | int ret = 1; | ||
1015 | char *pass = NULL; | ||
1016 | char *dpass = NULL; | ||
1017 | X509 *s_cert = NULL, *s_dcert = NULL; | ||
1018 | EVP_PKEY *s_key = NULL, *s_dkey = NULL; | ||
1019 | EVP_PKEY *s_key2 = NULL; | ||
1020 | X509 *s_cert2 = NULL; | ||
1021 | tlsextalpnctx alpn_ctx = { NULL, 0 }; | ||
1022 | |||
1023 | if (pledge("stdio rpath inet dns tty", NULL) == -1) { | ||
1024 | perror("pledge"); | ||
1025 | exit(1); | ||
1026 | } | ||
1027 | |||
1028 | memset(&cfg, 0, sizeof(cfg)); | ||
1029 | cfg.keymatexportlen = 20; | ||
1030 | cfg.meth = TLS_server_method(); | ||
1031 | cfg.naccept = -1; | ||
1032 | cfg.port = PORT; | ||
1033 | cfg.cert_file = TEST_CERT; | ||
1034 | cfg.cert_file2 = TEST_CERT2; | ||
1035 | cfg.cert_format = FORMAT_PEM; | ||
1036 | cfg.dcert_format = FORMAT_PEM; | ||
1037 | cfg.dkey_format = FORMAT_PEM; | ||
1038 | cfg.key_format = FORMAT_PEM; | ||
1039 | cfg.server_verify = SSL_VERIFY_NONE; | ||
1040 | cfg.socket_type = SOCK_STREAM; | ||
1041 | cfg.tlscstatp.timeout = -1; | ||
1042 | cfg.tlsextcbp.extension_error = | ||
1043 | SSL_TLSEXT_ERR_ALERT_WARNING; | ||
1044 | |||
1045 | local_argc = argc; | ||
1046 | local_argv = argv; | ||
1047 | |||
1048 | s_server_init(); | ||
1049 | |||
1050 | verify_depth = 0; | ||
1051 | |||
1052 | if (options_parse(argc, argv, s_server_options, NULL, NULL) != 0) { | ||
1053 | if (cfg.errstr == NULL) | ||
1054 | sv_usage(); | ||
1055 | goto end; | ||
1056 | } | ||
1057 | |||
1058 | if (!app_passwd(bio_err, cfg.passarg, | ||
1059 | cfg.dpassarg, &pass, &dpass)) { | ||
1060 | BIO_printf(bio_err, "Error getting password\n"); | ||
1061 | goto end; | ||
1062 | } | ||
1063 | if (cfg.key_file == NULL) | ||
1064 | cfg.key_file = cfg.cert_file; | ||
1065 | if (cfg.key_file2 == NULL) | ||
1066 | cfg.key_file2 = cfg.cert_file2; | ||
1067 | |||
1068 | if (cfg.nocert == 0) { | ||
1069 | s_key = load_key(bio_err, cfg.key_file, | ||
1070 | cfg.key_format, 0, pass, | ||
1071 | "server certificate private key file"); | ||
1072 | if (!s_key) { | ||
1073 | ERR_print_errors(bio_err); | ||
1074 | goto end; | ||
1075 | } | ||
1076 | s_cert = load_cert(bio_err, cfg.cert_file, | ||
1077 | cfg.cert_format, | ||
1078 | NULL, "server certificate file"); | ||
1079 | |||
1080 | if (!s_cert) { | ||
1081 | ERR_print_errors(bio_err); | ||
1082 | goto end; | ||
1083 | } | ||
1084 | if (cfg.tlsextcbp.servername) { | ||
1085 | s_key2 = load_key(bio_err, cfg.key_file2, | ||
1086 | cfg.key_format, 0, pass, | ||
1087 | "second server certificate private key file"); | ||
1088 | if (!s_key2) { | ||
1089 | ERR_print_errors(bio_err); | ||
1090 | goto end; | ||
1091 | } | ||
1092 | s_cert2 = load_cert(bio_err, cfg.cert_file2, | ||
1093 | cfg.cert_format, | ||
1094 | NULL, "second server certificate file"); | ||
1095 | |||
1096 | if (!s_cert2) { | ||
1097 | ERR_print_errors(bio_err); | ||
1098 | goto end; | ||
1099 | } | ||
1100 | } | ||
1101 | } | ||
1102 | alpn_ctx.data = NULL; | ||
1103 | if (cfg.alpn_in) { | ||
1104 | unsigned short len; | ||
1105 | alpn_ctx.data = next_protos_parse(&len, | ||
1106 | cfg.alpn_in); | ||
1107 | if (alpn_ctx.data == NULL) | ||
1108 | goto end; | ||
1109 | alpn_ctx.len = len; | ||
1110 | } | ||
1111 | |||
1112 | if (cfg.dcert_file) { | ||
1113 | |||
1114 | if (cfg.dkey_file == NULL) | ||
1115 | cfg.dkey_file = cfg.dcert_file; | ||
1116 | |||
1117 | s_dkey = load_key(bio_err, cfg.dkey_file, | ||
1118 | cfg.dkey_format, | ||
1119 | 0, dpass, "second certificate private key file"); | ||
1120 | if (!s_dkey) { | ||
1121 | ERR_print_errors(bio_err); | ||
1122 | goto end; | ||
1123 | } | ||
1124 | s_dcert = load_cert(bio_err, cfg.dcert_file, | ||
1125 | cfg.dcert_format, | ||
1126 | NULL, "second server certificate file"); | ||
1127 | |||
1128 | if (!s_dcert) { | ||
1129 | ERR_print_errors(bio_err); | ||
1130 | goto end; | ||
1131 | } | ||
1132 | } | ||
1133 | if (bio_s_out == NULL) { | ||
1134 | if (cfg.quiet && !cfg.debug && | ||
1135 | !cfg.msg) { | ||
1136 | bio_s_out = BIO_new(BIO_s_null()); | ||
1137 | } else { | ||
1138 | if (bio_s_out == NULL) | ||
1139 | bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); | ||
1140 | } | ||
1141 | } | ||
1142 | if (cfg.nocert) { | ||
1143 | cfg.cert_file = NULL; | ||
1144 | cfg.key_file = NULL; | ||
1145 | cfg.dcert_file = NULL; | ||
1146 | cfg.dkey_file = NULL; | ||
1147 | cfg.cert_file2 = NULL; | ||
1148 | cfg.key_file2 = NULL; | ||
1149 | } | ||
1150 | ctx = SSL_CTX_new(cfg.meth); | ||
1151 | if (ctx == NULL) { | ||
1152 | ERR_print_errors(bio_err); | ||
1153 | goto end; | ||
1154 | } | ||
1155 | |||
1156 | SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); | ||
1157 | |||
1158 | if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version)) | ||
1159 | goto end; | ||
1160 | if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version)) | ||
1161 | goto end; | ||
1162 | |||
1163 | if (cfg.session_id_prefix) { | ||
1164 | if (strlen(cfg.session_id_prefix) >= 32) | ||
1165 | BIO_printf(bio_err, | ||
1166 | "warning: id_prefix is too long, only one new session will be possible\n"); | ||
1167 | else if (strlen(cfg.session_id_prefix) >= 16) | ||
1168 | BIO_printf(bio_err, | ||
1169 | "warning: id_prefix is too long if you use SSLv2\n"); | ||
1170 | if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { | ||
1171 | BIO_printf(bio_err, "error setting 'id_prefix'\n"); | ||
1172 | ERR_print_errors(bio_err); | ||
1173 | goto end; | ||
1174 | } | ||
1175 | BIO_printf(bio_err, "id_prefix '%s' set.\n", | ||
1176 | cfg.session_id_prefix); | ||
1177 | } | ||
1178 | SSL_CTX_set_quiet_shutdown(ctx, 1); | ||
1179 | if (cfg.bugs) | ||
1180 | SSL_CTX_set_options(ctx, SSL_OP_ALL); | ||
1181 | SSL_CTX_set_options(ctx, cfg.off); | ||
1182 | |||
1183 | if (cfg.state) | ||
1184 | SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); | ||
1185 | if (cfg.no_cache) | ||
1186 | SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); | ||
1187 | else | ||
1188 | SSL_CTX_sess_set_cache_size(ctx, 128); | ||
1189 | |||
1190 | #ifndef OPENSSL_NO_SRTP | ||
1191 | if (cfg.srtp_profiles != NULL) | ||
1192 | SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles); | ||
1193 | #endif | ||
1194 | |||
1195 | if ((!SSL_CTX_load_verify_locations(ctx, cfg.CAfile, | ||
1196 | cfg.CApath)) || | ||
1197 | (!SSL_CTX_set_default_verify_paths(ctx))) { | ||
1198 | /* BIO_printf(bio_err,"X509_load_verify_locations\n"); */ | ||
1199 | ERR_print_errors(bio_err); | ||
1200 | /* goto end; */ | ||
1201 | } | ||
1202 | if (cfg.vpm) | ||
1203 | SSL_CTX_set1_param(ctx, cfg.vpm); | ||
1204 | |||
1205 | if (s_cert2) { | ||
1206 | ctx2 = SSL_CTX_new(cfg.meth); | ||
1207 | if (ctx2 == NULL) { | ||
1208 | ERR_print_errors(bio_err); | ||
1209 | goto end; | ||
1210 | } | ||
1211 | |||
1212 | if (!SSL_CTX_set_min_proto_version(ctx2, | ||
1213 | cfg.min_version)) | ||
1214 | goto end; | ||
1215 | if (!SSL_CTX_set_max_proto_version(ctx2, | ||
1216 | cfg.max_version)) | ||
1217 | goto end; | ||
1218 | SSL_CTX_clear_mode(ctx2, SSL_MODE_AUTO_RETRY); | ||
1219 | } | ||
1220 | if (ctx2) { | ||
1221 | BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); | ||
1222 | |||
1223 | if (cfg.session_id_prefix) { | ||
1224 | if (strlen(cfg.session_id_prefix) >= 32) | ||
1225 | BIO_printf(bio_err, | ||
1226 | "warning: id_prefix is too long, only one new session will be possible\n"); | ||
1227 | else if (strlen(cfg.session_id_prefix) >= 16) | ||
1228 | BIO_printf(bio_err, | ||
1229 | "warning: id_prefix is too long if you use SSLv2\n"); | ||
1230 | if (!SSL_CTX_set_generate_session_id(ctx2, | ||
1231 | generate_session_id)) { | ||
1232 | BIO_printf(bio_err, | ||
1233 | "error setting 'id_prefix'\n"); | ||
1234 | ERR_print_errors(bio_err); | ||
1235 | goto end; | ||
1236 | } | ||
1237 | BIO_printf(bio_err, "id_prefix '%s' set.\n", | ||
1238 | cfg.session_id_prefix); | ||
1239 | } | ||
1240 | SSL_CTX_set_quiet_shutdown(ctx2, 1); | ||
1241 | if (cfg.bugs) | ||
1242 | SSL_CTX_set_options(ctx2, SSL_OP_ALL); | ||
1243 | SSL_CTX_set_options(ctx2, cfg.off); | ||
1244 | |||
1245 | if (cfg.state) | ||
1246 | SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback); | ||
1247 | |||
1248 | if (cfg.no_cache) | ||
1249 | SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF); | ||
1250 | else | ||
1251 | SSL_CTX_sess_set_cache_size(ctx2, 128); | ||
1252 | |||
1253 | if ((!SSL_CTX_load_verify_locations(ctx2, | ||
1254 | cfg.CAfile, cfg.CApath)) || | ||
1255 | (!SSL_CTX_set_default_verify_paths(ctx2))) { | ||
1256 | ERR_print_errors(bio_err); | ||
1257 | } | ||
1258 | if (cfg.vpm) | ||
1259 | SSL_CTX_set1_param(ctx2, cfg.vpm); | ||
1260 | } | ||
1261 | if (alpn_ctx.data) | ||
1262 | SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); | ||
1263 | |||
1264 | if (cfg.groups_in != NULL) { | ||
1265 | if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) { | ||
1266 | BIO_printf(bio_err, "Failed to set groups '%s'\n", | ||
1267 | cfg.groups_in); | ||
1268 | goto end; | ||
1269 | } | ||
1270 | } | ||
1271 | |||
1272 | #ifndef OPENSSL_NO_DH | ||
1273 | if (!cfg.no_dhe) { | ||
1274 | DH *dh = NULL; | ||
1275 | |||
1276 | if (cfg.dhfile) | ||
1277 | dh = load_dh_param(cfg.dhfile); | ||
1278 | else if (cfg.cert_file) | ||
1279 | dh = load_dh_param(cfg.cert_file); | ||
1280 | |||
1281 | if (dh != NULL) | ||
1282 | BIO_printf(bio_s_out, "Setting temp DH parameters\n"); | ||
1283 | else | ||
1284 | BIO_printf(bio_s_out, "Using auto DH parameters\n"); | ||
1285 | (void) BIO_flush(bio_s_out); | ||
1286 | |||
1287 | if (dh == NULL) | ||
1288 | SSL_CTX_set_dh_auto(ctx, 1); | ||
1289 | else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { | ||
1290 | BIO_printf(bio_err, | ||
1291 | "Error setting temp DH parameters\n"); | ||
1292 | ERR_print_errors(bio_err); | ||
1293 | DH_free(dh); | ||
1294 | goto end; | ||
1295 | } | ||
1296 | |||
1297 | if (ctx2) { | ||
1298 | if (!cfg.dhfile) { | ||
1299 | DH *dh2 = NULL; | ||
1300 | |||
1301 | if (cfg.cert_file2 != NULL) | ||
1302 | dh2 = load_dh_param( | ||
1303 | cfg.cert_file2); | ||
1304 | if (dh2 != NULL) { | ||
1305 | BIO_printf(bio_s_out, | ||
1306 | "Setting temp DH parameters\n"); | ||
1307 | (void) BIO_flush(bio_s_out); | ||
1308 | |||
1309 | DH_free(dh); | ||
1310 | dh = dh2; | ||
1311 | } | ||
1312 | } | ||
1313 | if (dh == NULL) | ||
1314 | SSL_CTX_set_dh_auto(ctx2, 1); | ||
1315 | else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { | ||
1316 | BIO_printf(bio_err, | ||
1317 | "Error setting temp DH parameters\n"); | ||
1318 | ERR_print_errors(bio_err); | ||
1319 | DH_free(dh); | ||
1320 | goto end; | ||
1321 | } | ||
1322 | } | ||
1323 | DH_free(dh); | ||
1324 | } | ||
1325 | #endif | ||
1326 | |||
1327 | if (!cfg.no_ecdhe && cfg.named_curve != NULL) { | ||
1328 | EC_KEY *ecdh = NULL; | ||
1329 | int nid; | ||
1330 | |||
1331 | if ((nid = OBJ_sn2nid(cfg.named_curve)) == 0) { | ||
1332 | BIO_printf(bio_err, "unknown curve name (%s)\n", | ||
1333 | cfg.named_curve); | ||
1334 | goto end; | ||
1335 | } | ||
1336 | if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) { | ||
1337 | BIO_printf(bio_err, "unable to create curve (%s)\n", | ||
1338 | cfg.named_curve); | ||
1339 | goto end; | ||
1340 | } | ||
1341 | BIO_printf(bio_s_out, "Setting temp ECDH parameters\n"); | ||
1342 | (void) BIO_flush(bio_s_out); | ||
1343 | |||
1344 | SSL_CTX_set_tmp_ecdh(ctx, ecdh); | ||
1345 | if (ctx2) | ||
1346 | SSL_CTX_set_tmp_ecdh(ctx2, ecdh); | ||
1347 | EC_KEY_free(ecdh); | ||
1348 | } | ||
1349 | |||
1350 | if (!set_cert_key_stuff(ctx, s_cert, s_key)) | ||
1351 | goto end; | ||
1352 | if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2)) | ||
1353 | goto end; | ||
1354 | if (s_dcert != NULL) { | ||
1355 | if (!set_cert_key_stuff(ctx, s_dcert, s_dkey)) | ||
1356 | goto end; | ||
1357 | } | ||
1358 | |||
1359 | if (cfg.cipher != NULL) { | ||
1360 | if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) { | ||
1361 | BIO_printf(bio_err, "error setting cipher list\n"); | ||
1362 | ERR_print_errors(bio_err); | ||
1363 | goto end; | ||
1364 | } | ||
1365 | if (ctx2 && !SSL_CTX_set_cipher_list(ctx2, | ||
1366 | cfg.cipher)) { | ||
1367 | BIO_printf(bio_err, "error setting cipher list\n"); | ||
1368 | ERR_print_errors(bio_err); | ||
1369 | goto end; | ||
1370 | } | ||
1371 | } | ||
1372 | SSL_CTX_set_verify(ctx, cfg.server_verify, verify_callback); | ||
1373 | SSL_CTX_set_session_id_context(ctx, | ||
1374 | (void *) &s_server_session_id_context, | ||
1375 | sizeof s_server_session_id_context); | ||
1376 | |||
1377 | /* Set DTLS cookie generation and verification callbacks */ | ||
1378 | SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); | ||
1379 | SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); | ||
1380 | |||
1381 | if (ctx2) { | ||
1382 | SSL_CTX_set_verify(ctx2, cfg.server_verify, | ||
1383 | verify_callback); | ||
1384 | SSL_CTX_set_session_id_context(ctx2, | ||
1385 | (void *) &s_server_session_id_context, | ||
1386 | sizeof s_server_session_id_context); | ||
1387 | |||
1388 | cfg.tlsextcbp.biodebug = bio_s_out; | ||
1389 | SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); | ||
1390 | SSL_CTX_set_tlsext_servername_arg(ctx2, | ||
1391 | &cfg.tlsextcbp); | ||
1392 | SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); | ||
1393 | SSL_CTX_set_tlsext_servername_arg(ctx, | ||
1394 | &cfg.tlsextcbp); | ||
1395 | } | ||
1396 | |||
1397 | if (cfg.CAfile != NULL) { | ||
1398 | SSL_CTX_set_client_CA_list(ctx, | ||
1399 | SSL_load_client_CA_file(cfg.CAfile)); | ||
1400 | if (ctx2) | ||
1401 | SSL_CTX_set_client_CA_list(ctx2, | ||
1402 | SSL_load_client_CA_file(cfg.CAfile)); | ||
1403 | } | ||
1404 | BIO_printf(bio_s_out, "ACCEPT\n"); | ||
1405 | (void) BIO_flush(bio_s_out); | ||
1406 | if (cfg.www) | ||
1407 | do_server(cfg.port, cfg.socket_type, | ||
1408 | &accept_socket, www_body, cfg.context, | ||
1409 | cfg.naccept); | ||
1410 | else | ||
1411 | do_server(cfg.port, cfg.socket_type, | ||
1412 | &accept_socket, sv_body, cfg.context, | ||
1413 | cfg.naccept); | ||
1414 | print_stats(bio_s_out, ctx); | ||
1415 | ret = 0; | ||
1416 | end: | ||
1417 | SSL_CTX_free(ctx); | ||
1418 | X509_free(s_cert); | ||
1419 | X509_free(s_dcert); | ||
1420 | EVP_PKEY_free(s_key); | ||
1421 | EVP_PKEY_free(s_dkey); | ||
1422 | free(pass); | ||
1423 | free(dpass); | ||
1424 | X509_VERIFY_PARAM_free(cfg.vpm); | ||
1425 | free(cfg.tlscstatp.host); | ||
1426 | free(cfg.tlscstatp.port); | ||
1427 | free(cfg.tlscstatp.path); | ||
1428 | SSL_CTX_free(ctx2); | ||
1429 | X509_free(s_cert2); | ||
1430 | EVP_PKEY_free(s_key2); | ||
1431 | free(alpn_ctx.data); | ||
1432 | if (bio_s_out != NULL) { | ||
1433 | BIO_free(bio_s_out); | ||
1434 | bio_s_out = NULL; | ||
1435 | } | ||
1436 | |||
1437 | return (ret); | ||
1438 | } | ||
1439 | |||
1440 | static void | ||
1441 | print_stats(BIO *bio, SSL_CTX *ssl_ctx) | ||
1442 | { | ||
1443 | BIO_printf(bio, "%4ld items in the session cache\n", | ||
1444 | SSL_CTX_sess_number(ssl_ctx)); | ||
1445 | BIO_printf(bio, "%4ld client connects (SSL_connect())\n", | ||
1446 | SSL_CTX_sess_connect(ssl_ctx)); | ||
1447 | BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n", | ||
1448 | SSL_CTX_sess_connect_renegotiate(ssl_ctx)); | ||
1449 | BIO_printf(bio, "%4ld client connects that finished\n", | ||
1450 | SSL_CTX_sess_connect_good(ssl_ctx)); | ||
1451 | BIO_printf(bio, "%4ld server accepts (SSL_accept())\n", | ||
1452 | SSL_CTX_sess_accept(ssl_ctx)); | ||
1453 | BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n", | ||
1454 | SSL_CTX_sess_accept_renegotiate(ssl_ctx)); | ||
1455 | BIO_printf(bio, "%4ld server accepts that finished\n", | ||
1456 | SSL_CTX_sess_accept_good(ssl_ctx)); | ||
1457 | BIO_printf(bio, "%4ld session cache hits\n", | ||
1458 | SSL_CTX_sess_hits(ssl_ctx)); | ||
1459 | BIO_printf(bio, "%4ld session cache misses\n", | ||
1460 | SSL_CTX_sess_misses(ssl_ctx)); | ||
1461 | BIO_printf(bio, "%4ld session cache timeouts\n", | ||
1462 | SSL_CTX_sess_timeouts(ssl_ctx)); | ||
1463 | BIO_printf(bio, "%4ld callback cache hits\n", | ||
1464 | SSL_CTX_sess_cb_hits(ssl_ctx)); | ||
1465 | BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n", | ||
1466 | SSL_CTX_sess_cache_full(ssl_ctx), | ||
1467 | SSL_CTX_sess_get_cache_size(ssl_ctx)); | ||
1468 | } | ||
1469 | |||
1470 | static int | ||
1471 | sv_body(int s, unsigned char *context) | ||
1472 | { | ||
1473 | char *buf = NULL; | ||
1474 | int ret = 1; | ||
1475 | int k, i; | ||
1476 | unsigned long l; | ||
1477 | SSL *con = NULL; | ||
1478 | BIO *sbio; | ||
1479 | struct timeval timeout; | ||
1480 | |||
1481 | if ((buf = malloc(bufsize)) == NULL) { | ||
1482 | BIO_printf(bio_err, "out of memory\n"); | ||
1483 | goto err; | ||
1484 | } | ||
1485 | if (cfg.nbio) { | ||
1486 | if (!cfg.quiet) | ||
1487 | BIO_printf(bio_err, "turning on non blocking io\n"); | ||
1488 | if (!BIO_socket_nbio(s, 1)) | ||
1489 | ERR_print_errors(bio_err); | ||
1490 | } | ||
1491 | |||
1492 | if (con == NULL) { | ||
1493 | con = SSL_new(ctx); | ||
1494 | if (cfg.tlsextdebug) { | ||
1495 | SSL_set_tlsext_debug_callback(con, tlsext_cb); | ||
1496 | SSL_set_tlsext_debug_arg(con, bio_s_out); | ||
1497 | } | ||
1498 | if (cfg.tlsextstatus) { | ||
1499 | SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); | ||
1500 | cfg.tlscstatp.err = bio_err; | ||
1501 | SSL_CTX_set_tlsext_status_arg(ctx, | ||
1502 | &cfg.tlscstatp); | ||
1503 | } | ||
1504 | if (context) | ||
1505 | SSL_set_session_id_context(con, context, | ||
1506 | strlen((char *) context)); | ||
1507 | } | ||
1508 | SSL_clear(con); | ||
1509 | |||
1510 | if (SSL_is_dtls(con)) { | ||
1511 | sbio = BIO_new_dgram(s, BIO_NOCLOSE); | ||
1512 | |||
1513 | if (cfg.enable_timeouts) { | ||
1514 | timeout.tv_sec = 0; | ||
1515 | timeout.tv_usec = DGRAM_RCV_TIMEOUT; | ||
1516 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, | ||
1517 | &timeout); | ||
1518 | |||
1519 | timeout.tv_sec = 0; | ||
1520 | timeout.tv_usec = DGRAM_SND_TIMEOUT; | ||
1521 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, | ||
1522 | &timeout); | ||
1523 | } | ||
1524 | if (cfg.socket_mtu > 28) { | ||
1525 | SSL_set_options(con, SSL_OP_NO_QUERY_MTU); | ||
1526 | SSL_set_mtu(con, cfg.socket_mtu - 28); | ||
1527 | } else | ||
1528 | /* want to do MTU discovery */ | ||
1529 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); | ||
1530 | |||
1531 | /* turn on cookie exchange */ | ||
1532 | SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); | ||
1533 | } else | ||
1534 | sbio = BIO_new_socket(s, BIO_NOCLOSE); | ||
1535 | |||
1536 | if (cfg.nbio_test) { | ||
1537 | BIO *test; | ||
1538 | |||
1539 | test = BIO_new(BIO_f_nbio_test()); | ||
1540 | sbio = BIO_push(test, sbio); | ||
1541 | } | ||
1542 | |||
1543 | SSL_set_bio(con, sbio, sbio); | ||
1544 | SSL_set_accept_state(con); | ||
1545 | /* SSL_set_fd(con,s); */ | ||
1546 | |||
1547 | if (cfg.debug) { | ||
1548 | BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); | ||
1549 | BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out); | ||
1550 | } | ||
1551 | if (cfg.msg) { | ||
1552 | SSL_set_msg_callback(con, msg_cb); | ||
1553 | SSL_set_msg_callback_arg(con, bio_s_out); | ||
1554 | } | ||
1555 | if (cfg.tlsextdebug) { | ||
1556 | SSL_set_tlsext_debug_callback(con, tlsext_cb); | ||
1557 | SSL_set_tlsext_debug_arg(con, bio_s_out); | ||
1558 | } | ||
1559 | |||
1560 | for (;;) { | ||
1561 | int read_from_terminal; | ||
1562 | int read_from_sslcon; | ||
1563 | struct pollfd pfd[2]; | ||
1564 | int ptimeout; | ||
1565 | |||
1566 | read_from_terminal = 0; | ||
1567 | read_from_sslcon = SSL_pending(con); | ||
1568 | |||
1569 | if (!read_from_sslcon) { | ||
1570 | pfd[0].fd = fileno(stdin); | ||
1571 | pfd[0].events = POLLIN; | ||
1572 | pfd[1].fd = s; | ||
1573 | pfd[1].events = POLLIN; | ||
1574 | |||
1575 | if (SSL_is_dtls(con) && | ||
1576 | DTLSv1_get_timeout(con, &timeout)) | ||
1577 | ptimeout = timeout.tv_sec * 1000 + | ||
1578 | timeout.tv_usec / 1000; | ||
1579 | else | ||
1580 | ptimeout = -1; | ||
1581 | |||
1582 | i = poll(pfd, 2, ptimeout); | ||
1583 | |||
1584 | if (SSL_is_dtls(con) && | ||
1585 | DTLSv1_handle_timeout(con) > 0) | ||
1586 | BIO_printf(bio_err, "TIMEOUT occured\n"); | ||
1587 | if (i <= 0) | ||
1588 | continue; | ||
1589 | if (pfd[0].revents) { | ||
1590 | if ((pfd[0].revents & (POLLERR|POLLNVAL))) | ||
1591 | continue; | ||
1592 | read_from_terminal = 1; | ||
1593 | } | ||
1594 | if (pfd[1].revents) { | ||
1595 | if ((pfd[1].revents & (POLLERR|POLLNVAL))) | ||
1596 | continue; | ||
1597 | read_from_sslcon = 1; | ||
1598 | } | ||
1599 | } | ||
1600 | if (read_from_terminal) { | ||
1601 | if (cfg.crlf) { | ||
1602 | int j, lf_num; | ||
1603 | |||
1604 | i = read(fileno(stdin), buf, bufsize / 2); | ||
1605 | lf_num = 0; | ||
1606 | /* both loops are skipped when i <= 0 */ | ||
1607 | for (j = 0; j < i; j++) | ||
1608 | if (buf[j] == '\n') | ||
1609 | lf_num++; | ||
1610 | for (j = i - 1; j >= 0; j--) { | ||
1611 | buf[j + lf_num] = buf[j]; | ||
1612 | if (buf[j] == '\n') { | ||
1613 | lf_num--; | ||
1614 | i++; | ||
1615 | buf[j + lf_num] = '\r'; | ||
1616 | } | ||
1617 | } | ||
1618 | assert(lf_num == 0); | ||
1619 | } else | ||
1620 | i = read(fileno(stdin), buf, bufsize); | ||
1621 | if (!cfg.quiet) { | ||
1622 | if ((i <= 0) || (buf[0] == 'Q')) { | ||
1623 | BIO_printf(bio_s_out, "DONE\n"); | ||
1624 | shutdown(s, SHUT_RD); | ||
1625 | close(s); | ||
1626 | close_accept_socket(); | ||
1627 | ret = -11; | ||
1628 | goto err; | ||
1629 | } | ||
1630 | if ((i <= 0) || (buf[0] == 'q')) { | ||
1631 | BIO_printf(bio_s_out, "DONE\n"); | ||
1632 | if (!SSL_is_dtls(con)) { | ||
1633 | shutdown(s, SHUT_RD); | ||
1634 | close(s); | ||
1635 | } | ||
1636 | /* | ||
1637 | * close_accept_socket(); ret= -11; | ||
1638 | */ | ||
1639 | goto err; | ||
1640 | } | ||
1641 | if ((buf[0] == 'r') && | ||
1642 | ((buf[1] == '\n') || (buf[1] == '\r'))) { | ||
1643 | SSL_renegotiate(con); | ||
1644 | i = SSL_do_handshake(con); | ||
1645 | printf("SSL_do_handshake -> %d\n", i); | ||
1646 | i = 0; /* 13; */ | ||
1647 | continue; | ||
1648 | /* | ||
1649 | * RE-NEGOTIATE\n"); | ||
1650 | */ | ||
1651 | } | ||
1652 | if ((buf[0] == 'R') && | ||
1653 | ((buf[1] == '\n') || (buf[1] == '\r'))) { | ||
1654 | SSL_set_verify(con, | ||
1655 | SSL_VERIFY_PEER | | ||
1656 | SSL_VERIFY_CLIENT_ONCE, | ||
1657 | NULL); | ||
1658 | SSL_renegotiate(con); | ||
1659 | i = SSL_do_handshake(con); | ||
1660 | printf("SSL_do_handshake -> %d\n", i); | ||
1661 | i = 0; /* 13; */ | ||
1662 | continue; | ||
1663 | /* | ||
1664 | * RE-NEGOTIATE asking for client | ||
1665 | * cert\n"); | ||
1666 | */ | ||
1667 | } | ||
1668 | if (buf[0] == 'P') { | ||
1669 | static const char *str = | ||
1670 | "Lets print some clear text\n"; | ||
1671 | BIO_write(SSL_get_wbio(con), str, | ||
1672 | strlen(str)); | ||
1673 | } | ||
1674 | if (buf[0] == 'S') { | ||
1675 | print_stats(bio_s_out, | ||
1676 | SSL_get_SSL_CTX(con)); | ||
1677 | } | ||
1678 | } | ||
1679 | l = k = 0; | ||
1680 | for (;;) { | ||
1681 | /* should do a select for the write */ | ||
1682 | #ifdef RENEG | ||
1683 | { | ||
1684 | static count = 0; | ||
1685 | if (++count == 100) { | ||
1686 | count = 0; | ||
1687 | SSL_renegotiate(con); | ||
1688 | } | ||
1689 | } | ||
1690 | #endif | ||
1691 | k = SSL_write(con, &(buf[l]), (unsigned int) i); | ||
1692 | switch (SSL_get_error(con, k)) { | ||
1693 | case SSL_ERROR_NONE: | ||
1694 | break; | ||
1695 | case SSL_ERROR_WANT_WRITE: | ||
1696 | case SSL_ERROR_WANT_READ: | ||
1697 | case SSL_ERROR_WANT_X509_LOOKUP: | ||
1698 | BIO_printf(bio_s_out, "Write BLOCK\n"); | ||
1699 | break; | ||
1700 | case SSL_ERROR_SYSCALL: | ||
1701 | case SSL_ERROR_SSL: | ||
1702 | BIO_printf(bio_s_out, "ERROR\n"); | ||
1703 | ERR_print_errors(bio_err); | ||
1704 | ret = 1; | ||
1705 | goto err; | ||
1706 | /* break; */ | ||
1707 | case SSL_ERROR_ZERO_RETURN: | ||
1708 | BIO_printf(bio_s_out, "DONE\n"); | ||
1709 | ret = 1; | ||
1710 | goto err; | ||
1711 | } | ||
1712 | if (k <= 0) | ||
1713 | continue; | ||
1714 | l += k; | ||
1715 | i -= k; | ||
1716 | if (i <= 0) | ||
1717 | break; | ||
1718 | } | ||
1719 | } | ||
1720 | if (read_from_sslcon) { | ||
1721 | if (!SSL_is_init_finished(con)) { | ||
1722 | i = init_ssl_connection(con); | ||
1723 | |||
1724 | if (i < 0) { | ||
1725 | ret = 0; | ||
1726 | goto err; | ||
1727 | } else if (i == 0) { | ||
1728 | ret = 1; | ||
1729 | goto err; | ||
1730 | } | ||
1731 | } else { | ||
1732 | again: | ||
1733 | i = SSL_read(con, (char *) buf, bufsize); | ||
1734 | switch (SSL_get_error(con, i)) { | ||
1735 | case SSL_ERROR_NONE: { | ||
1736 | int len, n; | ||
1737 | for (len = 0; len < i;) { | ||
1738 | do { | ||
1739 | n = write(fileno(stdout), buf + len, i - len); | ||
1740 | } while (n == -1 && errno == EINTR); | ||
1741 | |||
1742 | if (n == -1) { | ||
1743 | BIO_printf(bio_s_out, "ERROR\n"); | ||
1744 | goto err; | ||
1745 | } | ||
1746 | len += n; | ||
1747 | } | ||
1748 | } | ||
1749 | if (SSL_pending(con)) | ||
1750 | goto again; | ||
1751 | break; | ||
1752 | case SSL_ERROR_WANT_WRITE: | ||
1753 | case SSL_ERROR_WANT_READ: | ||
1754 | BIO_printf(bio_s_out, "Read BLOCK\n"); | ||
1755 | break; | ||
1756 | case SSL_ERROR_SYSCALL: | ||
1757 | case SSL_ERROR_SSL: | ||
1758 | BIO_printf(bio_s_out, "ERROR\n"); | ||
1759 | ERR_print_errors(bio_err); | ||
1760 | ret = 1; | ||
1761 | goto err; | ||
1762 | case SSL_ERROR_ZERO_RETURN: | ||
1763 | BIO_printf(bio_s_out, "DONE\n"); | ||
1764 | ret = 1; | ||
1765 | goto err; | ||
1766 | } | ||
1767 | } | ||
1768 | } | ||
1769 | } | ||
1770 | err: | ||
1771 | if (con != NULL) { | ||
1772 | BIO_printf(bio_s_out, "shutting down SSL\n"); | ||
1773 | SSL_set_shutdown(con, | ||
1774 | SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); | ||
1775 | SSL_free(con); | ||
1776 | } | ||
1777 | BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); | ||
1778 | freezero(buf, bufsize); | ||
1779 | if (ret >= 0) | ||
1780 | BIO_printf(bio_s_out, "ACCEPT\n"); | ||
1781 | return (ret); | ||
1782 | } | ||
1783 | |||
1784 | static void | ||
1785 | close_accept_socket(void) | ||
1786 | { | ||
1787 | BIO_printf(bio_err, "shutdown accept socket\n"); | ||
1788 | if (accept_socket >= 0) { | ||
1789 | shutdown(accept_socket, SHUT_RDWR); | ||
1790 | close(accept_socket); | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1794 | static int | ||
1795 | init_ssl_connection(SSL *con) | ||
1796 | { | ||
1797 | int i; | ||
1798 | const char *str; | ||
1799 | X509 *peer; | ||
1800 | long verify_error; | ||
1801 | char buf[BUFSIZ]; | ||
1802 | unsigned char *exportedkeymat; | ||
1803 | |||
1804 | i = SSL_accept(con); | ||
1805 | if (i <= 0) { | ||
1806 | if (BIO_sock_should_retry(i)) { | ||
1807 | BIO_printf(bio_s_out, "DELAY\n"); | ||
1808 | return (1); | ||
1809 | } | ||
1810 | BIO_printf(bio_err, "ERROR\n"); | ||
1811 | verify_error = SSL_get_verify_result(con); | ||
1812 | if (verify_error != X509_V_OK) { | ||
1813 | BIO_printf(bio_err, "verify error:%s\n", | ||
1814 | X509_verify_cert_error_string(verify_error)); | ||
1815 | } else | ||
1816 | ERR_print_errors(bio_err); | ||
1817 | return (0); | ||
1818 | } | ||
1819 | PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); | ||
1820 | |||
1821 | peer = SSL_get_peer_certificate(con); | ||
1822 | if (peer != NULL) { | ||
1823 | BIO_printf(bio_s_out, "Client certificate\n"); | ||
1824 | PEM_write_bio_X509(bio_s_out, peer); | ||
1825 | X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf); | ||
1826 | BIO_printf(bio_s_out, "subject=%s\n", buf); | ||
1827 | X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf); | ||
1828 | BIO_printf(bio_s_out, "issuer=%s\n", buf); | ||
1829 | X509_free(peer); | ||
1830 | } | ||
1831 | if (SSL_get_shared_ciphers(con, buf, sizeof buf) != NULL) | ||
1832 | BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); | ||
1833 | str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); | ||
1834 | BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); | ||
1835 | |||
1836 | #ifndef OPENSSL_NO_SRTP | ||
1837 | { | ||
1838 | SRTP_PROTECTION_PROFILE *srtp_profile | ||
1839 | = SSL_get_selected_srtp_profile(con); | ||
1840 | |||
1841 | if (srtp_profile) | ||
1842 | BIO_printf(bio_s_out, | ||
1843 | "SRTP Extension negotiated, profile=%s\n", | ||
1844 | srtp_profile->name); | ||
1845 | } | ||
1846 | #endif | ||
1847 | if (SSL_cache_hit(con)) | ||
1848 | BIO_printf(bio_s_out, "Reused session-id\n"); | ||
1849 | BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", | ||
1850 | SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); | ||
1851 | if (cfg.keymatexportlabel != NULL) { | ||
1852 | BIO_printf(bio_s_out, "Keying material exporter:\n"); | ||
1853 | BIO_printf(bio_s_out, " Label: '%s'\n", | ||
1854 | cfg.keymatexportlabel); | ||
1855 | BIO_printf(bio_s_out, " Length: %i bytes\n", | ||
1856 | cfg.keymatexportlen); | ||
1857 | exportedkeymat = malloc(cfg.keymatexportlen); | ||
1858 | if (exportedkeymat != NULL) { | ||
1859 | if (!SSL_export_keying_material(con, exportedkeymat, | ||
1860 | cfg.keymatexportlen, | ||
1861 | cfg.keymatexportlabel, | ||
1862 | strlen(cfg.keymatexportlabel), | ||
1863 | NULL, 0, 0)) { | ||
1864 | BIO_printf(bio_s_out, " Error\n"); | ||
1865 | } else { | ||
1866 | BIO_printf(bio_s_out, " Keying material: "); | ||
1867 | for (i = 0; i < cfg.keymatexportlen; i++) | ||
1868 | BIO_printf(bio_s_out, "%02X", | ||
1869 | exportedkeymat[i]); | ||
1870 | BIO_printf(bio_s_out, "\n"); | ||
1871 | } | ||
1872 | free(exportedkeymat); | ||
1873 | } | ||
1874 | } | ||
1875 | return (1); | ||
1876 | } | ||
1877 | |||
1878 | #ifndef OPENSSL_NO_DH | ||
1879 | static DH * | ||
1880 | load_dh_param(const char *dhfile) | ||
1881 | { | ||
1882 | DH *ret = NULL; | ||
1883 | BIO *bio; | ||
1884 | |||
1885 | if ((bio = BIO_new_file(dhfile, "r")) == NULL) | ||
1886 | goto err; | ||
1887 | ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | ||
1888 | err: | ||
1889 | BIO_free(bio); | ||
1890 | return (ret); | ||
1891 | } | ||
1892 | #endif | ||
1893 | |||
1894 | static int | ||
1895 | www_body(int s, unsigned char *context) | ||
1896 | { | ||
1897 | char *buf = NULL; | ||
1898 | int ret = 1; | ||
1899 | int i, j, k, dot; | ||
1900 | SSL *con; | ||
1901 | const SSL_CIPHER *c; | ||
1902 | BIO *io, *ssl_bio, *sbio; | ||
1903 | |||
1904 | buf = malloc(bufsize); | ||
1905 | if (buf == NULL) | ||
1906 | return (0); | ||
1907 | io = BIO_new(BIO_f_buffer()); | ||
1908 | ssl_bio = BIO_new(BIO_f_ssl()); | ||
1909 | if ((io == NULL) || (ssl_bio == NULL)) | ||
1910 | goto err; | ||
1911 | |||
1912 | if (cfg.nbio) { | ||
1913 | if (!cfg.quiet) | ||
1914 | BIO_printf(bio_err, "turning on non blocking io\n"); | ||
1915 | if (!BIO_socket_nbio(s, 1)) | ||
1916 | ERR_print_errors(bio_err); | ||
1917 | } | ||
1918 | |||
1919 | /* lets make the output buffer a reasonable size */ | ||
1920 | if (!BIO_set_write_buffer_size(io, bufsize)) | ||
1921 | goto err; | ||
1922 | |||
1923 | if ((con = SSL_new(ctx)) == NULL) | ||
1924 | goto err; | ||
1925 | if (cfg.tlsextdebug) { | ||
1926 | SSL_set_tlsext_debug_callback(con, tlsext_cb); | ||
1927 | SSL_set_tlsext_debug_arg(con, bio_s_out); | ||
1928 | } | ||
1929 | if (context) | ||
1930 | SSL_set_session_id_context(con, context, | ||
1931 | strlen((char *) context)); | ||
1932 | |||
1933 | sbio = BIO_new_socket(s, BIO_NOCLOSE); | ||
1934 | if (cfg.nbio_test) { | ||
1935 | BIO *test; | ||
1936 | |||
1937 | test = BIO_new(BIO_f_nbio_test()); | ||
1938 | sbio = BIO_push(test, sbio); | ||
1939 | } | ||
1940 | SSL_set_bio(con, sbio, sbio); | ||
1941 | SSL_set_accept_state(con); | ||
1942 | |||
1943 | /* SSL_set_fd(con,s); */ | ||
1944 | BIO_set_ssl(ssl_bio, con, BIO_CLOSE); | ||
1945 | BIO_push(io, ssl_bio); | ||
1946 | |||
1947 | if (cfg.debug) { | ||
1948 | BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); | ||
1949 | BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out); | ||
1950 | } | ||
1951 | if (cfg.msg) { | ||
1952 | SSL_set_msg_callback(con, msg_cb); | ||
1953 | SSL_set_msg_callback_arg(con, bio_s_out); | ||
1954 | } | ||
1955 | for (;;) { | ||
1956 | i = BIO_gets(io, buf, bufsize - 1); | ||
1957 | if (i < 0) { /* error */ | ||
1958 | if (!BIO_should_retry(io)) { | ||
1959 | if (!cfg.quiet) | ||
1960 | ERR_print_errors(bio_err); | ||
1961 | goto err; | ||
1962 | } else { | ||
1963 | if (cfg.debug) { | ||
1964 | BIO_printf(bio_s_out, "read R BLOCK\n"); | ||
1965 | sleep(1); | ||
1966 | } | ||
1967 | continue; | ||
1968 | } | ||
1969 | } else if (i == 0) { /* end of input */ | ||
1970 | ret = 1; | ||
1971 | goto end; | ||
1972 | } | ||
1973 | /* else we have data */ | ||
1974 | if (((cfg.www == 1) && | ||
1975 | (strncmp("GET ", buf, 4) == 0)) || | ||
1976 | ((cfg.www == 2) && | ||
1977 | (strncmp("GET /stats ", buf, 11) == 0))) { | ||
1978 | char *p; | ||
1979 | X509 *peer; | ||
1980 | STACK_OF(SSL_CIPHER) *sk; | ||
1981 | static const char *space = " "; | ||
1982 | |||
1983 | BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); | ||
1984 | BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n"); | ||
1985 | BIO_puts(io, "<pre>\n"); | ||
1986 | /* BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/ | ||
1987 | BIO_puts(io, "\n"); | ||
1988 | for (i = 0; i < local_argc; i++) { | ||
1989 | BIO_puts(io, local_argv[i]); | ||
1990 | BIO_write(io, " ", 1); | ||
1991 | } | ||
1992 | BIO_puts(io, "\n"); | ||
1993 | |||
1994 | BIO_printf(io, | ||
1995 | "Secure Renegotiation IS%s supported\n", | ||
1996 | SSL_get_secure_renegotiation_support(con) ? | ||
1997 | "" : " NOT"); | ||
1998 | |||
1999 | /* | ||
2000 | * The following is evil and should not really be | ||
2001 | * done | ||
2002 | */ | ||
2003 | BIO_printf(io, | ||
2004 | "Ciphers supported in s_server binary\n"); | ||
2005 | sk = SSL_get_ciphers(con); | ||
2006 | j = sk_SSL_CIPHER_num(sk); | ||
2007 | for (i = 0; i < j; i++) { | ||
2008 | c = sk_SSL_CIPHER_value(sk, i); | ||
2009 | BIO_printf(io, "%-11s:%-25s", | ||
2010 | SSL_CIPHER_get_version(c), | ||
2011 | SSL_CIPHER_get_name(c)); | ||
2012 | if ((((i + 1) % 2) == 0) && (i + 1 != j)) | ||
2013 | BIO_puts(io, "\n"); | ||
2014 | } | ||
2015 | BIO_puts(io, "\n"); | ||
2016 | p = SSL_get_shared_ciphers(con, buf, bufsize); | ||
2017 | if (p != NULL) { | ||
2018 | BIO_printf(io, | ||
2019 | "---\nCiphers common between both SSL end points:\n"); | ||
2020 | j = i = 0; | ||
2021 | while (*p) { | ||
2022 | if (*p == ':') { | ||
2023 | BIO_write(io, space, 26 - j); | ||
2024 | i++; | ||
2025 | j = 0; | ||
2026 | BIO_write(io, | ||
2027 | ((i % 3) ? " " : "\n"), 1); | ||
2028 | } else { | ||
2029 | BIO_write(io, p, 1); | ||
2030 | j++; | ||
2031 | } | ||
2032 | p++; | ||
2033 | } | ||
2034 | BIO_puts(io, "\n"); | ||
2035 | } | ||
2036 | BIO_printf(io, (SSL_cache_hit(con) | ||
2037 | ? "---\nReused, " | ||
2038 | : "---\nNew, ")); | ||
2039 | c = SSL_get_current_cipher(con); | ||
2040 | BIO_printf(io, "%s, Cipher is %s\n", | ||
2041 | SSL_CIPHER_get_version(c), | ||
2042 | SSL_CIPHER_get_name(c)); | ||
2043 | SSL_SESSION_print(io, SSL_get_session(con)); | ||
2044 | BIO_printf(io, "---\n"); | ||
2045 | print_stats(io, SSL_get_SSL_CTX(con)); | ||
2046 | BIO_printf(io, "---\n"); | ||
2047 | peer = SSL_get_peer_certificate(con); | ||
2048 | if (peer != NULL) { | ||
2049 | BIO_printf(io, "Client certificate\n"); | ||
2050 | X509_print(io, peer); | ||
2051 | PEM_write_bio_X509(io, peer); | ||
2052 | } else | ||
2053 | BIO_puts(io, | ||
2054 | "no client certificate available\n"); | ||
2055 | BIO_puts(io, "</BODY></HTML>\r\n\r\n"); | ||
2056 | break; | ||
2057 | } else if ((cfg.www == 2 || | ||
2058 | cfg.www == 3) && | ||
2059 | (strncmp("GET /", buf, 5) == 0)) { | ||
2060 | BIO *file; | ||
2061 | char *p, *e; | ||
2062 | static const char *text = "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"; | ||
2063 | |||
2064 | /* skip the '/' */ | ||
2065 | p = &(buf[5]); | ||
2066 | |||
2067 | dot = 1; | ||
2068 | for (e = p; *e != '\0'; e++) { | ||
2069 | if (e[0] == ' ') | ||
2070 | break; | ||
2071 | |||
2072 | switch (dot) { | ||
2073 | case 1: | ||
2074 | dot = (e[0] == '.') ? 2 : 0; | ||
2075 | break; | ||
2076 | case 2: | ||
2077 | dot = (e[0] == '.') ? 3 : 0; | ||
2078 | break; | ||
2079 | case 3: | ||
2080 | dot = (e[0] == '/' || e[0] == '\\') ? | ||
2081 | -1 : 0; | ||
2082 | break; | ||
2083 | } | ||
2084 | if (dot == 0) | ||
2085 | dot = (e[0] == '/' || e[0] == '\\') ? | ||
2086 | 1 : 0; | ||
2087 | } | ||
2088 | dot = (dot == 3) || (dot == -1); /* filename contains | ||
2089 | * ".." component */ | ||
2090 | |||
2091 | if (*e == '\0') { | ||
2092 | BIO_puts(io, text); | ||
2093 | BIO_printf(io, | ||
2094 | "'%s' is an invalid file name\r\n", p); | ||
2095 | break; | ||
2096 | } | ||
2097 | *e = '\0'; | ||
2098 | |||
2099 | if (dot) { | ||
2100 | BIO_puts(io, text); | ||
2101 | BIO_printf(io, | ||
2102 | "'%s' contains '..' reference\r\n", p); | ||
2103 | break; | ||
2104 | } | ||
2105 | if (*p == '/') { | ||
2106 | BIO_puts(io, text); | ||
2107 | BIO_printf(io, | ||
2108 | "'%s' is an invalid path\r\n", p); | ||
2109 | break; | ||
2110 | } | ||
2111 | /* if a directory, do the index thang */ | ||
2112 | if (app_isdir(p) > 0) { | ||
2113 | BIO_puts(io, text); | ||
2114 | BIO_printf(io, "'%s' is a directory\r\n", p); | ||
2115 | break; | ||
2116 | } | ||
2117 | if ((file = BIO_new_file(p, "r")) == NULL) { | ||
2118 | BIO_puts(io, text); | ||
2119 | BIO_printf(io, "Error opening '%s'\r\n", p); | ||
2120 | ERR_print_errors(io); | ||
2121 | break; | ||
2122 | } | ||
2123 | if (!cfg.quiet) | ||
2124 | BIO_printf(bio_err, "FILE:%s\n", p); | ||
2125 | |||
2126 | if (cfg.www == 2) { | ||
2127 | i = strlen(p); | ||
2128 | if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) || | ||
2129 | ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) || | ||
2130 | ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0))) | ||
2131 | BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); | ||
2132 | else | ||
2133 | BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); | ||
2134 | } | ||
2135 | /* send the file */ | ||
2136 | for (;;) { | ||
2137 | i = BIO_read(file, buf, bufsize); | ||
2138 | if (i <= 0) | ||
2139 | break; | ||
2140 | |||
2141 | #ifdef RENEG | ||
2142 | total_bytes += i; | ||
2143 | fprintf(stderr, "%d\n", i); | ||
2144 | if (total_bytes > 3 * 1024) { | ||
2145 | total_bytes = 0; | ||
2146 | fprintf(stderr, "RENEGOTIATE\n"); | ||
2147 | SSL_renegotiate(con); | ||
2148 | } | ||
2149 | #endif | ||
2150 | |||
2151 | for (j = 0; j < i;) { | ||
2152 | #ifdef RENEG | ||
2153 | { | ||
2154 | static count = 0; | ||
2155 | if (++count == 13) { | ||
2156 | SSL_renegotiate(con); | ||
2157 | } | ||
2158 | } | ||
2159 | #endif | ||
2160 | k = BIO_write(io, &(buf[j]), i - j); | ||
2161 | if (k <= 0) { | ||
2162 | if (!BIO_should_retry(io)) | ||
2163 | goto write_error; | ||
2164 | else { | ||
2165 | BIO_printf(bio_s_out, | ||
2166 | "rwrite W BLOCK\n"); | ||
2167 | } | ||
2168 | } else { | ||
2169 | j += k; | ||
2170 | } | ||
2171 | } | ||
2172 | } | ||
2173 | write_error: | ||
2174 | BIO_free(file); | ||
2175 | break; | ||
2176 | } | ||
2177 | } | ||
2178 | |||
2179 | for (;;) { | ||
2180 | i = (int) BIO_flush(io); | ||
2181 | if (i <= 0) { | ||
2182 | if (!BIO_should_retry(io)) | ||
2183 | break; | ||
2184 | } else | ||
2185 | break; | ||
2186 | } | ||
2187 | end: | ||
2188 | /* make sure we re-use sessions */ | ||
2189 | SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); | ||
2190 | |||
2191 | err: | ||
2192 | |||
2193 | if (ret >= 0) | ||
2194 | BIO_printf(bio_s_out, "ACCEPT\n"); | ||
2195 | |||
2196 | free(buf); | ||
2197 | BIO_free_all(io); | ||
2198 | /* if (ssl_bio != NULL) BIO_free(ssl_bio);*/ | ||
2199 | return (ret); | ||
2200 | } | ||
2201 | |||
2202 | #define MAX_SESSION_ID_ATTEMPTS 10 | ||
2203 | static int | ||
2204 | generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) | ||
2205 | { | ||
2206 | unsigned int count = 0; | ||
2207 | do { | ||
2208 | arc4random_buf(id, *id_len); | ||
2209 | /* | ||
2210 | * Prefix the session_id with the required prefix. NB: If our | ||
2211 | * prefix is too long, clip it - but there will be worse | ||
2212 | * effects anyway, eg. the server could only possibly create | ||
2213 | * 1 session ID (ie. the prefix!) so all future session | ||
2214 | * negotiations will fail due to conflicts. | ||
2215 | */ | ||
2216 | memcpy(id, cfg.session_id_prefix, | ||
2217 | (strlen(cfg.session_id_prefix) < *id_len) ? | ||
2218 | strlen(cfg.session_id_prefix) : *id_len); | ||
2219 | } | ||
2220 | while (SSL_has_matching_session_id(ssl, id, *id_len) && | ||
2221 | (++count < MAX_SESSION_ID_ATTEMPTS)); | ||
2222 | if (count >= MAX_SESSION_ID_ATTEMPTS) | ||
2223 | return 0; | ||
2224 | return 1; | ||
2225 | } | ||
2226 | |||
2227 | static int | ||
2228 | ssl_servername_cb(SSL *s, int *ad, void *arg) | ||
2229 | { | ||
2230 | tlsextctx *p = (tlsextctx *) arg; | ||
2231 | const char *servername = SSL_get_servername(s, | ||
2232 | TLSEXT_NAMETYPE_host_name); | ||
2233 | |||
2234 | if (servername && p->biodebug) | ||
2235 | BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", | ||
2236 | servername); | ||
2237 | |||
2238 | if (!p->servername) | ||
2239 | return SSL_TLSEXT_ERR_NOACK; | ||
2240 | |||
2241 | if (servername) { | ||
2242 | if (strcmp(servername, p->servername)) | ||
2243 | return p->extension_error; | ||
2244 | if (ctx2) { | ||
2245 | BIO_printf(p->biodebug, "Switching server context.\n"); | ||
2246 | SSL_set_SSL_CTX(s, ctx2); | ||
2247 | } | ||
2248 | } | ||
2249 | return SSL_TLSEXT_ERR_OK; | ||
2250 | } | ||
2251 | |||
2252 | /* Certificate Status callback. This is called when a client includes a | ||
2253 | * certificate status request extension. | ||
2254 | * | ||
2255 | * This is a simplified version. It examines certificates each time and | ||
2256 | * makes one OCSP responder query for each request. | ||
2257 | * | ||
2258 | * A full version would store details such as the OCSP certificate IDs and | ||
2259 | * minimise the number of OCSP responses by caching them until they were | ||
2260 | * considered "expired". | ||
2261 | */ | ||
2262 | |||
2263 | static int | ||
2264 | cert_status_cb(SSL *s, void *arg) | ||
2265 | { | ||
2266 | tlsextstatusctx *srctx = arg; | ||
2267 | BIO *err = srctx->err; | ||
2268 | char *host = NULL, *port = NULL, *path = NULL; | ||
2269 | int use_ssl; | ||
2270 | unsigned char *rspder = NULL; | ||
2271 | int rspderlen; | ||
2272 | STACK_OF(OPENSSL_STRING) *aia = NULL; | ||
2273 | X509 *x = NULL; | ||
2274 | X509_STORE_CTX *inctx = NULL; | ||
2275 | X509_OBJECT *obj = NULL; | ||
2276 | OCSP_REQUEST *req = NULL; | ||
2277 | OCSP_RESPONSE *resp = NULL; | ||
2278 | OCSP_CERTID *id = NULL; | ||
2279 | STACK_OF(X509_EXTENSION) *exts; | ||
2280 | int ret = SSL_TLSEXT_ERR_NOACK; | ||
2281 | int i; | ||
2282 | |||
2283 | if (srctx->verbose) | ||
2284 | BIO_puts(err, "cert_status: callback called\n"); | ||
2285 | /* Build up OCSP query from server certificate */ | ||
2286 | x = SSL_get_certificate(s); | ||
2287 | aia = X509_get1_ocsp(x); | ||
2288 | if (aia) { | ||
2289 | if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), | ||
2290 | &host, &port, &path, &use_ssl)) { | ||
2291 | BIO_puts(err, "cert_status: can't parse AIA URL\n"); | ||
2292 | goto err; | ||
2293 | } | ||
2294 | if (srctx->verbose) | ||
2295 | BIO_printf(err, "cert_status: AIA URL: %s\n", | ||
2296 | sk_OPENSSL_STRING_value(aia, 0)); | ||
2297 | } else { | ||
2298 | if (!srctx->host) { | ||
2299 | BIO_puts(srctx->err, | ||
2300 | "cert_status: no AIA and no default responder URL\n"); | ||
2301 | goto done; | ||
2302 | } | ||
2303 | host = srctx->host; | ||
2304 | path = srctx->path; | ||
2305 | port = srctx->port; | ||
2306 | use_ssl = srctx->use_ssl; | ||
2307 | } | ||
2308 | |||
2309 | if ((inctx = X509_STORE_CTX_new()) == NULL) | ||
2310 | goto err; | ||
2311 | |||
2312 | if (!X509_STORE_CTX_init(inctx, | ||
2313 | SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), | ||
2314 | NULL, NULL)) | ||
2315 | goto err; | ||
2316 | if ((obj = X509_OBJECT_new()) == NULL) | ||
2317 | goto done; | ||
2318 | if (X509_STORE_get_by_subject(inctx, X509_LU_X509, | ||
2319 | X509_get_issuer_name(x), obj) <= 0) { | ||
2320 | BIO_puts(err, | ||
2321 | "cert_status: Can't retrieve issuer certificate.\n"); | ||
2322 | X509_STORE_CTX_cleanup(inctx); | ||
2323 | goto done; | ||
2324 | } | ||
2325 | req = OCSP_REQUEST_new(); | ||
2326 | if (!req) | ||
2327 | goto err; | ||
2328 | id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj)); | ||
2329 | X509_OBJECT_free(obj); | ||
2330 | obj = NULL; | ||
2331 | X509_STORE_CTX_free(inctx); | ||
2332 | inctx = NULL; | ||
2333 | if (!id) | ||
2334 | goto err; | ||
2335 | if (!OCSP_request_add0_id(req, id)) | ||
2336 | goto err; | ||
2337 | id = NULL; | ||
2338 | /* Add any extensions to the request */ | ||
2339 | SSL_get_tlsext_status_exts(s, &exts); | ||
2340 | for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { | ||
2341 | X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); | ||
2342 | if (!OCSP_REQUEST_add_ext(req, ext, -1)) | ||
2343 | goto err; | ||
2344 | } | ||
2345 | resp = process_responder(err, req, host, path, port, use_ssl, NULL, | ||
2346 | srctx->timeout); | ||
2347 | if (!resp) { | ||
2348 | BIO_puts(err, "cert_status: error querying responder\n"); | ||
2349 | goto done; | ||
2350 | } | ||
2351 | rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); | ||
2352 | if (rspderlen <= 0) | ||
2353 | goto err; | ||
2354 | SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); | ||
2355 | if (srctx->verbose) { | ||
2356 | BIO_puts(err, "cert_status: ocsp response sent:\n"); | ||
2357 | OCSP_RESPONSE_print(err, resp, 2); | ||
2358 | } | ||
2359 | ret = SSL_TLSEXT_ERR_OK; | ||
2360 | done: | ||
2361 | X509_STORE_CTX_free(inctx); | ||
2362 | X509_OBJECT_free(obj); | ||
2363 | if (ret != SSL_TLSEXT_ERR_OK) | ||
2364 | ERR_print_errors(err); | ||
2365 | if (aia) { | ||
2366 | free(host); | ||
2367 | free(path); | ||
2368 | free(port); | ||
2369 | X509_email_free(aia); | ||
2370 | } | ||
2371 | if (id) | ||
2372 | OCSP_CERTID_free(id); | ||
2373 | if (req) | ||
2374 | OCSP_REQUEST_free(req); | ||
2375 | if (resp) | ||
2376 | OCSP_RESPONSE_free(resp); | ||
2377 | return ret; | ||
2378 | err: | ||
2379 | ret = SSL_TLSEXT_ERR_ALERT_FATAL; | ||
2380 | goto done; | ||
2381 | } | ||
2382 | |||
2383 | static int | ||
2384 | alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
2385 | const unsigned char *in, unsigned int inlen, void *arg) | ||
2386 | { | ||
2387 | tlsextalpnctx *alpn_ctx = arg; | ||
2388 | |||
2389 | if (!cfg.quiet) { | ||
2390 | /* We can assume that in is syntactically valid. */ | ||
2391 | unsigned i; | ||
2392 | |||
2393 | BIO_printf(bio_s_out, | ||
2394 | "ALPN protocols advertised by the client: "); | ||
2395 | for (i = 0; i < inlen; ) { | ||
2396 | if (i) | ||
2397 | BIO_write(bio_s_out, ", ", 2); | ||
2398 | BIO_write(bio_s_out, &in[i + 1], in[i]); | ||
2399 | i += in[i] + 1; | ||
2400 | } | ||
2401 | BIO_write(bio_s_out, "\n", 1); | ||
2402 | } | ||
2403 | |||
2404 | if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data, | ||
2405 | alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) | ||
2406 | return (SSL_TLSEXT_ERR_NOACK); | ||
2407 | |||
2408 | if (!cfg.quiet) { | ||
2409 | BIO_printf(bio_s_out, "ALPN protocols selected: "); | ||
2410 | BIO_write(bio_s_out, *out, *outlen); | ||
2411 | BIO_write(bio_s_out, "\n", 1); | ||
2412 | } | ||
2413 | |||
2414 | return (SSL_TLSEXT_ERR_OK); | ||
2415 | } | ||