diff options
author | Jung-uk Kim <jkim@FreeBSD.org> | 2015-10-23 19:46:02 +0000 |
---|---|---|
committer | Jung-uk Kim <jkim@FreeBSD.org> | 2015-10-23 19:46:02 +0000 |
commit | e9fcefce9bb70f20c272a996443928c5f6ab8cd8 (patch) | |
tree | ae816a5a768ec78af3610e509ca39507b33aa9f7 /apps/s_server.c | |
parent | c07d7b3a386974c338492659291008bed07948e6 (diff) | |
download | src-e9fcefce9bb70f20c272a996443928c5f6ab8cd8.tar.gz src-e9fcefce9bb70f20c272a996443928c5f6ab8cd8.zip |
Import OpenSSL 1.0.2d.vendor/openssl/1.0.2d
Notes
Notes:
svn path=/vendor-crypto/openssl/dist/; revision=289848
svn path=/vendor-crypto/openssl/1.0.2d/; revision=289849; tag=vendor/openssl/1.0.2d
Diffstat (limited to 'apps/s_server.c')
-rw-r--r-- | apps/s_server.c | 782 |
1 files changed, 630 insertions, 152 deletions
diff --git a/apps/s_server.c b/apps/s_server.c index b58e5e07c41c..acef382c2c4b 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -209,14 +209,17 @@ typedef unsigned int u_int; #ifndef OPENSSL_NO_RSA static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); #endif -static int sv_body(char *hostname, int s, unsigned char *context); -static int www_body(char *hostname, int s, unsigned char *context); +static int sv_body(char *hostname, int s, int stype, unsigned char *context); +static int www_body(char *hostname, int s, int stype, unsigned char *context); +static int rev_body(char *hostname, int s, int stype, unsigned char *context); static void close_accept_socket(void); static void sv_usage(void); static int init_ssl_connection(SSL *s); static void print_stats(BIO *bp, SSL_CTX *ctx); static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len); +static void init_session_cache_ctx(SSL_CTX *sctx); +static void free_sessions(void); #ifndef OPENSSL_NO_DH static DH *load_dh_param(const char *dhfile); static DH *get_dh2048(void); @@ -286,16 +289,16 @@ static int accept_socket = -1; #undef PROG #define PROG s_server_main -extern int verify_depth, verify_return_error; +extern int verify_depth, verify_return_error, verify_quiet; -static char *cipher = NULL; static int s_server_verify = SSL_VERIFY_NONE; static int s_server_session_id_context = 1; /* anything will do */ -static const char *s_cert_file = TEST_CERT, *s_key_file = NULL; +static const char *s_cert_file = TEST_CERT, *s_key_file = + NULL, *s_chain_file = NULL; #ifndef OPENSSL_NO_TLSEXT static const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL; #endif -static char *s_dcert_file = NULL, *s_dkey_file = NULL; +static char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL; #ifdef FIONBIO static int s_nbio = 0; #endif @@ -308,14 +311,18 @@ static SSL_CTX *ctx2 = NULL; static int www = 0; static BIO *bio_s_out = NULL; +static BIO *bio_s_msg = NULL; static int s_debug = 0; #ifndef OPENSSL_NO_TLSEXT static int s_tlsextdebug = 0; static int s_tlsextstatus = 0; static int cert_status_cb(SSL *s, void *arg); #endif +static int no_resume_ephemeral = 0; static int s_msg = 0; static int s_quiet = 0; +static int s_ign_eof = 0; +static int s_brief = 0; static char *keymatexportlabel = NULL; static int keymatexportlen = 20; @@ -332,6 +339,12 @@ static long socket_mtu; static int cert_chain = 0; #endif +#ifndef OPENSSL_NO_TLSEXT +static BIO *serverinfo_in = NULL; +static const char *s_serverinfo_file = NULL; + +#endif + #ifndef OPENSSL_NO_PSK static char *psk_identity = "Client_identity"; char *psk_key = NULL; /* by default PSK is not used */ @@ -447,12 +460,13 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) static void s_server_init(void) { accept_socket = -1; - cipher = NULL; s_server_verify = SSL_VERIFY_NONE; s_dcert_file = NULL; s_dkey_file = NULL; + s_dchain_file = NULL; s_cert_file = TEST_CERT; s_key_file = NULL; + s_chain_file = NULL; # ifndef OPENSSL_NO_TLSEXT s_cert_file2 = TEST_CERT2; s_key_file2 = NULL; @@ -469,6 +483,7 @@ static void s_server_init(void) s_debug = 0; s_msg = 0; s_quiet = 0; + s_brief = 0; hack = 0; # ifndef OPENSSL_NO_ENGINE engine_id = NULL; @@ -482,6 +497,12 @@ static void sv_usage(void) BIO_printf(bio_err, "\n"); BIO_printf(bio_err, " -accept arg - port to accept on (default is %d)\n", PORT); + BIO_printf(bio_err, + " -verify_host host - check peer certificate matches \"host\"\n"); + BIO_printf(bio_err, + " -verify_email email - check peer certificate matches \"email\"\n"); + BIO_printf(bio_err, + " -verify_ip ipaddr - check peer certificate matches \"ipaddr\"\n"); BIO_printf(bio_err, " -context arg - set session ID context\n"); BIO_printf(bio_err, " -verify arg - turn on peer certificate verification\n"); @@ -491,6 +512,16 @@ static void sv_usage(void) " -verify_return_error - return verification errors\n"); BIO_printf(bio_err, " -cert arg - certificate file to use\n"); BIO_printf(bio_err, " (default is %s)\n", TEST_CERT); +#ifndef OPENSSL_NO_TLSEXT + BIO_printf(bio_err, + " -serverinfo arg - PEM serverinfo file for certificate\n"); + BIO_printf(bio_err, + " -auth - send and receive RFC 5878 TLS auth extensions and supplemental data\n"); + BIO_printf(bio_err, + " -auth_require_reneg - Do not send TLS auth extensions until renegotiation\n"); +#endif + BIO_printf(bio_err, + " -no_resumption_on_reneg - set SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION flag\n"); BIO_printf(bio_err, " -crl_check - check the peer certificate has not been revoked by its CA.\n" " The CRL(s) are appended to the certificate file\n"); @@ -569,6 +600,7 @@ static void sv_usage(void) BIO_printf(bio_err, " -tls1_1 - Just talk TLSv1.1\n"); BIO_printf(bio_err, " -tls1 - Just talk TLSv1\n"); BIO_printf(bio_err, " -dtls1 - Just talk DTLSv1\n"); + BIO_printf(bio_err, " -dtls1_2 - Just talk DTLSv1.2\n"); BIO_printf(bio_err, " -timeout - Enable timeouts\n"); BIO_printf(bio_err, " -mtu - Set link layer MTU\n"); BIO_printf(bio_err, " -chain - Read a certificate chain\n"); @@ -628,6 +660,8 @@ static void sv_usage(void) BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); # endif + BIO_printf(bio_err, + " -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n"); #endif BIO_printf(bio_err, " -keymatexport label - Export keying material using label\n"); @@ -988,12 +1022,53 @@ static int next_proto_cb(SSL *s, const unsigned char **data, } # endif /* ndef OPENSSL_NO_NEXTPROTONEG */ -#endif +/* This the context that we pass to alpn_cb */ +typedef struct tlsextalpnctx_st { + unsigned char *data; + unsigned short len; +} tlsextalpnctx; + +static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + tlsextalpnctx *alpn_ctx = arg; + + if (!s_quiet) { + /* We can assume that |in| is syntactically valid. */ + unsigned i; + BIO_printf(bio_s_out, "ALPN protocols advertised by the client: "); + for (i = 0; i < inlen;) { + if (i) + BIO_write(bio_s_out, ", ", 2); + BIO_write(bio_s_out, &in[i + 1], in[i]); + i += in[i] + 1; + } + BIO_write(bio_s_out, "\n", 1); + } + + if (SSL_select_next_proto + ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, + inlen) != OPENSSL_NPN_NEGOTIATED) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (!s_quiet) { + BIO_printf(bio_s_out, "ALPN protocols selected: "); + BIO_write(bio_s_out, *out, *outlen); + BIO_write(bio_s_out, "\n", 1); + } + + return SSL_TLSEXT_ERR_OK; +} +#endif /* ndef OPENSSL_NO_TLSEXT */ int MAIN(int, char **); #ifndef OPENSSL_NO_JPAKE static char *jpake_secret = NULL; +# define no_jpake !jpake_secret +#else +# define no_jpake 1 #endif #ifndef OPENSSL_NO_SRP static srpsrvparm srp_callback_parm; @@ -1008,18 +1083,14 @@ int MAIN(int argc, char *argv[]) int badarg = 0; short port = PORT; char *CApath = NULL, *CAfile = NULL; + char *chCApath = NULL, *chCAfile = NULL; + char *vfyCApath = NULL, *vfyCAfile = NULL; unsigned char *context = NULL; char *dhfile = NULL; -#ifndef OPENSSL_NO_ECDH - char *named_curve = NULL; -#endif - int badop = 0, bugs = 0; + int badop = 0; int ret = 1; - int off = 0; - int no_tmp_rsa = 0, no_dhe = 0, nocert = 0; -#ifndef OPENSSL_NO_ECDH - int no_ecdhe = 0; -#endif + int build_chain = 0; + int no_tmp_rsa = 0, no_dhe = 0, no_ecdhe = 0, nocert = 0; int state = 0; const SSL_METHOD *meth = NULL; int socket_type = SOCK_STREAM; @@ -1030,16 +1101,20 @@ int MAIN(int argc, char *argv[]) char *dpassarg = NULL, *dpass = NULL; int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; X509 *s_cert = NULL, *s_dcert = NULL; + STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; EVP_PKEY *s_key = NULL, *s_dkey = NULL; - int no_cache = 0; + int no_cache = 0, ext_cache = 0; + int rev = 0, naccept = -1; #ifndef OPENSSL_NO_TLSEXT EVP_PKEY *s_key2 = NULL; X509 *s_cert2 = NULL; tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING }; # ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; - tlsextnextprotoctx next_proto; + tlsextnextprotoctx next_proto = { NULL, 0 }; # endif + const char *alpn_in = NULL; + tlsextalpnctx alpn_ctx = { NULL, 0 }; #endif #ifndef OPENSSL_NO_PSK /* by default do not send a PSK identity hint */ @@ -1049,6 +1124,15 @@ int MAIN(int argc, char *argv[]) char *srpuserseed = NULL; char *srp_verifier_file = NULL; #endif + SSL_EXCERT *exc = NULL; + SSL_CONF_CTX *cctx = NULL; + STACK_OF(OPENSSL_STRING) *ssl_args = NULL; + + char *crl_file = NULL; + int crl_format = FORMAT_PEM; + int crl_download = 0; + STACK_OF(X509_CRL) *crls = NULL; + meth = SSLv23_server_method(); local_argc = argc; @@ -1065,6 +1149,12 @@ int MAIN(int argc, char *argv[]) if (!load_config(bio_err, NULL)) goto end; + cctx = SSL_CONF_CTX_new(); + if (!cctx) + goto end; + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CMDLINE); + verify_depth = 0; #ifdef FIONBIO s_nbio = 0; @@ -1080,12 +1170,21 @@ int MAIN(int argc, char *argv[]) goto bad; if (!extract_port(*(++argv), &port)) goto bad; + } else if (strcmp(*argv, "-naccept") == 0) { + if (--argc < 1) + goto bad; + naccept = atol(*(++argv)); + if (naccept <= 0) { + BIO_printf(bio_err, "bad accept value %s\n", *argv); + goto bad; + } } else if (strcmp(*argv, "-verify") == 0) { s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; if (--argc < 1) goto bad; verify_depth = atoi(*(++argv)); - BIO_printf(bio_err, "verify depth is %d\n", verify_depth); + if (!s_quiet) + BIO_printf(bio_err, "verify depth is %d\n", verify_depth); } else if (strcmp(*argv, "-Verify") == 0) { s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | @@ -1093,9 +1192,10 @@ int MAIN(int argc, char *argv[]) if (--argc < 1) goto bad; verify_depth = atoi(*(++argv)); - BIO_printf(bio_err, - "verify depth is %d, must return a certificate\n", - verify_depth); + if (!s_quiet) + BIO_printf(bio_err, + "verify depth is %d, must return a certificate\n", + verify_depth); } else if (strcmp(*argv, "-context") == 0) { if (--argc < 1) goto bad; @@ -1104,7 +1204,20 @@ int MAIN(int argc, char *argv[]) if (--argc < 1) goto bad; s_cert_file = *(++argv); - } else if (strcmp(*argv, "-certform") == 0) { + } else if (strcmp(*argv, "-CRL") == 0) { + if (--argc < 1) + goto bad; + crl_file = *(++argv); + } else if (strcmp(*argv, "-crl_download") == 0) + crl_download = 1; +#ifndef OPENSSL_NO_TLSEXT + else if (strcmp(*argv, "-serverinfo") == 0) { + if (--argc < 1) + goto bad; + s_serverinfo_file = *(++argv); + } +#endif + else if (strcmp(*argv, "-certform") == 0) { if (--argc < 1) goto bad; s_cert_format = str2fmt(*(++argv)); @@ -1120,19 +1233,15 @@ int MAIN(int argc, char *argv[]) if (--argc < 1) goto bad; passarg = *(++argv); - } else if (strcmp(*argv, "-dhparam") == 0) { + } else if (strcmp(*argv, "-cert_chain") == 0) { if (--argc < 1) goto bad; - dhfile = *(++argv); - } -#ifndef OPENSSL_NO_ECDH - else if (strcmp(*argv, "-named_curve") == 0) { + s_chain_file = *(++argv); + } else if (strcmp(*argv, "-dhparam") == 0) { if (--argc < 1) goto bad; - named_curve = *(++argv); - } -#endif - else if (strcmp(*argv, "-dcertform") == 0) { + dhfile = *(++argv); + } else if (strcmp(*argv, "-dcertform") == 0) { if (--argc < 1) goto bad; s_dcert_format = str2fmt(*(++argv)); @@ -1152,32 +1261,62 @@ int MAIN(int argc, char *argv[]) if (--argc < 1) goto bad; s_dkey_file = *(++argv); + } else if (strcmp(*argv, "-dcert_chain") == 0) { + if (--argc < 1) + goto bad; + s_dchain_file = *(++argv); } else if (strcmp(*argv, "-nocert") == 0) { nocert = 1; } else if (strcmp(*argv, "-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); + } else if (strcmp(*argv, "-chainCApath") == 0) { + if (--argc < 1) + goto bad; + chCApath = *(++argv); + } else if (strcmp(*argv, "-verifyCApath") == 0) { + if (--argc < 1) + goto bad; + vfyCApath = *(++argv); } else if (strcmp(*argv, "-no_cache") == 0) no_cache = 1; - else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { + else if (strcmp(*argv, "-ext_cache") == 0) + ext_cache = 1; + else if (strcmp(*argv, "-CRLform") == 0) { + if (--argc < 1) + goto bad; + crl_format = str2fmt(*(++argv)); + } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { + if (badarg) + goto bad; + continue; + } else if (args_excert(&argv, &argc, &badarg, bio_err, &exc)) { + if (badarg) + goto bad; + continue; + } else if (args_ssl(&argv, &argc, cctx, &badarg, bio_err, &ssl_args)) { if (badarg) goto bad; continue; } else if (strcmp(*argv, "-verify_return_error") == 0) verify_return_error = 1; - else if (strcmp(*argv, "-serverpref") == 0) { - off |= SSL_OP_CIPHER_SERVER_PREFERENCE; - } else if (strcmp(*argv, "-legacy_renegotiation") == 0) - off |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; - else if (strcmp(*argv, "-cipher") == 0) { + else if (strcmp(*argv, "-verify_quiet") == 0) + verify_quiet = 1; + else if (strcmp(*argv, "-build_chain") == 0) + build_chain = 1; + else if (strcmp(*argv, "-CAfile") == 0) { if (--argc < 1) goto bad; - cipher = *(++argv); - } else if (strcmp(*argv, "-CAfile") == 0) { + CAfile = *(++argv); + } else if (strcmp(*argv, "-chainCAfile") == 0) { if (--argc < 1) goto bad; - CAfile = *(++argv); + chCAfile = *(++argv); + } else if (strcmp(*argv, "-verifyCAfile") == 0) { + if (--argc < 1) + goto bad; + vfyCAfile = *(++argv); } #ifdef FIONBIO else if (strcmp(*argv, "-nbio") == 0) { @@ -1189,7 +1328,11 @@ int MAIN(int argc, char *argv[]) s_nbio = 1; #endif s_nbio_test = 1; - } else if (strcmp(*argv, "-debug") == 0) { + } else if (strcmp(*argv, "-ign_eof") == 0) + s_ign_eof = 1; + else if (strcmp(*argv, "-no_ign_eof") == 0) + s_ign_eof = 0; + else if (strcmp(*argv, "-debug") == 0) { s_debug = 1; } #ifndef OPENSSL_NO_TLSEXT @@ -1220,7 +1363,17 @@ int MAIN(int argc, char *argv[]) #endif else if (strcmp(*argv, "-msg") == 0) { s_msg = 1; - } else if (strcmp(*argv, "-hack") == 0) { + } else if (strcmp(*argv, "-msgfile") == 0) { + if (--argc < 1) + goto bad; + bio_s_msg = BIO_new_file(*(++argv), "w"); + } +#ifndef OPENSSL_NO_SSL_TRACE + else if (strcmp(*argv, "-trace") == 0) { + s_msg = 2; + } +#endif + else if (strcmp(*argv, "-hack") == 0) { hack = 1; } else if (strcmp(*argv, "-state") == 0) { state = 1; @@ -1228,18 +1381,19 @@ int MAIN(int argc, char *argv[]) s_crlf = 1; } else if (strcmp(*argv, "-quiet") == 0) { s_quiet = 1; - } else if (strcmp(*argv, "-bugs") == 0) { - bugs = 1; + } else if (strcmp(*argv, "-brief") == 0) { + s_quiet = 1; + s_brief = 1; + verify_quiet = 1; } else if (strcmp(*argv, "-no_tmp_rsa") == 0) { no_tmp_rsa = 1; } else if (strcmp(*argv, "-no_dhe") == 0) { no_dhe = 1; - } -#ifndef OPENSSL_NO_ECDH - else if (strcmp(*argv, "-no_ecdhe") == 0) { + } else if (strcmp(*argv, "-no_ecdhe") == 0) { no_ecdhe = 1; + } else if (strcmp(*argv, "-no_resume_ephemeral") == 0) { + no_resume_ephemeral = 1; } -#endif #ifndef OPENSSL_NO_PSK else if (strcmp(*argv, "-psk_hint") == 0) { if (--argc < 1) @@ -1272,32 +1426,18 @@ int MAIN(int argc, char *argv[]) meth = TLSv1_server_method(); } #endif - else if (strcmp(*argv, "-www") == 0) { + else if (strcmp(*argv, "-rev") == 0) { + rev = 1; + } else if (strcmp(*argv, "-www") == 0) { www = 1; } else if (strcmp(*argv, "-WWW") == 0) { www = 2; } else if (strcmp(*argv, "-HTTP") == 0) { www = 3; - } else if (strcmp(*argv, "-no_ssl2") == 0) { - off |= SSL_OP_NO_SSLv2; - } else if (strcmp(*argv, "-no_ssl3") == 0) { - off |= SSL_OP_NO_SSLv3; - } else if (strcmp(*argv, "-no_tls1") == 0) { - off |= SSL_OP_NO_TLSv1; - } else if (strcmp(*argv, "-no_tls1_1") == 0) { - off |= SSL_OP_NO_TLSv1_1; - } else if (strcmp(*argv, "-no_tls1_2") == 0) { - off |= SSL_OP_NO_TLSv1_2; - } else if (strcmp(*argv, "-no_comp") == 0) { - off |= SSL_OP_NO_COMPRESSION; } -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-no_ticket") == 0) { - off |= SSL_OP_NO_TICKET; - } -#endif #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv, "-ssl2") == 0) { + no_ecdhe = 1; meth = SSLv2_server_method(); } #endif @@ -1316,9 +1456,15 @@ int MAIN(int argc, char *argv[]) } #endif #ifndef OPENSSL_NO_DTLS1 - else if (strcmp(*argv, "-dtls1") == 0) { + else if (strcmp(*argv, "-dtls") == 0) { + meth = DTLS_server_method(); + socket_type = SOCK_DGRAM; + } else if (strcmp(*argv, "-dtls1") == 0) { meth = DTLSv1_server_method(); socket_type = SOCK_DGRAM; + } else if (strcmp(*argv, "-dtls1_2") == 0) { + meth = DTLSv1_2_server_method(); + socket_type = SOCK_DGRAM; } else if (strcmp(*argv, "-timeout") == 0) enable_timeouts = 1; else if (strcmp(*argv, "-mtu") == 0) { @@ -1368,6 +1514,11 @@ int MAIN(int argc, char *argv[]) next_proto_neg_in = *(++argv); } # endif + else if (strcmp(*argv, "-alpn") == 0) { + if (--argc < 1) + goto bad; + alpn_in = *(++argv); + } #endif #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) else if (strcmp(*argv, "-jpake") == 0) { @@ -1420,11 +1571,6 @@ int MAIN(int argc, char *argv[]) goto end; } psk_identity = "JPAKE"; - if (cipher) { - BIO_printf(bio_err, "JPAKE sets cipher to PSK\n"); - goto end; - } - cipher = "PSK"; } #endif @@ -1447,6 +1593,9 @@ int MAIN(int argc, char *argv[]) s_key_file2 = s_cert_file2; #endif + if (!load_excert(&exc, bio_err)) + goto end; + if (nocert == 0) { s_key = load_key(bio_err, s_key_file, s_key_format, 0, pass, e, "server certificate private key file"); @@ -1462,6 +1611,12 @@ int MAIN(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } + if (s_chain_file) { + s_chain = load_certs(bio_err, s_chain_file, FORMAT_PEM, + NULL, e, "server certificate chain"); + if (!s_chain) + goto end; + } #ifndef OPENSSL_NO_TLSEXT if (tlsextcbp.servername) { s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e, @@ -1479,9 +1634,10 @@ int MAIN(int argc, char *argv[]) goto end; } } -#endif +#endif /* OPENSSL_NO_TLSEXT */ } -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_TLSEXT) +# if !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto_neg_in) { unsigned short len; next_proto.data = next_protos_parse(&len, next_proto_neg_in); @@ -1491,8 +1647,34 @@ int MAIN(int argc, char *argv[]) } else { next_proto.data = NULL; } +# endif + alpn_ctx.data = NULL; + if (alpn_in) { + unsigned short len; + alpn_ctx.data = next_protos_parse(&len, alpn_in); + if (alpn_ctx.data == NULL) + goto end; + alpn_ctx.len = len; + } #endif + if (crl_file) { + X509_CRL *crl; + crl = load_crl(crl_file, crl_format); + if (!crl) { + 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)) { + BIO_puts(bio_err, "Error adding CRL\n"); + ERR_print_errors(bio_err); + X509_CRL_free(crl); + goto end; + } + } + if (s_dcert_file) { if (s_dkey_file == NULL) @@ -1512,6 +1694,12 @@ int MAIN(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } + if (s_dchain_file) { + s_dchain = load_certs(bio_err, s_dchain_file, FORMAT_PEM, + NULL, e, "second server certificate chain"); + if (!s_dchain) + goto end; + } } @@ -1525,8 +1713,10 @@ int MAIN(int argc, char *argv[]) app_RAND_load_files(inrand)); if (bio_s_out == NULL) { - if (s_quiet && !s_debug && !s_msg) { + if (s_quiet && !s_debug) { bio_s_out = BIO_new(BIO_s_null()); + if (s_msg && !bio_s_msg) + bio_s_msg = BIO_new_fp(stdout, BIO_NOCLOSE); } else { if (bio_s_out == NULL) bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); @@ -1566,16 +1756,17 @@ int 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 (bugs) - SSL_CTX_set_options(ctx, SSL_OP_ALL); if (hack) SSL_CTX_set_options(ctx, SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); - SSL_CTX_set_options(ctx, off); + if (exc) + ssl_ctx_set_excert(ctx, exc); if (state) SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); if (no_cache) SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + else if (ext_cache) + init_session_cache_ctx(ctx); else SSL_CTX_sess_set_cache_size(ctx, 128); @@ -1606,6 +1797,17 @@ int MAIN(int argc, char *argv[]) if (vpm) SSL_CTX_set1_param(ctx, vpm); + ssl_ctx_add_crls(ctx, crls, 0); + + if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, no_ecdhe, no_jpake)) + goto end; + + if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, + crls, crl_download)) { + BIO_printf(bio_err, "Error loading store locations\n"); + ERR_print_errors(bio_err); + goto end; + } #ifndef OPENSSL_NO_TLSEXT if (s_cert2) { ctx2 = SSL_CTX_new(meth); @@ -1633,17 +1835,18 @@ int 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 (bugs) - SSL_CTX_set_options(ctx2, SSL_OP_ALL); if (hack) SSL_CTX_set_options(ctx2, SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); - SSL_CTX_set_options(ctx2, off); + if (exc) + ssl_ctx_set_excert(ctx2, exc); if (state) SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback); if (no_cache) SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF); + else if (ext_cache) + init_session_cache_ctx(ctx2); else SSL_CTX_sess_set_cache_size(ctx2, 128); @@ -1653,12 +1856,20 @@ int MAIN(int argc, char *argv[]) } if (vpm) SSL_CTX_set1_param(ctx2, vpm); + + ssl_ctx_add_crls(ctx2, crls, 0); + + if (!args_ssl_call(ctx2, bio_err, cctx, ssl_args, no_ecdhe, no_jpake)) + goto end; + } # ifndef OPENSSL_NO_NEXTPROTONEG if (next_proto.data) SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto); # endif + if (alpn_ctx.data) + SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); #endif #ifndef OPENSSL_NO_DH @@ -1702,54 +1913,21 @@ int MAIN(int argc, char *argv[]) } #endif -#ifndef OPENSSL_NO_ECDH - if (!no_ecdhe) { - EC_KEY *ecdh = NULL; - - if (named_curve) { - int nid = OBJ_sn2nid(named_curve); - - if (nid == 0) { - BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); - goto end; - } - ecdh = EC_KEY_new_by_curve_name(nid); - if (ecdh == NULL) { - BIO_printf(bio_err, "unable to create curve (%s)\n", - named_curve); - goto end; - } - } - - if (ecdh != NULL) { - BIO_printf(bio_s_out, "Setting temp ECDH parameters\n"); - } else { - BIO_printf(bio_s_out, "Using default temp ECDH parameters\n"); - ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - if (ecdh == NULL) { - BIO_printf(bio_err, "unable to create curve (nistp256)\n"); - goto end; - } - } - (void)BIO_flush(bio_s_out); - - SSL_CTX_set_tmp_ecdh(ctx, ecdh); -# ifndef OPENSSL_NO_TLSEXT - if (ctx2) - SSL_CTX_set_tmp_ecdh(ctx2, ecdh); -# endif - EC_KEY_free(ecdh); + if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) + goto end; +#ifndef OPENSSL_NO_TLSEXT + if (s_serverinfo_file != NULL + && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) { + ERR_print_errors(bio_err); + goto end; } #endif - - if (!set_cert_key_stuff(ctx, s_cert, s_key)) - goto end; #ifndef OPENSSL_NO_TLSEXT - if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2)) + if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) goto end; #endif if (s_dcert != NULL) { - if (!set_cert_key_stuff(ctx, s_dcert, s_dkey)) + if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain)) goto end; } #ifndef OPENSSL_NO_RSA @@ -1808,20 +1986,6 @@ int MAIN(int argc, char *argv[]) } #endif - if (cipher != NULL) { - if (!SSL_CTX_set_cipher_list(ctx, cipher)) { - BIO_printf(bio_err, "error setting cipher list\n"); - ERR_print_errors(bio_err); - goto end; - } -#ifndef OPENSSL_NO_TLSEXT - if (ctx2 && !SSL_CTX_set_cipher_list(ctx2, cipher)) { - BIO_printf(bio_err, "error setting cipher list\n"); - ERR_print_errors(bio_err); - goto end; - } -#endif - } SSL_CTX_set_verify(ctx, s_server_verify, verify_callback); SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, sizeof s_server_session_id_context); @@ -1873,10 +2037,15 @@ int MAIN(int argc, char *argv[]) BIO_printf(bio_s_out, "ACCEPT\n"); (void)BIO_flush(bio_s_out); - if (www) - do_server(port, socket_type, &accept_socket, www_body, context); + if (rev) + do_server(port, socket_type, &accept_socket, rev_body, context, + naccept); + else if (www) + do_server(port, socket_type, &accept_socket, www_body, context, + naccept); else - do_server(port, socket_type, &accept_socket, sv_body, context); + do_server(port, socket_type, &accept_socket, sv_body, context, + naccept); print_stats(bio_s_out, ctx); ret = 0; end: @@ -1884,18 +2053,25 @@ int MAIN(int argc, char *argv[]) SSL_CTX_free(ctx); if (s_cert) X509_free(s_cert); + if (crls) + sk_X509_CRL_pop_free(crls, X509_CRL_free); if (s_dcert) X509_free(s_dcert); if (s_key) EVP_PKEY_free(s_key); if (s_dkey) EVP_PKEY_free(s_dkey); + if (s_chain) + sk_X509_pop_free(s_chain, X509_free); + if (s_dchain) + sk_X509_pop_free(s_dchain, X509_free); if (pass) OPENSSL_free(pass); if (dpass) OPENSSL_free(dpass); if (vpm) X509_VERIFY_PARAM_free(vpm); + free_sessions(); #ifndef OPENSSL_NO_TLSEXT if (tlscstatp.host) OPENSSL_free(tlscstatp.host); @@ -1909,11 +2085,32 @@ int MAIN(int argc, char *argv[]) X509_free(s_cert2); if (s_key2) EVP_PKEY_free(s_key2); + if (serverinfo_in != NULL) + BIO_free(serverinfo_in); +# ifndef OPENSSL_NO_NEXTPROTONEG + if (next_proto.data) + OPENSSL_free(next_proto.data); +# endif + if (alpn_ctx.data) + OPENSSL_free(alpn_ctx.data); +#endif + ssl_excert_free(exc); + if (ssl_args) + sk_OPENSSL_STRING_free(ssl_args); + if (cctx) + SSL_CONF_CTX_free(cctx); +#ifndef OPENSSL_NO_JPAKE + if (jpake_secret && psk_key) + OPENSSL_free(psk_key); #endif if (bio_s_out != NULL) { BIO_free(bio_s_out); bio_s_out = NULL; } + if (bio_s_msg != NULL) { + BIO_free(bio_s_msg); + bio_s_msg = NULL; + } apps_shutdown(); OPENSSL_EXIT(ret); } @@ -1946,7 +2143,7 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) SSL_CTX_sess_get_cache_size(ssl_ctx)); } -static int sv_body(char *hostname, int s, unsigned char *context) +static int sv_body(char *hostname, int s, int stype, unsigned char *context) { char *buf = NULL; fd_set readfds; @@ -2010,7 +2207,7 @@ static int sv_body(char *hostname, int s, unsigned char *context) # endif #endif - if (SSL_version(con) == DTLS1_VERSION) { + if (stype == SOCK_DGRAM) { sbio = BIO_new_dgram(s, BIO_NOCLOSE); @@ -2069,8 +2266,13 @@ static int sv_body(char *hostname, int s, unsigned char *context) BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } if (s_msg) { - SSL_set_msg_callback(con, msg_cb); - SSL_set_msg_callback_arg(con, bio_s_out); +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); } #ifndef OPENSSL_NO_TLSEXT if (s_tlsextdebug) { @@ -2168,7 +2370,7 @@ static int sv_body(char *hostname, int s, unsigned char *context) assert(lf_num == 0); } else i = raw_read_stdin(buf, bufsize); - if (!s_quiet) { + if (!s_quiet && !s_brief) { if ((i <= 0) || (buf[0] == 'Q')) { BIO_printf(bio_s_out, "DONE\n"); SHUTDOWN(s); @@ -2383,6 +2585,16 @@ static int init_ssl_connection(SSL *con) unsigned char *exportedkeymat; i = SSL_accept(con); +#ifdef CERT_CB_TEST_RETRY + { + while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP + && SSL_state(con) == SSL3_ST_SR_CLNT_HELLO_C) { + fprintf(stderr, + "LOOKUP from certificate callback during accept\n"); + i = SSL_accept(con); + } + } +#endif #ifndef OPENSSL_NO_SRP while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP during accept %s\n", @@ -2398,6 +2610,7 @@ static int init_ssl_connection(SSL *con) i = SSL_accept(con); } #endif + if (i <= 0) { if (BIO_sock_should_retry(i)) { BIO_printf(bio_s_out, "DELAY\n"); @@ -2409,11 +2622,15 @@ static int init_ssl_connection(SSL *con) if (verify_error != X509_V_OK) { BIO_printf(bio_err, "verify error:%s\n", X509_verify_cert_error_string(verify_error)); - } else - ERR_print_errors(bio_err); + } + /* Always print any error messages */ + ERR_print_errors(bio_err); return (0); } + if (s_brief) + print_ssl_summary(bio_err, con); + PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); peer = SSL_get_peer_certificate(con); @@ -2430,6 +2647,11 @@ static int init_ssl_connection(SSL *con) if (SSL_get_shared_ciphers(con, buf, sizeof buf) != NULL) BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); + ssl_print_sigalgs(bio_s_out, con); +#ifndef OPENSSL_NO_EC + ssl_print_point_formats(bio_s_out, con); + ssl_print_curves(bio_s_out, con, 0); +#endif BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) @@ -2529,7 +2751,7 @@ static int load_CA(SSL_CTX *ctx, char *file) } #endif -static int www_body(char *hostname, int s, unsigned char *context) +static int www_body(char *hostname, int s, int stype, unsigned char *context) { char *buf = NULL; int ret = 1; @@ -2604,8 +2826,13 @@ static int www_body(char *hostname, int s, unsigned char *context) BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } if (s_msg) { - SSL_set_msg_callback(con, msg_cb); - SSL_set_msg_callback_arg(con, bio_s_out); +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); } for (;;) { @@ -2724,6 +2951,10 @@ static int www_body(char *hostname, int s, unsigned char *context) } BIO_puts(io, "\n"); } + ssl_print_sigalgs(io, con); +#ifndef OPENSSL_NO_EC + ssl_print_curves(io, con, 0); +#endif BIO_printf(io, (SSL_cache_hit(con) ? "---\nReused, " : "---\nNew, ")); c = SSL_get_current_cipher(con); @@ -2906,6 +3137,140 @@ static int www_body(char *hostname, int s, unsigned char *context) return (ret); } +static int rev_body(char *hostname, int s, int stype, unsigned char *context) +{ + char *buf = NULL; + int i; + int ret = 1; + SSL *con; + BIO *io, *ssl_bio, *sbio; +#ifndef OPENSSL_NO_KRB5 + KSSL_CTX *kctx; +#endif + + buf = OPENSSL_malloc(bufsize); + if (buf == NULL) + return (0); + io = BIO_new(BIO_f_buffer()); + ssl_bio = BIO_new(BIO_f_ssl()); + if ((io == NULL) || (ssl_bio == NULL)) + goto err; + + /* lets make the output buffer a reasonable size */ + if (!BIO_set_write_buffer_size(io, bufsize)) + goto err; + + if ((con = SSL_new(ctx)) == NULL) + goto err; +#ifndef OPENSSL_NO_TLSEXT + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } +#endif +#ifndef OPENSSL_NO_KRB5 + if ((kctx = kssl_ctx_new()) != NULL) { + kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC); + kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB); + } +#endif /* OPENSSL_NO_KRB5 */ + if (context) + SSL_set_session_id_context(con, context, strlen((char *)context)); + + sbio = BIO_new_socket(s, BIO_NOCLOSE); + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + + BIO_set_ssl(ssl_bio, con, BIO_CLOSE); + BIO_push(io, ssl_bio); +#ifdef CHARSET_EBCDIC + io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); +#endif + + if (s_debug) { + SSL_set_debug(con, 1); + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); + } + if (s_msg) { +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); + } + + for (;;) { + i = BIO_do_handshake(io); + if (i > 0) + break; + if (!BIO_should_retry(io)) { + BIO_puts(bio_err, "CONNECTION FAILURE\n"); + ERR_print_errors(bio_err); + goto end; + } + } + BIO_printf(bio_err, "CONNECTION ESTABLISHED\n"); + print_ssl_summary(bio_err, con); + + for (;;) { + i = BIO_gets(io, buf, bufsize - 1); + if (i < 0) { /* error */ + if (!BIO_should_retry(io)) { + if (!s_quiet) + ERR_print_errors(bio_err); + goto err; + } else { + BIO_printf(bio_s_out, "read R BLOCK\n"); +#if defined(OPENSSL_SYS_NETWARE) + delay(1000); +#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__) + sleep(1); +#endif + continue; + } + } else if (i == 0) { /* end of input */ + ret = 1; + BIO_printf(bio_err, "CONNECTION CLOSED\n"); + goto end; + } else { + char *p = buf + i - 1; + while (i && (*p == '\n' || *p == '\r')) { + p--; + i--; + } + if (!s_ign_eof && i == 5 && !strncmp(buf, "CLOSE", 5)) { + ret = 1; + BIO_printf(bio_err, "CONNECTION CLOSED\n"); + goto end; + } + BUF_reverse((unsigned char *)buf, NULL, i); + buf[i] = '\n'; + BIO_write(io, buf, i + 1); + for (;;) { + i = BIO_flush(io); + if (i > 0) + break; + if (!BIO_should_retry(io)) + goto end; + } + } + } + end: + /* make sure we re-use sessions */ + SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + + err: + + if (buf != NULL) + OPENSSL_free(buf); + if (io != NULL) + BIO_free_all(io); + return (ret); +} + #ifndef OPENSSL_NO_RSA static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) { @@ -2961,3 +3326,116 @@ static int generate_session_id(const SSL *ssl, unsigned char *id, return 0; return 1; } + +/* + * By default s_server uses an in-memory cache which caches SSL_SESSION + * structures without any serialisation. This hides some bugs which only + * become apparent in deployed servers. By implementing a basic external + * session cache some issues can be debugged using s_server. + */ + +typedef struct simple_ssl_session_st { + unsigned char *id; + unsigned int idlen; + unsigned char *der; + int derlen; + struct simple_ssl_session_st *next; +} simple_ssl_session; + +static simple_ssl_session *first = NULL; + +static int add_session(SSL *ssl, SSL_SESSION *session) +{ + simple_ssl_session *sess; + unsigned char *p; + + sess = OPENSSL_malloc(sizeof(simple_ssl_session)); + if (!sess) { + BIO_printf(bio_err, "Out of memory adding session to external cache\n"); + return 0; + } + + SSL_SESSION_get_id(session, &sess->idlen); + sess->derlen = i2d_SSL_SESSION(session, NULL); + + sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); + + sess->der = OPENSSL_malloc(sess->derlen); + if (!sess->id || !sess->der) { + BIO_printf(bio_err, "Out of memory adding session to external cache\n"); + + if (sess->id) + OPENSSL_free(sess->id); + if (sess->der) + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return 0; + } + p = sess->der; + i2d_SSL_SESSION(session, &p); + + sess->next = first; + first = sess; + BIO_printf(bio_err, "New session added to external cache\n"); + return 0; +} + +static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen, + int *do_copy) +{ + simple_ssl_session *sess; + *do_copy = 0; + for (sess = first; sess; sess = sess->next) { + if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) { + const unsigned char *p = sess->der; + BIO_printf(bio_err, "Lookup session: cache hit\n"); + return d2i_SSL_SESSION(NULL, &p, sess->derlen); + } + } + BIO_printf(bio_err, "Lookup session: cache miss\n"); + return NULL; +} + +static void del_session(SSL_CTX *sctx, SSL_SESSION *session) +{ + simple_ssl_session *sess, *prev = NULL; + const unsigned char *id; + unsigned int idlen; + id = SSL_SESSION_get_id(session, &idlen); + for (sess = first; sess; sess = sess->next) { + if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) { + if (prev) + prev->next = sess->next; + else + first = sess->next; + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return; + } + prev = sess; + } +} + +static void init_session_cache_ctx(SSL_CTX *sctx) +{ + SSL_CTX_set_session_cache_mode(sctx, + SSL_SESS_CACHE_NO_INTERNAL | + SSL_SESS_CACHE_SERVER); + SSL_CTX_sess_set_new_cb(sctx, add_session); + SSL_CTX_sess_set_get_cb(sctx, get_session); + SSL_CTX_sess_set_remove_cb(sctx, del_session); +} + +static void free_sessions(void) +{ + simple_ssl_session *sess, *tsess; + for (sess = first; sess;) { + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + tsess = sess; + sess = sess->next; + OPENSSL_free(tsess); + } + first = NULL; +} |