#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);
#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;
#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";
+static const char psk_identity[] = "Client_identity";
char *psk_key = NULL; /* by default PSK is not used */
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
}
/* Structure passed to cert status callback */
-
typedef struct tlsextstatusctx_st {
+ int timeout;
/* File to load OCSP Response from (or NULL if no file) */
char *respin;
/* Default responder to use */
char *host, *path, *port;
int use_ssl;
- int timeout;
int verbose;
} tlsextstatusctx;
-static tlsextstatusctx tlscstatp = { NULL, NULL, NULL, NULL, 0, -1, 0 };
+static tlsextstatusctx tlscstatp = { -1 };
#ifndef OPENSSL_NO_OCSP
err:
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
done:
- if (aia) {
+ /*
+ * If we parsed aia we need to free; otherwise they were copied and we
+ * don't
+ */
+ if (aia != NULL) {
OPENSSL_free(host);
OPENSSL_free(path);
OPENSSL_free(port);
}
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
BIO_free(derbio);
- if (!resp) {
+ if (resp == NULL) {
BIO_puts(bio_err, "cert_status: Error reading OCSP response\n");
goto err;
}
/* 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,
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,
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,
+ OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA,
OPT_S_ENUM,
OPT_V_ENUM,
OPT_X_ENUM
{"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"},
#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
#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}
};
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);
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
int no_resume_ephemeral = 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;
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;
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:
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();
}
#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;
}
#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) {
}
}
#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);
&& 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);
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;
#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) {
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;
/* 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;
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
* 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));
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
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);
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)
}
(void)BIO_flush(bio_s_out);
- return (1);
}
#ifndef OPENSSL_NO_DH
}
#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;
#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);
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;