Add a -sctp option to s_server
Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3286)
This commit is contained in:
parent
5114d8227e
commit
72d0bc84de
3 changed files with 80 additions and 21 deletions
|
@ -20,9 +20,9 @@
|
|||
#define PORT "4433"
|
||||
#define PROTOCOL "tcp"
|
||||
|
||||
typedef int (*do_server_cb)(int s, int stype, unsigned char *context);
|
||||
typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
|
||||
int do_server(int *accept_sock, const char *host, const char *port,
|
||||
int family, int type,
|
||||
int family, int type, int protocol,
|
||||
do_server_cb cb,
|
||||
unsigned char *context, int naccept);
|
||||
#ifdef HEADER_X509_H
|
||||
|
|
|
@ -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);
|
||||
|
@ -719,7 +719,7 @@ typedef enum OPTION_choice {
|
|||
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_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,
|
||||
|
@ -903,6 +903,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
|
||||
|
@ -960,7 +963,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);
|
||||
|
@ -1429,6 +1432,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:
|
||||
|
@ -1543,6 +1551,17 @@ int s_server_main(int argc, char *argv[])
|
|||
}
|
||||
#endif
|
||||
|
||||
#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 (split_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
BIO_printf(bio_err, "Bad split send fragment size\n");
|
||||
goto end;
|
||||
|
@ -2018,7 +2037,7 @@ 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;
|
||||
|
@ -2090,7 +2109,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;
|
||||
|
@ -2105,6 +2124,13 @@ static int sv_body(int s, int stype, unsigned char *context)
|
|||
#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");
|
||||
if (s_nbio) {
|
||||
|
@ -2136,9 +2162,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;
|
||||
|
@ -2169,12 +2199,20 @@ 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);
|
||||
if (prot != IPPROTO_SCTP) {
|
||||
/* Turn on cookie exchange. Not necessary for SCTP */
|
||||
SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
|
||||
}
|
||||
} 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;
|
||||
|
||||
|
@ -2767,7 +2805,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;
|
||||
|
@ -3153,7 +3191,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;
|
||||
|
|
|
@ -128,7 +128,7 @@ int init_client(int *sock, const char *host, const char *port,
|
|||
* 0 on failure, something other on success.
|
||||
*/
|
||||
int do_server(int *accept_sock, const char *host, const char *port,
|
||||
int family, int type, do_server_cb cb,
|
||||
int family, int type, int protocol, do_server_cb cb,
|
||||
unsigned char *context, int naccept)
|
||||
{
|
||||
int asock = 0;
|
||||
|
@ -140,7 +140,8 @@ int do_server(int *accept_sock, const char *host, const char *port,
|
|||
if (!BIO_sock_init())
|
||||
return 0;
|
||||
|
||||
if (!BIO_lookup(host, port, BIO_LOOKUP_SERVER, family, type, &res)) {
|
||||
if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol,
|
||||
&res)) {
|
||||
ERR_print_errors(bio_err);
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,7 +149,8 @@ int do_server(int *accept_sock, const char *host, const char *port,
|
|||
/* Admittedly, these checks are quite paranoid, we should not get
|
||||
* anything in the BIO_ADDRINFO chain that we haven't asked for */
|
||||
OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
|
||||
&& (type == 0 || type == BIO_ADDRINFO_socktype(res)));
|
||||
&& (type == 0 || type == BIO_ADDRINFO_socktype(res))
|
||||
&& (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res)));
|
||||
|
||||
asock = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
|
||||
BIO_ADDRINFO_protocol(res), 0);
|
||||
|
@ -161,6 +163,25 @@ int do_server(int *accept_sock, const char *host, const char *port,
|
|||
goto end;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (protocol == IPPROTO_SCTP) {
|
||||
/*
|
||||
* For SCTP we have to set various options on the socket prior to
|
||||
* accepting. This is done automatically by BIO_new_dgram_sctp().
|
||||
* We don't actually need the created BIO though so we free it again
|
||||
* immediately.
|
||||
*/
|
||||
BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE);
|
||||
|
||||
if (tmpbio == NULL) {
|
||||
BIO_closesocket(asock);
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
BIO_free(tmpbio);
|
||||
}
|
||||
#endif
|
||||
|
||||
BIO_ADDRINFO_free(res);
|
||||
res = NULL;
|
||||
|
||||
|
@ -176,10 +197,10 @@ int do_server(int *accept_sock, const char *host, const char *port,
|
|||
BIO_closesocket(asock);
|
||||
break;
|
||||
}
|
||||
i = (*cb)(sock, type, context);
|
||||
i = (*cb)(sock, type, protocol, context);
|
||||
BIO_closesocket(sock);
|
||||
} else {
|
||||
i = (*cb)(asock, type, context);
|
||||
i = (*cb)(asock, type, protocol, context);
|
||||
}
|
||||
|
||||
if (naccept != -1)
|
||||
|
|
Loading…
Reference in a new issue