X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=apps%2Fs_server.c;h=930ef6e4a863bf727bbdc701270b1fb0eb2c123d;hb=93a8b3ba793c769a3634e56642dac55a8d44023f;hp=f3494120e0130c391d40bd044c87b7c7aca9e33d;hpb=6530c4909ffbf4fd655416cbd765b1e7174b9b83;p=openssl.git diff --git a/apps/s_server.c b/apps/s_server.c index f3494120e0..930ef6e4a8 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -91,9 +91,9 @@ typedef unsigned int u_int; #endif static int not_resumable_sess_cb(SSL *s, int is_forward_secure); -static int sv_body(int s, int stype, unsigned char *context); -static int www_body(int s, int stype, unsigned char *context); -static int rev_body(int s, int stype, unsigned char *context); +static int sv_body(int s, int stype, int prot, unsigned char *context); +static int www_body(int s, int stype, int prot, unsigned char *context); +static int rev_body(int s, int stype, int prot, unsigned char *context); static void close_accept_socket(void); static int init_ssl_connection(SSL *s); static void print_stats(BIO *bp, SSL_CTX *ctx); @@ -104,8 +104,7 @@ static void free_sessions(void); #ifndef OPENSSL_NO_DH static DH *load_dh_param(const char *dhfile); #endif - -/* static int load_CA(SSL_CTX *ctx, char *file);*/ +static void print_connection_info(SSL *con); static const int bufsize = 16 * 1024; static int accept_socket = -1; @@ -139,10 +138,16 @@ static const char *session_id_prefix = NULL; #ifndef OPENSSL_NO_DTLS static int enable_timeouts = 0; static long socket_mtu; - #endif + +/* + * We define this but make it always be 0 in no-dtls builds to simplify the + * code. + */ static int dtlslisten = 0; +static int early_data = 0; + #ifndef OPENSSL_NO_PSK static char *psk_identity = "Client_identity"; char *psk_key = NULL; /* by default PSK is not used */ @@ -156,7 +161,7 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, if (s_debug) BIO_printf(bio_s_out, "psk_server_cb\n"); - if (!identity) { + if (identity == NULL) { BIO_printf(bio_err, "Error: client did not send PSK identity\n"); goto out_err; } @@ -166,12 +171,12 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, /* here we could lookup the given identity e.g. from a database */ if (strcmp(identity, psk_identity) != 0) { - BIO_printf(bio_s_out, "PSK error: client identity not found" + BIO_printf(bio_s_out, "PSK warning: client identity not what we expected" " (got '%s' expected '%s')\n", identity, psk_identity); - goto out_err; - } - if (s_debug) + } else { + if (s_debug) BIO_printf(bio_s_out, "PSK client identity found\n"); + } /* convert the PSK key to binary */ key = OPENSSL_hexstr2buf(psk_key, &key_len); @@ -430,17 +435,17 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg) { tlsextctx *p = (tlsextctx *) arg; const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); - if (servername && p->biodebug) + if (servername != NULL && p->biodebug != NULL) BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", servername); - if (!p->servername) + if (p->servername == NULL) return SSL_TLSEXT_ERR_NOACK; - if (servername) { + if (servername != NULL) { if (strcasecmp(servername, p->servername)) return p->extension_error; - if (ctx2) { + if (ctx2 != NULL) { BIO_printf(p->biodebug, "Switching server context.\n"); SSL_set_SSL_CTX(s, ctx2); } @@ -449,7 +454,6 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg) } /* Structure passed to cert status callback */ - typedef struct tlsextstatusctx_st { int timeout; /* File to load OCSP Response from (or NULL if no file) */ @@ -489,7 +493,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, /* Build up OCSP query from server certificate */ x = SSL_get_certificate(s); aia = X509_get1_ocsp(x); - if (aia) { + if (aia != NULL) { if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &host, &port, &path, &use_ssl)) { BIO_puts(bio_err, "cert_status: can't parse AIA URL\n"); @@ -499,7 +503,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, BIO_printf(bio_err, "cert_status: AIA URL: %s\n", sk_OPENSSL_STRING_value(aia, 0)); } else { - if (!srctx->host) { + if (srctx->host == NULL) { BIO_puts(bio_err, "cert_status: no AIA and no default responder URL\n"); goto done; @@ -525,7 +529,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, } id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj)); X509_OBJECT_free(obj); - if (!id) + if (id == NULL) goto err; req = OCSP_REQUEST_new(); if (req == NULL) @@ -629,7 +633,7 @@ static int cert_status_cb(SSL *s, void *arg) /* This is the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { unsigned char *data; - unsigned int len; + size_t len; } tlsextnextprotoctx; static int next_proto_cb(SSL *s, const unsigned char **data, @@ -699,7 +703,7 @@ static char *srtp_profiles = NULL; typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, - OPT_VERIFY, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, + OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT, OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT, @@ -711,14 +715,16 @@ typedef enum OPTION_choice { OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, - OPT_NO_RESUME_EPHEMERAL, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE, + OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, - OPT_SSL_CONFIG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, + OPT_SSL_CONFIG, + OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, - OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, + OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA, OPT_S_ENUM, OPT_V_ENUM, OPT_X_ENUM @@ -743,6 +749,7 @@ const OPTIONS s_server_options[] = { {"Verify", OPT_UPPER_V_VERIFY, 'n', "Turn on peer certificate verification, must have a cert"}, {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, {"serverinfo", OPT_SERVERINFO, 's', "PEM serverinfo file for certificate"}, @@ -850,17 +857,19 @@ const OPTIONS s_server_options[] = { {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, {"ssl_config", OPT_SSL_CONFIG, 's', "Configure SSL_CTX using the configuration 'val'"}, - {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'n', + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', "Size used to split data for encrypt pipelines"}, - {"max_pipelines", OPT_MAX_PIPELINES, 'n', + {"max_pipelines", OPT_MAX_PIPELINES, 'p', "Maximum number of encrypt/decrypt pipelines to be used"}, - {"read_buf", OPT_READ_BUF, 'n', + {"read_buf", OPT_READ_BUF, 'p', "Default read buffer size to be used for connections"}, OPT_S_OPTIONS, OPT_V_OPTIONS, OPT_X_OPTIONS, {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, #ifndef OPENSSL_NO_PSK + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"}, {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"}, {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, #endif @@ -897,6 +906,9 @@ const OPTIONS s_server_options[] = { #ifndef OPENSSL_NO_DTLS1_2 {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, #endif +#ifndef OPENSSL_NO_SCTP + {"sctp", OPT_SCTP, '-', "Use SCTP"}, +#endif #ifndef OPENSSL_NO_DH {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, #endif @@ -913,6 +925,10 @@ const OPTIONS s_server_options[] = { #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + {"max_early_data", OPT_MAX_EARLY, 'n', + "The maximum number of bytes of early data"}, + {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, {NULL, OPT_EOF, 0, NULL} }; @@ -950,7 +966,7 @@ int s_server_main(int argc, char *argv[]) int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; int rev = 0, naccept = -1, sdebug = 0; - int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; int state = 0, crl_format = FORMAT_PEM, crl_download = 0; char *host = NULL; char *port = BUF_strdup(PORT); @@ -969,7 +985,7 @@ int s_server_main(int argc, char *argv[]) tlsextalpnctx alpn_ctx = { NULL, 0 }; #ifndef OPENSSL_NO_PSK /* by default do not send a PSK identity hint */ - static char *psk_identity_hint = NULL; + char *psk_identity_hint = NULL; char *p; #endif #ifndef OPENSSL_NO_SRP @@ -986,8 +1002,11 @@ int s_server_main(int argc, char *argv[]) int s_tlsextstatus = 0; #endif int no_resume_ephemeral = 0; + unsigned int max_send_fragment = 0; unsigned int split_send_fragment = 0, max_pipelines = 0; const char *s_serverinfo_file = NULL; + const char *keylog_file = NULL; + int max_early_data = -1; /* Init of few remaining global variables */ local_argc = argc; @@ -1124,6 +1143,10 @@ int s_server_main(int argc, char *argv[]) case OPT_CERT: s_cert_file = opt_arg(); break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; case OPT_CRL: crl_file = opt_arg(); break; @@ -1329,6 +1352,11 @@ int s_server_main(int argc, char *argv[]) case OPT_NO_RESUME_EPHEMERAL: no_resume_ephemeral = 1; break; + case OPT_PSK_IDENTITY: +#ifndef OPENSSL_NO_PSK + psk_identity = opt_arg(); +#endif + break; case OPT_PSK_HINT: #ifndef OPENSSL_NO_PSK psk_identity_hint = opt_arg(); @@ -1413,6 +1441,11 @@ int s_server_main(int argc, char *argv[]) min_version = DTLS1_2_VERSION; max_version = DTLS1_2_VERSION; socket_type = SOCK_DGRAM; +#endif + break; + case OPT_SCTP: +#ifndef OPENSSL_NO_SCTP + protocol = IPPROTO_SCTP; #endif break; case OPT_TIMEOUT: @@ -1473,15 +1506,11 @@ int s_server_main(int argc, char *argv[]) case OPT_ASYNC: async = 1; break; + case OPT_MAX_SEND_FRAG: + max_send_fragment = atoi(opt_arg()); + break; case OPT_SPLIT_SEND_FRAG: split_send_fragment = atoi(opt_arg()); - if (split_send_fragment == 0) { - /* - * Not allowed - set to a deliberately bad value so we get an - * error message below - */ - split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH + 1; - } break; case OPT_MAX_PIPELINES: max_pipelines = atoi(opt_arg()); @@ -1489,12 +1518,30 @@ int s_server_main(int argc, char *argv[]) case OPT_READ_BUF: read_buf_len = atoi(opt_arg()); break; - + case OPT_KEYLOG_FILE: + keylog_file = opt_arg(); + break; + case OPT_MAX_EARLY: + max_early_data = atoi(opt_arg()); + if (max_early_data < 0) { + BIO_printf(bio_err, "Invalid value for max_early_data\n"); + goto end; + } + break; + case OPT_EARLY_DATA: + early_data = 1; + break; } } argc = opt_num_rest(); argv = opt_rest(); +#ifndef OPENSSL_NO_NEXTPROTONEG + if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { + BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); + goto opthelp; + } +#endif #ifndef OPENSSL_NO_DTLS if (www && socket_type == SOCK_DGRAM) { BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n"); @@ -1515,15 +1562,16 @@ int s_server_main(int argc, char *argv[]) } #endif - if (split_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { - BIO_printf(bio_err, "Bad split send fragment size\n"); - goto end; - } - - if (max_pipelines > SSL_MAX_PIPELINES) { - BIO_printf(bio_err, "Bad max pipelines value\n"); - goto end; +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + if (socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); + goto end; + } + /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ + socket_type = SOCK_STREAM; } +#endif if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { BIO_printf(bio_err, "Error getting password\n"); @@ -1542,7 +1590,7 @@ int s_server_main(int argc, char *argv[]) if (nocert == 0) { s_key = load_key(s_key_file, s_key_format, 0, pass, engine, "server certificate private key file"); - if (!s_key) { + if (s_key == NULL) { ERR_print_errors(bio_err); goto end; } @@ -1550,20 +1598,20 @@ int s_server_main(int argc, char *argv[]) s_cert = load_cert(s_cert_file, s_cert_format, "server certificate file"); - if (!s_cert) { + if (s_cert == NULL) { ERR_print_errors(bio_err); goto end; } - if (s_chain_file) { + if (s_chain_file != NULL) { if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, "server certificate chain")) goto end; } - if (tlsextcbp.servername) { + if (tlsextcbp.servername != NULL) { s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine, "second server certificate private key file"); - if (!s_key2) { + if (s_key2 == NULL) { ERR_print_errors(bio_err); goto end; } @@ -1571,7 +1619,7 @@ int s_server_main(int argc, char *argv[]) s_cert2 = load_cert(s_cert_file2, s_cert_format, "second server certificate file"); - if (!s_cert2) { + if (s_cert2 == NULL) { ERR_print_errors(bio_err); goto end; } @@ -1579,34 +1627,28 @@ int s_server_main(int argc, char *argv[]) } #if !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto_neg_in) { - size_t len; - next_proto.data = next_protos_parse(&len, next_proto_neg_in); + next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); if (next_proto.data == NULL) goto end; - next_proto.len = len; - } else { - next_proto.data = NULL; } #endif alpn_ctx.data = NULL; if (alpn_in) { - size_t len; - alpn_ctx.data = next_protos_parse(&len, alpn_in); + alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in); if (alpn_ctx.data == NULL) goto end; - alpn_ctx.len = len; } - if (crl_file) { + if (crl_file != NULL) { X509_CRL *crl; crl = load_crl(crl_file, crl_format); - if (!crl) { + if (crl == NULL) { BIO_puts(bio_err, "Error loading CRL\n"); ERR_print_errors(bio_err); goto end; } crls = sk_X509_CRL_new_null(); - if (!crls || !sk_X509_CRL_push(crls, crl)) { + if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { BIO_puts(bio_err, "Error adding CRL\n"); ERR_print_errors(bio_err); X509_CRL_free(crl); @@ -1614,14 +1656,14 @@ int s_server_main(int argc, char *argv[]) } } - if (s_dcert_file) { + if (s_dcert_file != NULL) { if (s_dkey_file == NULL) s_dkey_file = s_dcert_file; s_dkey = load_key(s_dkey_file, s_dkey_format, 0, dpass, engine, "second certificate private key file"); - if (!s_dkey) { + if (s_dkey == NULL) { ERR_print_errors(bio_err); goto end; } @@ -1629,11 +1671,11 @@ int s_server_main(int argc, char *argv[]) s_dcert = load_cert(s_dcert_file, s_dcert_format, "second server certificate file"); - if (!s_dcert) { + if (s_dcert == NULL) { ERR_print_errors(bio_err); goto end; } - if (s_dchain_file) { + if (s_dchain_file != NULL) { if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, "second server certificate chain")) goto end; @@ -1653,7 +1695,7 @@ int s_server_main(int argc, char *argv[]) if (bio_s_out == NULL) { if (s_quiet && !s_debug) { bio_s_out = BIO_new(BIO_s_null()); - if (s_msg && !bio_s_msg) + if (s_msg && bio_s_msg == NULL) bio_s_msg = dup_bio_out(FORMAT_TEXT); } else { if (bio_s_out == NULL) @@ -1704,7 +1746,7 @@ int s_server_main(int argc, char *argv[]) BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx, 1); - if (exc) + if (exc != NULL) ssl_ctx_set_excert(ctx, exc); if (state) @@ -1719,11 +1761,25 @@ int s_server_main(int argc, char *argv[]) if (async) { SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); } - if (split_send_fragment > 0) { - SSL_CTX_set_split_send_fragment(ctx, split_send_fragment); + + if (max_send_fragment > 0 + && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { + BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", + prog, max_send_fragment); + goto end; + } + + if (split_send_fragment > 0 + && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { + BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", + prog, split_send_fragment); + goto end; } - if (max_pipelines > 0) { - SSL_CTX_set_max_pipelines(ctx, max_pipelines); + if (max_pipelines > 0 + && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { + BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", + prog, max_pipelines); + goto end; } if (read_buf_len > 0) { @@ -1769,7 +1825,7 @@ int s_server_main(int argc, char *argv[]) } } - if (ctx2) { + if (ctx2 != NULL) { BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); if (sdebug) @@ -1787,7 +1843,7 @@ int s_server_main(int argc, char *argv[]) BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx2, 1); - if (exc) + if (exc != NULL) ssl_ctx_set_excert(ctx2, exc); if (state) @@ -1830,9 +1886,9 @@ int s_server_main(int argc, char *argv[]) if (!no_dhe) { DH *dh = NULL; - if (dhfile) + if (dhfile != NULL) dh = load_dh_param(dhfile); - else if (s_cert_file) + else if (s_cert_file != NULL) dh = load_dh_param(s_cert_file); if (dh != NULL) { @@ -1842,16 +1898,16 @@ int s_server_main(int argc, char *argv[]) } (void)BIO_flush(bio_s_out); - if (dh == NULL) + if (dh == NULL) { SSL_CTX_set_dh_auto(ctx, 1); - else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { + } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { BIO_puts(bio_err, "Error setting temp DH parameters\n"); ERR_print_errors(bio_err); DH_free(dh); goto end; } - if (ctx2) { + if (ctx2 != NULL) { if (!dhfile) { DH *dh2 = load_dh_param(s_cert_file2); if (dh2 != NULL) { @@ -1862,9 +1918,9 @@ int s_server_main(int argc, char *argv[]) dh = dh2; } } - if (dh == NULL) + if (dh == NULL) { SSL_CTX_set_dh_auto(ctx2, 1); - else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { + } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { BIO_puts(bio_err, "Error setting temp DH parameters\n"); ERR_print_errors(bio_err); DH_free(dh); @@ -1884,7 +1940,8 @@ int s_server_main(int argc, char *argv[]) goto end; } - if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) + if (ctx2 != NULL + && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) goto end; if (s_dcert != NULL) { @@ -1896,7 +1953,7 @@ int s_server_main(int argc, char *argv[]) SSL_CTX_set_not_resumable_session_callback(ctx, not_resumable_sess_cb); - if (ctx2) + if (ctx2 != NULL) SSL_CTX_set_not_resumable_session_callback(ctx2, not_resumable_sess_cb); } @@ -1927,7 +1984,7 @@ int s_server_main(int argc, char *argv[]) SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); - if (ctx2) { + if (ctx2 != NULL) { SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback); if (!SSL_CTX_set_session_id_context(ctx2, (void *)&s_server_session_id_context, @@ -1977,6 +2034,11 @@ int s_server_main(int argc, char *argv[]) } } #endif + if (set_keylog_file(ctx, keylog_file)) + goto end; + + if (max_early_data >= 0) + SSL_CTX_set_max_early_data(ctx, max_early_data); BIO_printf(bio_s_out, "ACCEPT\n"); (void)BIO_flush(bio_s_out); @@ -1991,12 +2053,13 @@ int s_server_main(int argc, char *argv[]) && unlink_unix_path) unlink(host); #endif - do_server(&accept_socket, host, port, socket_family, socket_type, + do_server(&accept_socket, host, port, socket_family, socket_type, protocol, server_cb, context, naccept); print_stats(bio_s_out, ctx); ret = 0; end: SSL_CTX_free(ctx); + set_keylog_file(NULL, NULL); X509_free(s_cert); sk_X509_CRL_pop_free(crls, X509_CRL_free); X509_free(s_dcert); @@ -2062,7 +2125,7 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) SSL_CTX_sess_get_cache_size(ssl_ctx)); } -static int sv_body(int s, int stype, unsigned char *context) +static int sv_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; fd_set readfds; @@ -2076,6 +2139,13 @@ static int sv_body(int s, int stype, unsigned char *context) struct timeval tv; #else struct timeval *timeoutp; +#endif +#ifndef OPENSSL_NO_DTLS +# ifndef OPENSSL_NO_SCTP + int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP); +# else + int isdtls = (stype == SOCK_DGRAM); +# endif #endif buf = app_malloc(bufsize, "server buffer"); @@ -2108,9 +2178,13 @@ static int sv_body(int s, int stype, unsigned char *context) goto err; } #ifndef OPENSSL_NO_DTLS - if (stype == SOCK_DGRAM) { - - sbio = BIO_new_dgram(s, BIO_NOCLOSE); + if (isdtls) { +# ifndef OPENSSL_NO_SCTP + if (prot == IPPROTO_SCTP) + sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + else +# endif + sbio = BIO_new_dgram(s, BIO_NOCLOSE); if (enable_timeouts) { timeout.tv_sec = 0; @@ -2141,12 +2215,22 @@ static int sv_body(int s, int stype, unsigned char *context) /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); - /* turn on cookie exchange */ - SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); +# ifndef OPENSSL_NO_SCTP + if (prot != IPPROTO_SCTP) { + /* Turn on cookie exchange. Not necessary for SCTP */ + SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); + } +# endif } else #endif sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (sbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ERR_print_errors(bio_err); + goto err; + } + if (s_nbio_test) { BIO *test; @@ -2177,6 +2261,45 @@ static int sv_body(int s, int stype, unsigned char *context) SSL_set_tlsext_debug_arg(con, bio_s_out); } + if (early_data) { + int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR; + size_t readbytes; + + while (edret != SSL_READ_EARLY_DATA_FINISH) { + for (;;) { + edret = SSL_read_early_data(con, buf, bufsize, &readbytes); + if (edret != SSL_READ_EARLY_DATA_ERROR) + break; + + switch (SSL_get_error(con, 0)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_READ: + /* Just keep trying - busy waiting */ + continue; + default: + BIO_printf(bio_err, "Error reading early data\n"); + ERR_print_errors(bio_err); + goto err; + } + } + if (readbytes > 0) { + if (write_header) { + BIO_printf(bio_s_out, "Early data received:\n"); + write_header = 0; + } + raw_write_stdout(buf, (unsigned int)readbytes); + (void)BIO_flush(bio_s_out); + } + } + if (write_header) + BIO_printf(bio_s_out, "No early data received\n"); + else + BIO_printf(bio_s_out, "\nEnd of early data\n"); + if (SSL_is_init_finished(con)) + print_connection_info(con); + } + if (fileno_stdin() > s) width = fileno_stdin() + 1; else @@ -2257,8 +2380,9 @@ static int sv_body(int s, int stype, unsigned char *context) } } assert(lf_num == 0); - } else + } else { i = raw_read_stdin(buf, bufsize); + } if (!s_quiet && !s_brief) { if ((i <= 0) || (buf[0] == 'Q')) { @@ -2311,6 +2435,20 @@ static int sv_body(int s, int stype, unsigned char *context) * cert\n"); */ } + if ((buf[0] == 'K' || buf[0] == 'k') + && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_key_update(con, buf[0] == 'K' ? + SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + continue; + /* + * strcpy(buf,"server side RE-NEGOTIATE asking for client + * cert\n"); + */ + } if (buf[0] == 'P') { static const char *str = "Lets print some clear text\n"; BIO_write(SSL_get_wbio(con), str, strlen(str)); @@ -2485,18 +2623,20 @@ static void close_accept_socket(void) } } +static int is_retryable(SSL *con, int i) +{ + int err = SSL_get_error(con, i); + + /* If it's not a fatal error, it must be retryable */ + return (err != SSL_ERROR_SSL) + && (err != SSL_ERROR_SYSCALL) + && (err != SSL_ERROR_ZERO_RETURN); +} + static int init_ssl_connection(SSL *con) { int i; - const char *str; - X509 *peer; long verify_err; - char buf[BUFSIZ]; -#if !defined(OPENSSL_NO_NEXTPROTONEG) - const unsigned char *next_proto_neg; - unsigned next_proto_neg_len; -#endif - unsigned char *exportedkeymat; int retry = 0; #ifndef OPENSSL_NO_DTLS @@ -2535,7 +2675,7 @@ static int init_ssl_connection(SSL *con) i = SSL_accept(con); if (i <= 0) - retry = BIO_sock_should_retry(i); + retry = is_retryable(con, i); #ifdef CERT_CB_TEST_RETRY { while (i <= 0 @@ -2545,7 +2685,7 @@ static int init_ssl_connection(SSL *con) "LOOKUP from certificate callback during accept\n"); i = SSL_accept(con); if (i <= 0) - retry = BIO_sock_should_retry(i); + retry = is_retryable(con, i); } } #endif @@ -2566,7 +2706,7 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out, "LOOKUP not successful\n"); i = SSL_accept(con); if (i <= 0) - retry = BIO_sock_should_retry(i); + retry = is_retryable(con, i); } #endif } while (i < 0 && SSL_waiting_for_async(con)); @@ -2590,6 +2730,22 @@ static int init_ssl_connection(SSL *con) return (0); } + print_connection_info(con); + return 1; +} + +static void print_connection_info(SSL *con) +{ + const char *str; + X509 *peer; + char buf[BUFSIZ]; +#if !defined(OPENSSL_NO_NEXTPROTONEG) + const unsigned char *next_proto_neg; + unsigned next_proto_neg_len; +#endif + unsigned char *exportedkeymat; + int i; + if (s_brief) print_ssl_summary(con); @@ -2599,10 +2755,7 @@ static int init_ssl_connection(SSL *con) if (peer != NULL) { BIO_printf(bio_s_out, "Client certificate\n"); PEM_write_bio_X509(bio_s_out, peer); - X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf); - BIO_printf(bio_s_out, "subject=%s\n", buf); - X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf); - BIO_printf(bio_s_out, "issuer=%s\n", buf); + dump_cert_text(bio_s_out, peer); X509_free(peer); peer = NULL; } @@ -2615,6 +2768,7 @@ static int init_ssl_connection(SSL *con) ssl_print_point_formats(bio_s_out, con); ssl_print_groups(bio_s_out, con, 0); #endif + print_ca_names(bio_s_out, con); BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); #if !defined(OPENSSL_NO_NEXTPROTONEG) @@ -2639,6 +2793,9 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out, "Reused session-id\n"); BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); + if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION)) + BIO_printf(bio_s_out, "Renegotiation is DISABLED\n"); + if (keymatexportlabel != NULL) { BIO_printf(bio_s_out, "Keying material exporter:\n"); BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); @@ -2660,7 +2817,6 @@ static int init_ssl_connection(SSL *con) } (void)BIO_flush(bio_s_out); - return (1); } #ifndef OPENSSL_NO_DH @@ -2678,7 +2834,7 @@ static DH *load_dh_param(const char *dhfile) } #endif -static int www_body(int s, int stype, unsigned char *context) +static int www_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; int ret = 1; @@ -2720,7 +2876,7 @@ static int www_body(int s, int stype, unsigned char *context) SSL_set_tlsext_debug_arg(con, bio_s_out); } - if (context + if (context != NULL && !SSL_set_session_id_context(con, context, strlen((char *)context))) goto err; @@ -2902,6 +3058,7 @@ static int www_body(int s, int stype, unsigned char *context) #ifndef OPENSSL_NO_EC ssl_print_groups(io, con, 0); #endif + print_ca_names(io, con); BIO_printf(io, (SSL_session_reused(con) ? "---\nReused, " : "---\nNew, ")); c = SSL_get_current_cipher(con); @@ -3063,7 +3220,7 @@ static int www_body(int s, int stype, unsigned char *context) return (ret); } -static int rev_body(int s, int stype, unsigned char *context) +static int rev_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; int i; @@ -3088,7 +3245,7 @@ static int rev_body(int s, int stype, unsigned char *context) SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } - if (context + if (context != NULL && !SSL_set_session_id_context(con, context, strlen((char *)context))) { ERR_print_errors(bio_err);