summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2014-12-10 15:24:01 +0000
committerjsing <jsing@openbsd.org>2014-12-10 15:24:01 +0000
commit1b4c9cadff09a31b4e349dd13647f233f6388ff6 (patch)
treed7e690b470a8464ee1c932c8ed19bbed3c98d12d
parentAdd regress for ALPN. (diff)
downloadwireguard-openbsd-1b4c9cadff09a31b4e349dd13647f233f6388ff6.tar.xz
wireguard-openbsd-1b4c9cadff09a31b4e349dd13647f233f6388ff6.zip
Add ALPN support to openssl(1).
Based on OpenSSL.
-rw-r--r--usr.bin/openssl/s_client.c32
-rw-r--r--usr.bin/openssl/s_server.c74
2 files changed, 95 insertions, 11 deletions
diff --git a/usr.bin/openssl/s_client.c b/usr.bin/openssl/s_client.c
index 94e24dacaae..4476852cdb4 100644
--- a/usr.bin/openssl/s_client.c
+++ b/usr.bin/openssl/s_client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: s_client.c,v 1.9 2014/12/02 19:44:49 deraadt Exp $ */
+/* $OpenBSD: s_client.c,v 1.10 2014/12/10 15:24:01 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -253,6 +253,7 @@ sc_usage(void)
#ifndef OPENSSL_NO_NEXTPROTONEG
BIO_printf(bio_err, " -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n");
#endif
+ BIO_printf(bio_err, " -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n");
#ifndef OPENSSL_NO_SRTP
BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
#endif
@@ -374,6 +375,7 @@ s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_NEXTPROTONEG
const char *next_proto_neg_in = NULL;
#endif
+ const char *alpn_in = NULL;
char *sess_in = NULL;
char *sess_out = NULL;
struct sockaddr peer;
@@ -544,7 +546,11 @@ s_client_main(int argc, char **argv)
next_proto_neg_in = *(++argv);
}
#endif
- else if (strcmp(*argv, "-serverpref") == 0)
+ else if (strcmp(*argv, "-alpn") == 0) {
+ if (--argc < 1)
+ goto bad;
+ alpn_in = *(++argv);
+ } else if (strcmp(*argv, "-serverpref") == 0)
off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
else if (strcmp(*argv, "-legacy_renegotiation") == 0)
; /* no-op */
@@ -736,6 +742,17 @@ bad:
if (next_proto.data)
SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
#endif
+ if (alpn_in) {
+ unsigned short alpn_len;
+ unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);
+
+ if (alpn == NULL) {
+ BIO_printf(bio_err, "Error parsing -alpn argument\n");
+ goto end;
+ }
+ SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
+ free(alpn);
+ }
if (state)
SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
@@ -1423,6 +1440,17 @@ print_stuff(BIO * bio, SSL * s, int full)
BIO_write(bio, "\n", 1);
}
#endif
+ {
+ const unsigned char *proto;
+ unsigned int proto_len;
+ SSL_get0_alpn_selected(s, &proto, &proto_len);
+ if (proto_len > 0) {
+ BIO_printf(bio, "ALPN protocol: ");
+ BIO_write(bio, proto, proto_len);
+ BIO_write(bio, "\n", 1);
+ } else
+ BIO_printf(bio, "No ALPN negotiated\n");
+ }
#ifndef OPENSSL_NO_SRTP
{
diff --git a/usr.bin/openssl/s_server.c b/usr.bin/openssl/s_server.c
index b3cdb30a61f..35ed6d169c0 100644
--- a/usr.bin/openssl/s_server.c
+++ b/usr.bin/openssl/s_server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: s_server.c,v 1.7 2014/12/02 19:44:49 deraadt Exp $ */
+/* $OpenBSD: s_server.c,v 1.8 2014/12/10 15:24:01 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -351,6 +351,7 @@ sv_usage(void)
#ifndef OPENSSL_NO_NEXTPROTONEG
BIO_printf(bio_err, " -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n");
#endif
+ BIO_printf(bio_err," -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n");
#ifndef OPENSSL_NO_SRTP
BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
#endif
@@ -545,6 +546,45 @@ next_proto_cb(SSL * s, const unsigned char **data, unsigned int *len, void *arg)
#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
+/* 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);
+}
int s_server_main(int, char **);
@@ -583,8 +623,10 @@ s_server_main(int argc, char *argv[])
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 };
meth = SSLv23_server_method();
local_argc = argc;
@@ -838,6 +880,11 @@ s_server_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);
+ }
#ifndef OPENSSL_NO_SRTP
else if (strcmp(*argv, "-use_srtp") == 0) {
if (--argc < 1)
@@ -916,7 +963,7 @@ bad:
}
}
}
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto_neg_in) {
unsigned short len;
next_proto.data = next_protos_parse(&len, next_proto_neg_in);
@@ -927,7 +974,14 @@ bad:
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;
+ }
if (s_dcert_file) {
@@ -957,8 +1011,7 @@ bad:
bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE);
}
}
- if (nocert)
- {
+ if (nocert) {
s_cert_file = NULL;
s_key_file = NULL;
s_dcert_file = NULL;
@@ -1076,6 +1129,8 @@ bad:
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);
#ifndef OPENSSL_NO_DH
if (!no_dhe) {
@@ -1241,6 +1296,8 @@ end:
X509_free(s_cert2);
if (s_key2)
EVP_PKEY_free(s_key2);
+ free(next_proto.data);
+ free(alpn_ctx.data);
if (bio_s_out != NULL) {
BIO_free(bio_s_out);
bio_s_out = NULL;
@@ -1603,13 +1660,12 @@ init_ssl_connection(SSL * con)
X509 *peer;
long verify_error;
char buf[BUFSIZ];
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
const unsigned char *next_proto_neg;
unsigned next_proto_neg_len;
#endif
unsigned char *exportedkeymat;
-
i = SSL_accept(con);
if (i <= 0) {
if (BIO_sock_should_retry(i)) {
@@ -1642,7 +1698,7 @@ init_ssl_connection(SSL * con)
str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
if (next_proto_neg) {
BIO_printf(bio_s_out, "NEXTPROTO is ");