X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_server.c;h=1a54f082f48e8cdc148c8f58f1359ec8d70b88cd;hp=698dd1c73bc48297da974abfab8cd490a798d2ba;hb=ab69ac00f3c7;hpb=8caab744f5698ed2b55eca20f032540f713327fd diff --git a/apps/s_server.c b/apps/s_server.c index 698dd1c73b..1a54f082f4 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -191,9 +191,12 @@ typedef unsigned int u_int; #endif static int not_resumable_sess_cb(SSL *s, int is_forward_secure); -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 int sv_body(const char *hostname, int s, int stype, + unsigned char *context); +static int www_body(const char *hostname, int s, int stype, + unsigned char *context); +static int rev_body(const char *hostname, int s, int stype, + 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); @@ -257,9 +260,9 @@ static char *engine_id = NULL; #endif static const char *session_id_prefix = NULL; +#ifndef OPENSSL_NO_DTLS static int enable_timeouts = 0; static long socket_mtu; -#ifndef OPENSSL_NO_DTLS static int cert_chain = 0; #endif static int dtlslisten = 0; @@ -791,8 +794,8 @@ static char *srtp_profiles = NULL; #endif typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_ENGINE, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, + 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_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT, @@ -807,7 +810,7 @@ typedef enum OPTION_choice { OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, OPT_NO_RESUME_EPHEMERAL, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, - OPT_SSL3, + OPT_SSL_CONFIG, OPT_SSL3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_CHAIN, OPT_LISTEN, OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, @@ -821,9 +824,13 @@ typedef enum OPTION_choice { OPTIONS s_server_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"port", OPT_PORT, 'p'}, - {"accept", OPT_PORT, 'p', - "TCP/IP port to accept on (default is " PORT_STR ")"}, + {"accept", OPT_ACCEPT, 's', + "TCP/IP port or service to accept on (default is " PORT ")"}, +#ifdef AF_UNIX {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"}, +#endif + {"4", OPT_4, '-', "Use IPv4 only"}, + {"6", OPT_6, '-', "Use IPv6 only"}, {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, {"context", OPT_CONTEXT, 's', "Set session ID context"}, {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"}, @@ -863,9 +870,6 @@ OPTIONS s_server_options[] = { "Do not load certificates from the default certificates directory"}, {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, {"quiet", OPT_QUIET, '-', "No server output"}, - {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"}, - {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"}, - {"tls1", OPT_TLS1, '-', "Just talk TLSv1"}, {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-', "Disable caching and tickets if ephemeral (EC)DH is used"}, {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"}, @@ -915,6 +919,7 @@ OPTIONS s_server_options[] = { {"brief", OPT_BRIEF, '-'}, {"rev", OPT_REV, '-'}, {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, + {"ssl_config", OPT_SSL_CONFIG, 's'}, OPT_S_OPTIONS, OPT_V_OPTIONS, OPT_X_OPTIONS, @@ -936,16 +941,29 @@ OPTIONS s_server_options[] = { #ifndef OPENSSL_NO_SSL3 {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"}, #endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just talk TLSv1"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"}, +#endif #ifndef OPENSSL_NO_DTLS {"dtls", OPT_DTLS, '-'}, - {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, - {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, {"mtu", OPT_MTU, 'p', "Set link layer MTU"}, {"chain", OPT_CHAIN, '-', "Read a certificate chain"}, {"listen", OPT_LISTEN, '-', "Listen for a DTLS ClientHello with a cookie and then connect"}, #endif +#ifndef OPENSSL_NO_DTLS1 + {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, +#endif #ifndef OPENSSL_NO_DH {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, #endif @@ -987,11 +1005,10 @@ int s_server_main(int argc, char *argv[]) #ifndef OPENSSL_NO_PSK char *p; #endif - const char *unix_path = NULL; -#ifndef NO_SYS_UN_H +#ifdef AF_UNIX int unlink_unix_path = 0; #endif - int (*server_cb) (char *hostname, int s, int stype, + int (*server_cb) (const char *hostname, int s, int stype, unsigned char *context); int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0; #ifndef OPENSSL_NO_DH @@ -1001,14 +1018,17 @@ int s_server_main(int argc, char *argv[]) int noCApath = 0, noCAfile = 0; 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, socket_type = SOCK_STREAM; + int rev = 0, naccept = -1, sdebug = 0; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM; int state = 0, crl_format = FORMAT_PEM, crl_download = 0; - unsigned short port = PORT; + char *host = NULL; + char *port = BUF_strdup(PORT); unsigned char *context = NULL; OPTION_CHOICE o; EVP_PKEY *s_key2 = NULL; X509 *s_cert2 = NULL; tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING }; + const char *ssl_config = NULL; #ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; tlsextnextprotoctx next_proto = { NULL, 0 }; @@ -1037,19 +1057,6 @@ int s_server_main(int argc, char *argv[]) prog = opt_init(argc, argv, s_server_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { -#ifdef OPENSSL_NO_PSK - case OPT_PSK_HINT: - case OPT_PSK: -#endif -#ifdef OPENSSL_NO_DTLS - case OPT_DTLS: - case OPT_DTLS1: - case OPT_DTLS1_2: - case OPT_TIMEOUT: - case OPT_MTU: - case OPT_CHAIN: - case OPT_LISTEN: -#endif case OPT_EOF: case OPT_ERR: opthelp: @@ -1060,26 +1067,71 @@ int s_server_main(int argc, char *argv[]) ret = 0; goto end; + case OPT_4: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; + } +#endif + socket_family = AF_INET; + break; + case OPT_6: + if (1) { +#ifdef AF_INET6 +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; + } +#endif + socket_family = AF_INET6; + } else { +#endif + BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog); + goto end; + } + break; case OPT_PORT: - if (!extract_port(opt_arg(), &port)) +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } +#endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -port argument malformed or ambiguous\n", + port); goto end; + } break; - case OPT_UNIX: -#ifdef NO_SYS_UN_H - BIO_printf(bio_err, "unix domain sockets unsupported\n"); - goto end; -#else - unix_path = opt_arg(); + case OPT_ACCEPT: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } #endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -accept argument malformed or ambiguous\n", + port); + goto end; + } + break; +#ifdef AF_UNIX + case OPT_UNIX: + socket_family = AF_UNIX; + OPENSSL_free(host); host = BUF_strdup(opt_arg()); + OPENSSL_free(port); port = NULL; break; case OPT_UNLINK: -#ifdef NO_SYS_UN_H - BIO_printf(bio_err, "unix domain sockets unsupported\n"); - goto end; -#else unlink_unix_path = 1; -#endif break; +#endif case OPT_NACCEPT: naccept = atol(opt_arg()); break; @@ -1297,33 +1349,33 @@ int s_server_main(int argc, char *argv[]) case OPT_NO_RESUME_EPHEMERAL: no_resume_ephemeral = 1; break; -#ifndef OPENSSL_NO_PSK case OPT_PSK_HINT: +#ifndef OPENSSL_NO_PSK psk_identity_hint = opt_arg(); +#endif break; case OPT_PSK: +#ifndef OPENSSL_NO_PSK for (p = psk_key = opt_arg(); *p; p++) { if (isxdigit(*p)) continue; BIO_printf(bio_err, "Not a hex number '%s'\n", *argv); goto end; } - break; #endif -#ifndef OPENSSL_NO_SRP + break; case OPT_SRPVFILE: +#ifndef OPENSSL_NO_SRP srp_verifier_file = opt_arg(); meth = TLSv1_server_method(); +#endif break; case OPT_SRPUSERSEED: +#ifndef OPENSSL_NO_SRP srpuserseed = opt_arg(); meth = TLSv1_server_method(); - break; -#else - case OPT_SRPVFILE: - case OPT_SRPUSERSEED: - break; #endif + break; case OPT_REV: rev = 1; break; @@ -1336,46 +1388,67 @@ int s_server_main(int argc, char *argv[]) case OPT_HTTP: www = 3; break; + case OPT_SSL_CONFIG: + ssl_config = opt_arg(); + break; case OPT_SSL3: #ifndef OPENSSL_NO_SSL3 meth = SSLv3_server_method(); #endif break; case OPT_TLS1_2: +#ifndef OPENSSL_NO_TLS1_2 meth = TLSv1_2_server_method(); +#endif break; case OPT_TLS1_1: +#ifndef OPENSSL_NO_TLS1_1 meth = TLSv1_1_server_method(); +#endif break; case OPT_TLS1: +#ifndef OPENSSL_NO_TLS1 meth = TLSv1_server_method(); +#endif break; -#ifndef OPENSSL_NO_DTLS case OPT_DTLS: +#ifndef OPENSSL_NO_DTLS meth = DTLS_server_method(); socket_type = SOCK_DGRAM; +#endif break; case OPT_DTLS1: +#ifndef OPENSSL_NO_DTLS1 meth = DTLSv1_server_method(); socket_type = SOCK_DGRAM; +#endif break; case OPT_DTLS1_2: +#ifndef OPENSSL_NO_DTLS1_2 meth = DTLSv1_2_server_method(); socket_type = SOCK_DGRAM; +#endif break; case OPT_TIMEOUT: +#ifndef OPENSSL_NO_DTLS enable_timeouts = 1; +#endif break; case OPT_MTU: +#ifndef OPENSSL_NO_DTLS socket_mtu = atol(opt_arg()); +#endif break; case OPT_CHAIN: +#ifndef OPENSSL_NO_DTLS cert_chain = 1; +#endif break; case OPT_LISTEN: +#ifndef OPENSSL_NO_DTLS dtlslisten = 1; - break; #endif + break; case OPT_ID_PREFIX: session_id_prefix = opt_arg(); break; @@ -1442,11 +1515,13 @@ int s_server_main(int argc, char *argv[]) } #endif - if (unix_path && (socket_type != SOCK_STREAM)) { +#ifdef AF_UNIX + if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { BIO_printf(bio_err, "Can't use unix sockets and datagrams together\n"); goto end; } +#endif #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) if (jpake_secret) { if (psk_key) { @@ -1487,9 +1562,8 @@ int s_server_main(int argc, char *argv[]) goto end; } if (s_chain_file) { - s_chain = load_certs(s_chain_file, FORMAT_PEM, - NULL, e, "server certificate chain"); - if (!s_chain) + if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, e, + "server certificate chain")) goto end; } @@ -1567,9 +1641,8 @@ int s_server_main(int argc, char *argv[]) goto end; } if (s_dchain_file) { - s_dchain = load_certs(s_dchain_file, FORMAT_PEM, - NULL, e, "second server certificate chain"); - if (!s_dchain) + if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, e, + "second server certificate chain")) goto end; } @@ -1613,6 +1686,15 @@ int s_server_main(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } + if (ssl_config) { + if (SSL_CTX_config(ctx, ssl_config) == 0) { + BIO_printf(bio_err, "Error using configuration \"%s\"\n", + ssl_config); + ERR_print_errors(bio_err); + goto end; + } + } + if (session_id_prefix) { if (strlen(session_id_prefix) >= 32) BIO_printf(bio_err, @@ -1902,16 +1984,13 @@ int s_server_main(int argc, char *argv[]) server_cb = www_body; else server_cb = sv_body; -#ifndef NO_SYS_UN_H - if (unix_path) { - if (unlink_unix_path) - unlink(unix_path); - do_server_unix(unix_path, &accept_socket, server_cb, context, - naccept); - } else +#ifdef AF_UNIX + if (socket_family == AF_UNIX + && unlink_unix_path) + unlink(host); #endif - do_server(port, socket_type, &accept_socket, server_cb, context, - naccept); + do_server(&accept_socket, host, port, socket_family, socket_type, + server_cb, context, naccept); print_stats(bio_s_out, ctx); ret = 0; end: @@ -1925,6 +2004,8 @@ int s_server_main(int argc, char *argv[]) sk_X509_pop_free(s_dchain, X509_free); OPENSSL_free(pass); OPENSSL_free(dpass); + OPENSSL_free(host); + OPENSSL_free(port); X509_VERIFY_PARAM_free(vpm); free_sessions(); OPENSSL_free(tlscstatp.host); @@ -1979,7 +2060,8 @@ 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, int stype, unsigned char *context) +static int sv_body(const char *hostname, int s, int stype, + unsigned char *context) { char *buf = NULL; fd_set readfds; @@ -2028,7 +2110,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) ret = -1; goto err; } - +#ifndef OPENSSL_NO_DTLS if (stype == SOCK_DGRAM) { sbio = BIO_new_dgram(s, BIO_NOCLOSE); @@ -2065,6 +2147,7 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) /* turn on cookie exchange */ SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); } else +#endif sbio = BIO_new_socket(s, BIO_NOCLOSE); if (s_nbio_test) { @@ -2083,7 +2166,6 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) /* SSL_set_fd(con,s); */ 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); } @@ -2405,12 +2487,15 @@ static int init_ssl_connection(SSL *con) unsigned next_proto_neg_len; #endif unsigned char *exportedkeymat; -#ifndef OPENSSL_NO_DTLS - struct sockaddr_storage client; -#endif #ifndef OPENSSL_NO_DTLS if(dtlslisten) { + BIO_ADDR *client = NULL; + + if ((client = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "ERROR - memory\n"); + return 0; + } i = DTLSv1_listen(con, &client); if (i > 0) { BIO *wbio; @@ -2421,11 +2506,12 @@ static int init_ssl_connection(SSL *con) BIO_get_fd(wbio, &fd); } - if(!wbio || connect(fd, (struct sockaddr *)&client, - sizeof(struct sockaddr_storage))) { + if(!wbio || BIO_connect(fd, client, 0) == 0) { BIO_printf(bio_err, "ERROR - unable to connect\n"); + BIO_ADDR_free(client); return 0; } + BIO_ADDR_free(client); dtlslisten = 0; i = SSL_accept(con); } @@ -2568,7 +2654,8 @@ static DH *load_dh_param(const char *dhfile) } #endif -static int www_body(char *hostname, int s, int stype, unsigned char *context) +static int www_body(const char *hostname, int s, int stype, + unsigned char *context) { char *buf = NULL; int ret = 1; @@ -2636,7 +2723,6 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) #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); } @@ -2956,7 +3042,8 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) return (ret); } -static int rev_body(char *hostname, int s, int stype, unsigned char *context) +static int rev_body(const char *hostname, int s, int stype, + unsigned char *context) { char *buf = NULL; int i; @@ -2998,7 +3085,6 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) #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); } @@ -3165,7 +3251,7 @@ static int add_session(SSL *ssl, SSL_SESSION *session) return 0; } - sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); + sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); sess->der = app_malloc(sess->derlen, "get session buffer"); if (!sess->id) { BIO_printf(bio_err, "Out of memory adding to external cache\n"); @@ -3191,7 +3277,7 @@ static int add_session(SSL *ssl, SSL_SESSION *session) return 0; } -static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen, +static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, int *do_copy) { simple_ssl_session *sess;