summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-04-20 09:56:56 +0100
committerMatt Caswell <matt@openssl.org>2017-04-25 11:13:39 +0100
commit72d0bc84de394e93f7d756a997c0d42a4ae35058 (patch)
treec91160175ec3833e4058bf27102483789221fdcc
parent5114d8227e0516fffc0c8653f5118290709f6494 (diff)
Add a -sctp option to s_server
Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3286)
-rw-r--r--apps/s_apps.h4
-rw-r--r--apps/s_server.c66
-rw-r--r--apps/s_socket.c31
3 files changed, 80 insertions, 21 deletions
diff --git a/apps/s_apps.h b/apps/s_apps.h
index aa0565d360..1f76009b8d 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -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
diff --git a/apps/s_server.c b/apps/s_server.c
index 4bd2620c9f..81c3973d6f 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -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);
@@ -1431,6 +1434,11 @@ int s_server_main(int argc, char *argv[])
socket_type = SOCK_DGRAM;
#endif
break;
+ case OPT_SCTP:
+#ifndef OPENSSL_NO_SCTP
+ protocol = IPPROTO_SCTP;
+#endif
+ break;
case OPT_TIMEOUT:
#ifndef OPENSSL_NO_DTLS
enable_timeouts = 1;
@@ -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;
diff --git a/apps/s_socket.c b/apps/s_socket.c
index d16f5ad817..97dc9afffb 100644
--- a/apps/s_socket.c
+++ b/apps/s_socket.c
@@ -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)