Adds no new files, and I've seen it before.. ok beck@ - get it in and we'll sort it out in tree if anything further is needed.
On Wed, Jul 27, 2016 at 10:59 AM, Joel Sing <j...@sing.id.au> wrote: > The following diff adds ALPN support to libtls via: > > tls_config_set_alpn() - set the ALPN protocols supported by this > client/server > tls_conn_alpn_selected() - get the ALPN protocol selected for this > connection > > ok? > > Index: tls.c > =================================================================== > RCS file: /cvs/src/lib/libtls/tls.c,v > retrieving revision 1.41 > diff -u -p -r1.41 tls.c > --- tls.c 7 Jul 2016 14:09:03 -0000 1.41 > +++ tls.c 27 Jul 2016 16:57:06 -0000 > @@ -310,6 +310,14 @@ tls_configure_ssl(struct tls *ctx) > if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0) > SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1_2); > > + if (ctx->config->alpn != NULL) { > + if (SSL_CTX_set_alpn_protos(ctx->ssl_ctx, > ctx->config->alpn, > + ctx->config->alpn_len) != 0) { > + tls_set_errorx(ctx, "failed to set alpn"); > + goto err; > + } > + } > + > if (ctx->config->ciphers != NULL) { > if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, > ctx->config->ciphers) != 1) { > Index: tls.h > =================================================================== > RCS file: /cvs/src/lib/libtls/tls.h,v > retrieving revision 1.29 > diff -u -p -r1.29 tls.h > --- tls.h 27 May 2016 14:21:24 -0000 1.29 > +++ tls.h 27 Jul 2016 16:57:06 -0000 > @@ -52,6 +52,7 @@ const char *tls_error(struct tls *_ctx); > struct tls_config *tls_config_new(void); > void tls_config_free(struct tls_config *_config); > > +int tls_config_set_alpn(struct tls_config *_config, const char *_alpn); > int tls_config_set_ca_file(struct tls_config *_config, const char > *_ca_file); > int tls_config_set_ca_path(struct tls_config *_config, const char > *_ca_path); > int tls_config_set_ca_mem(struct tls_config *_config, const uint8_t *_ca, > @@ -116,8 +117,9 @@ const char *tls_peer_cert_subject(struct > time_t tls_peer_cert_notbefore(struct tls *_ctx); > time_t tls_peer_cert_notafter(struct tls *_ctx); > > -const char *tls_conn_version(struct tls *_ctx); > +const char *tls_conn_alpn_selected(struct tls *_ctx); > const char *tls_conn_cipher(struct tls *_ctx); > +const char *tls_conn_version(struct tls *_ctx); > > uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); > > Index: tls_config.c > =================================================================== > RCS file: /cvs/src/lib/libtls/tls_config.c,v > retrieving revision 1.22 > diff -u -p -r1.22 tls_config.c > --- tls_config.c 13 Jul 2016 16:30:48 -0000 1.22 > +++ tls_config.c 27 Jul 2016 16:57:06 -0000 > @@ -166,6 +166,7 @@ tls_config_free(struct tls_config *confi > > free(config->error.msg); > > + free(config->alpn); > free((char *)config->ca_file); > free((char *)config->ca_mem); > free((char *)config->ca_path); > @@ -247,6 +248,72 @@ tls_config_parse_protocols(uint32_t *pro > free(s); > > return (0); > +} > + > +static int > +tls_config_parse_alpn(struct tls_config *config, const char *alpn, > + char **alpn_data, size_t *alpn_len) > +{ > + size_t buf_len, i, len; > + char *buf = NULL; > + char *s = NULL; > + char *p, *q; > + > + if ((buf_len = strlen(alpn) + 1) > 65535) { > + tls_config_set_errorx(config, "alpn too large"); > + goto err; > + } > + > + if ((buf = malloc(buf_len)) == NULL) { > + tls_config_set_errorx(config, "out of memory"); > + goto err; > + } > + > + if ((s = strdup(alpn)) == NULL) { > + tls_config_set_errorx(config, "out of memory"); > + goto err; > + } > + > + i = 0; > + q = s; > + while ((p = strsep(&q, ",")) != NULL) { > + if ((len = strlen(p)) == 0) { > + tls_config_set_errorx(config, > + "alpn protocol with zero length"); > + goto err; > + } > + if (len > 255) { > + tls_config_set_errorx(config, > + "alpn protocol too long"); > + goto err; > + } > + buf[i++] = len & 0xff; > + memcpy(&buf[i], p, len); > + i += len; > + } > + > + free(s); > + > + *alpn_data = buf; > + *alpn_len = buf_len; > + > + return (0); > + > + err: > + free(buf); > + free(s); > + > + *alpn_data = NULL; > + *alpn_len = 0; > + > + return (-1); > +} > + > +int > +tls_config_set_alpn(struct tls_config *config, const char *alpn) > +{ > + return tls_config_parse_alpn(config, alpn, &config->alpn, > + &config->alpn_len); > } > > int > Index: tls_conninfo.c > =================================================================== > RCS file: /cvs/src/lib/libtls/tls_conninfo.c,v > retrieving revision 1.5 > diff -u -p -r1.5 tls_conninfo.c > --- tls_conninfo.c 7 Oct 2015 23:33:38 -0000 1.5 > +++ tls_conninfo.c 27 Jul 2016 16:57:06 -0000 > @@ -150,6 +150,26 @@ tls_get_peer_cert_times(struct tls *ctx, > return (rv); > } > > +static int > +tls_conninfo_alpn_proto(struct tls *ctx) > +{ > + const unsigned char *p; > + unsigned int len; > + > + free(ctx->conninfo->alpn); > + ctx->conninfo->alpn = NULL; > + > + SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); > + if (len > 0) { > + if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) > + return (-1); > + memcpy(ctx->conninfo->alpn, p, len); > + ctx->conninfo->alpn[len] = '\0'; > + } > + > + return (0); > +} > + > int > tls_get_conninfo(struct tls *ctx) { > const char * tmp; > @@ -175,6 +195,9 @@ tls_get_conninfo(struct tls *ctx) { > ctx->conninfo->cipher = strdup(tmp); > if (ctx->conninfo->cipher == NULL) > goto err; > + if (tls_conninfo_alpn_proto(ctx) == -1) > + goto err; > + > return (0); > err: > tls_free_conninfo(ctx->conninfo); > @@ -184,6 +207,8 @@ err: > void > tls_free_conninfo(struct tls_conninfo *conninfo) { > if (conninfo != NULL) { > + free(conninfo->alpn); > + conninfo->alpn = NULL; > free(conninfo->hash); > conninfo->hash = NULL; > free(conninfo->subject); > @@ -195,6 +220,14 @@ tls_free_conninfo(struct tls_conninfo *c > free(conninfo->cipher); > conninfo->cipher = NULL; > } > +} > + > +const char * > +tls_conn_alpn_selected(struct tls *ctx) > +{ > + if (ctx->conninfo == NULL) > + return (NULL); > + return (ctx->conninfo->alpn); > } > > const char * > Index: tls_init.3 > =================================================================== > RCS file: /cvs/src/lib/libtls/tls_init.3,v > retrieving revision 1.62 > diff -u -p -r1.62 tls_init.3 > --- tls_init.3 13 Jul 2016 16:30:48 -0000 1.62 > +++ tls_init.3 27 Jul 2016 16:57:06 -0000 > @@ -24,6 +24,7 @@ > .Nm tls_config_new , > .Nm tls_config_free , > .Nm tls_config_parse_protocols , > +.Nm tls_config_set_alpn , > .Nm tls_config_set_ca_file , > .Nm tls_config_set_ca_path , > .Nm tls_config_set_ca_mem , > @@ -54,8 +55,9 @@ > .Nm tls_peer_cert_hash , > .Nm tls_peer_cert_notbefore , > .Nm tls_peer_cert_notafter , > -.Nm tls_conn_version , > +.Nm tls_conn_alpn_selected , > .Nm tls_conn_cipher , > +.Nm tls_conn_version , > .Nm tls_load_file , > .Nm tls_client , > .Nm tls_server , > @@ -88,6 +90,8 @@ > .Ft "int" > .Fn tls_config_parse_protocols "uint32_t *protocols" "const char > *protostr" > .Ft "int" > +.Fn tls_config_set_alpn "struct tls_config *config" "const char *alpn" > +.Ft "int" > .Fn tls_config_set_ca_file "struct tls_config *config" "const char > *ca_file" > .Ft "int" > .Fn tls_config_set_ca_path "struct tls_config *config" "const char > *ca_path" > @@ -148,9 +152,11 @@ > .Ft "time_t" > .Fn tls_peer_cert_notafter "struct tls *ctx" > .Ft "const char *" > -.Fn tls_conn_version "struct tls *ctx" > +.Fn tls_conn_alpn_selected "struct tls *ctx" > .Ft "const char *" > .Fn tls_conn_cipher "struct tls *ctx" > +.Ft "const char *" > +.Fn tls_conn_version "struct tls *ctx" > .Ft "uint8_t *" > .Fn tls_load_file "const char *file" "size_t *len" "char *password" > .Ft "struct tls *" > @@ -295,6 +301,11 @@ The following functions modify a configu > Configuration options may apply to only clients or only servers or both. > .Bl -bullet -offset four > .It > +.Fn tls_config_set_alpn > +sets the ALPN protocols that are supported. > +The alpn string is a comma separated list of protocols, in order of > preference. > +.Em (Client and Server) > +.It > .Fn tls_config_set_ca_file > sets the filename used to load a file > containing the root certificates. > @@ -480,13 +491,14 @@ the peer certificate from > will only succeed after the handshake is complete. > .Em (Server and client) > .It > -.Fn tls_conn_version > -returns a string > -corresponding to a TLS version negotiated with the peer > +.Fn tls_conn_alpn_selected > +returns a string that specifies the ALPN protocol selected for use with > the peer > connected to > .Ar ctx . > -.Fn tls_conn_version > +If no protocol was selected then NULL is returned. > +.Fn tls_conn_alpn_selected > will only succeed after the handshake is complete. > +.Em (Server and Client) > .It > .Fn tls_conn_cipher > returns a string > @@ -496,6 +508,14 @@ connected to > .Fn tls_conn_cipher > will only succeed after the handshake is complete. > .Em (Server and client) > +.It > +.Fn tls_conn_version > +returns a string > +corresponding to a TLS version negotiated with the peer > +connected to > +.Ar ctx . > +.Fn tls_conn_version > +will only succeed after the handshake is complete. > .It > .Fn tls_load_file > loads a certificate or key from disk into memory to be loaded with > Index: tls_internal.h > =================================================================== > RCS file: /cvs/src/lib/libtls/tls_internal.h,v > retrieving revision 1.32 > diff -u -p -r1.32 tls_internal.h > --- tls_internal.h 13 Jul 2016 16:30:48 -0000 1.32 > +++ tls_internal.h 27 Jul 2016 16:57:06 -0000 > @@ -55,6 +55,8 @@ struct tls_keypair { > struct tls_config { > struct tls_error error; > > + char *alpn; > + size_t alpn_len; > const char *ca_file; > const char *ca_path; > char *ca_mem; > @@ -73,6 +75,7 @@ struct tls_config { > }; > > struct tls_conninfo { > + char *alpn; > char *issuer; > char *subject; > char *hash; > @@ -104,6 +107,7 @@ struct tls { > SSL *ssl_conn; > SSL_CTX *ssl_ctx; > X509 *ssl_peer_cert; > + > struct tls_conninfo *conninfo; > }; > > Index: tls_server.c > =================================================================== > RCS file: /cvs/src/lib/libtls/tls_server.c,v > retrieving revision 1.19 > diff -u -p -r1.19 tls_server.c > --- tls_server.c 28 Apr 2016 17:05:59 -0000 1.19 > +++ tls_server.c 27 Jul 2016 16:57:06 -0000 > @@ -48,6 +48,20 @@ tls_server_conn(struct tls *ctx) > return (conn_ctx); > } > > +static int > +tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char > *outlen, > + const unsigned char *in, unsigned int inlen, void *arg) > +{ > + struct tls *ctx = arg; > + > + if (SSL_select_next_proto((unsigned char**)out, outlen, > + ctx->config->alpn, ctx->config->alpn_len, in, inlen) == > + OPENSSL_NPN_NEGOTIATED) > + return (SSL_TLSEXT_ERR_OK); > + > + return (SSL_TLSEXT_ERR_NOACK); > +} > + > int > tls_configure_server(struct tls *ctx) > { > @@ -70,6 +84,10 @@ tls_configure_server(struct tls *ctx) > if (tls_configure_ssl_verify(ctx, verify) == -1) > goto err; > } > + > + if (ctx->config->alpn != NULL) > + SSL_CTX_set_alpn_select_cb(ctx->ssl_ctx, > tls_server_alpn_cb, > + ctx); > > if (ctx->config->dheparams == -1) > SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1); > > > >