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