diff options
author | jsing <> | 2014-12-10 15:24:01 +0000 |
---|---|---|
committer | jsing <> | 2014-12-10 15:24:01 +0000 |
commit | 7b2f3298f7eb7ce5cfd1c3eb55b1ecc89118f52c (patch) | |
tree | 4a25ae6462c869427ff08aebdc597ea5802b4ec6 | |
parent | e8934f925b10bc19b03a59e35d50bd496f57edff (diff) | |
download | openbsd-7b2f3298f7eb7ce5cfd1c3eb55b1ecc89118f52c.tar.gz openbsd-7b2f3298f7eb7ce5cfd1c3eb55b1ecc89118f52c.tar.bz2 openbsd-7b2f3298f7eb7ce5cfd1c3eb55b1ecc89118f52c.zip |
Add ALPN support to openssl(1).
Based on OpenSSL.
-rw-r--r-- | src/usr.bin/openssl/s_client.c | 32 | ||||
-rw-r--r-- | src/usr.bin/openssl/s_server.c | 74 |
2 files changed, 95 insertions, 11 deletions
diff --git a/src/usr.bin/openssl/s_client.c b/src/usr.bin/openssl/s_client.c index 94e24dacaa..4476852cdb 100644 --- a/src/usr.bin/openssl/s_client.c +++ b/src/usr.bin/openssl/s_client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: s_client.c,v 1.9 2014/12/02 19:44:49 deraadt Exp $ */ | 1 | /* $OpenBSD: s_client.c,v 1.10 2014/12/10 15:24:01 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -253,6 +253,7 @@ sc_usage(void) | |||
253 | #ifndef OPENSSL_NO_NEXTPROTONEG | 253 | #ifndef OPENSSL_NO_NEXTPROTONEG |
254 | BIO_printf(bio_err, " -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); | 254 | BIO_printf(bio_err, " -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); |
255 | #endif | 255 | #endif |
256 | BIO_printf(bio_err, " -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n"); | ||
256 | #ifndef OPENSSL_NO_SRTP | 257 | #ifndef OPENSSL_NO_SRTP |
257 | BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); | 258 | BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); |
258 | #endif | 259 | #endif |
@@ -374,6 +375,7 @@ s_client_main(int argc, char **argv) | |||
374 | #ifndef OPENSSL_NO_NEXTPROTONEG | 375 | #ifndef OPENSSL_NO_NEXTPROTONEG |
375 | const char *next_proto_neg_in = NULL; | 376 | const char *next_proto_neg_in = NULL; |
376 | #endif | 377 | #endif |
378 | const char *alpn_in = NULL; | ||
377 | char *sess_in = NULL; | 379 | char *sess_in = NULL; |
378 | char *sess_out = NULL; | 380 | char *sess_out = NULL; |
379 | struct sockaddr peer; | 381 | struct sockaddr peer; |
@@ -544,7 +546,11 @@ s_client_main(int argc, char **argv) | |||
544 | next_proto_neg_in = *(++argv); | 546 | next_proto_neg_in = *(++argv); |
545 | } | 547 | } |
546 | #endif | 548 | #endif |
547 | else if (strcmp(*argv, "-serverpref") == 0) | 549 | else if (strcmp(*argv, "-alpn") == 0) { |
550 | if (--argc < 1) | ||
551 | goto bad; | ||
552 | alpn_in = *(++argv); | ||
553 | } else if (strcmp(*argv, "-serverpref") == 0) | ||
548 | off |= SSL_OP_CIPHER_SERVER_PREFERENCE; | 554 | off |= SSL_OP_CIPHER_SERVER_PREFERENCE; |
549 | else if (strcmp(*argv, "-legacy_renegotiation") == 0) | 555 | else if (strcmp(*argv, "-legacy_renegotiation") == 0) |
550 | ; /* no-op */ | 556 | ; /* no-op */ |
@@ -736,6 +742,17 @@ bad: | |||
736 | if (next_proto.data) | 742 | if (next_proto.data) |
737 | SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); | 743 | SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); |
738 | #endif | 744 | #endif |
745 | if (alpn_in) { | ||
746 | unsigned short alpn_len; | ||
747 | unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in); | ||
748 | |||
749 | if (alpn == NULL) { | ||
750 | BIO_printf(bio_err, "Error parsing -alpn argument\n"); | ||
751 | goto end; | ||
752 | } | ||
753 | SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); | ||
754 | free(alpn); | ||
755 | } | ||
739 | 756 | ||
740 | if (state) | 757 | if (state) |
741 | SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); | 758 | SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); |
@@ -1423,6 +1440,17 @@ print_stuff(BIO * bio, SSL * s, int full) | |||
1423 | BIO_write(bio, "\n", 1); | 1440 | BIO_write(bio, "\n", 1); |
1424 | } | 1441 | } |
1425 | #endif | 1442 | #endif |
1443 | { | ||
1444 | const unsigned char *proto; | ||
1445 | unsigned int proto_len; | ||
1446 | SSL_get0_alpn_selected(s, &proto, &proto_len); | ||
1447 | if (proto_len > 0) { | ||
1448 | BIO_printf(bio, "ALPN protocol: "); | ||
1449 | BIO_write(bio, proto, proto_len); | ||
1450 | BIO_write(bio, "\n", 1); | ||
1451 | } else | ||
1452 | BIO_printf(bio, "No ALPN negotiated\n"); | ||
1453 | } | ||
1426 | 1454 | ||
1427 | #ifndef OPENSSL_NO_SRTP | 1455 | #ifndef OPENSSL_NO_SRTP |
1428 | { | 1456 | { |
diff --git a/src/usr.bin/openssl/s_server.c b/src/usr.bin/openssl/s_server.c index b3cdb30a61..35ed6d169c 100644 --- a/src/usr.bin/openssl/s_server.c +++ b/src/usr.bin/openssl/s_server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: s_server.c,v 1.7 2014/12/02 19:44:49 deraadt Exp $ */ | 1 | /* $OpenBSD: s_server.c,v 1.8 2014/12/10 15:24:01 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -351,6 +351,7 @@ sv_usage(void) | |||
351 | #ifndef OPENSSL_NO_NEXTPROTONEG | 351 | #ifndef OPENSSL_NO_NEXTPROTONEG |
352 | BIO_printf(bio_err, " -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n"); | 352 | BIO_printf(bio_err, " -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n"); |
353 | #endif | 353 | #endif |
354 | BIO_printf(bio_err," -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n"); | ||
354 | #ifndef OPENSSL_NO_SRTP | 355 | #ifndef OPENSSL_NO_SRTP |
355 | BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); | 356 | BIO_printf(bio_err, " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); |
356 | #endif | 357 | #endif |
@@ -545,6 +546,45 @@ next_proto_cb(SSL * s, const unsigned char **data, unsigned int *len, void *arg) | |||
545 | #endif /* ndef OPENSSL_NO_NEXTPROTONEG */ | 546 | #endif /* ndef OPENSSL_NO_NEXTPROTONEG */ |
546 | 547 | ||
547 | 548 | ||
549 | /* This the context that we pass to alpn_cb */ | ||
550 | typedef struct tlsextalpnctx_st { | ||
551 | unsigned char *data; | ||
552 | unsigned short len; | ||
553 | } tlsextalpnctx; | ||
554 | |||
555 | static int | ||
556 | alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
557 | const unsigned char *in, unsigned int inlen, void *arg) | ||
558 | { | ||
559 | tlsextalpnctx *alpn_ctx = arg; | ||
560 | |||
561 | if (!s_quiet) { | ||
562 | /* We can assume that in is syntactically valid. */ | ||
563 | unsigned i; | ||
564 | |||
565 | BIO_printf(bio_s_out, | ||
566 | "ALPN protocols advertised by the client: "); | ||
567 | for (i = 0; i < inlen; ) { | ||
568 | if (i) | ||
569 | BIO_write(bio_s_out, ", ", 2); | ||
570 | BIO_write(bio_s_out, &in[i + 1], in[i]); | ||
571 | i += in[i] + 1; | ||
572 | } | ||
573 | BIO_write(bio_s_out, "\n", 1); | ||
574 | } | ||
575 | |||
576 | if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data, | ||
577 | alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) | ||
578 | return (SSL_TLSEXT_ERR_NOACK); | ||
579 | |||
580 | if (!s_quiet) { | ||
581 | BIO_printf(bio_s_out, "ALPN protocols selected: "); | ||
582 | BIO_write(bio_s_out, *out, *outlen); | ||
583 | BIO_write(bio_s_out, "\n", 1); | ||
584 | } | ||
585 | |||
586 | return (SSL_TLSEXT_ERR_OK); | ||
587 | } | ||
548 | 588 | ||
549 | int s_server_main(int, char **); | 589 | int s_server_main(int, char **); |
550 | 590 | ||
@@ -583,8 +623,10 @@ s_server_main(int argc, char *argv[]) | |||
583 | tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING}; | 623 | tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING}; |
584 | #ifndef OPENSSL_NO_NEXTPROTONEG | 624 | #ifndef OPENSSL_NO_NEXTPROTONEG |
585 | const char *next_proto_neg_in = NULL; | 625 | const char *next_proto_neg_in = NULL; |
586 | tlsextnextprotoctx next_proto; | 626 | tlsextnextprotoctx next_proto = { NULL, 0 }; |
587 | #endif | 627 | #endif |
628 | const char *alpn_in = NULL; | ||
629 | tlsextalpnctx alpn_ctx = { NULL, 0 }; | ||
588 | meth = SSLv23_server_method(); | 630 | meth = SSLv23_server_method(); |
589 | 631 | ||
590 | local_argc = argc; | 632 | local_argc = argc; |
@@ -838,6 +880,11 @@ s_server_main(int argc, char *argv[]) | |||
838 | next_proto_neg_in = *(++argv); | 880 | next_proto_neg_in = *(++argv); |
839 | } | 881 | } |
840 | #endif | 882 | #endif |
883 | else if (strcmp(*argv,"-alpn") == 0) { | ||
884 | if (--argc < 1) | ||
885 | goto bad; | ||
886 | alpn_in = *(++argv); | ||
887 | } | ||
841 | #ifndef OPENSSL_NO_SRTP | 888 | #ifndef OPENSSL_NO_SRTP |
842 | else if (strcmp(*argv, "-use_srtp") == 0) { | 889 | else if (strcmp(*argv, "-use_srtp") == 0) { |
843 | if (--argc < 1) | 890 | if (--argc < 1) |
@@ -916,7 +963,7 @@ bad: | |||
916 | } | 963 | } |
917 | } | 964 | } |
918 | } | 965 | } |
919 | #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) | 966 | #if !defined(OPENSSL_NO_NEXTPROTONEG) |
920 | if (next_proto_neg_in) { | 967 | if (next_proto_neg_in) { |
921 | unsigned short len; | 968 | unsigned short len; |
922 | next_proto.data = next_protos_parse(&len, next_proto_neg_in); | 969 | next_proto.data = next_protos_parse(&len, next_proto_neg_in); |
@@ -927,7 +974,14 @@ bad: | |||
927 | next_proto.data = NULL; | 974 | next_proto.data = NULL; |
928 | } | 975 | } |
929 | #endif | 976 | #endif |
930 | 977 | alpn_ctx.data = NULL; | |
978 | if (alpn_in) { | ||
979 | unsigned short len; | ||
980 | alpn_ctx.data = next_protos_parse(&len, alpn_in); | ||
981 | if (alpn_ctx.data == NULL) | ||
982 | goto end; | ||
983 | alpn_ctx.len = len; | ||
984 | } | ||
931 | 985 | ||
932 | if (s_dcert_file) { | 986 | if (s_dcert_file) { |
933 | 987 | ||
@@ -957,8 +1011,7 @@ bad: | |||
957 | bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); | 1011 | bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); |
958 | } | 1012 | } |
959 | } | 1013 | } |
960 | if (nocert) | 1014 | if (nocert) { |
961 | { | ||
962 | s_cert_file = NULL; | 1015 | s_cert_file = NULL; |
963 | s_key_file = NULL; | 1016 | s_key_file = NULL; |
964 | s_dcert_file = NULL; | 1017 | s_dcert_file = NULL; |
@@ -1076,6 +1129,8 @@ bad: | |||
1076 | if (next_proto.data) | 1129 | if (next_proto.data) |
1077 | SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto); | 1130 | SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto); |
1078 | #endif | 1131 | #endif |
1132 | if (alpn_ctx.data) | ||
1133 | SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); | ||
1079 | 1134 | ||
1080 | #ifndef OPENSSL_NO_DH | 1135 | #ifndef OPENSSL_NO_DH |
1081 | if (!no_dhe) { | 1136 | if (!no_dhe) { |
@@ -1241,6 +1296,8 @@ end: | |||
1241 | X509_free(s_cert2); | 1296 | X509_free(s_cert2); |
1242 | if (s_key2) | 1297 | if (s_key2) |
1243 | EVP_PKEY_free(s_key2); | 1298 | EVP_PKEY_free(s_key2); |
1299 | free(next_proto.data); | ||
1300 | free(alpn_ctx.data); | ||
1244 | if (bio_s_out != NULL) { | 1301 | if (bio_s_out != NULL) { |
1245 | BIO_free(bio_s_out); | 1302 | BIO_free(bio_s_out); |
1246 | bio_s_out = NULL; | 1303 | bio_s_out = NULL; |
@@ -1603,13 +1660,12 @@ init_ssl_connection(SSL * con) | |||
1603 | X509 *peer; | 1660 | X509 *peer; |
1604 | long verify_error; | 1661 | long verify_error; |
1605 | char buf[BUFSIZ]; | 1662 | char buf[BUFSIZ]; |
1606 | #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) | 1663 | #if !defined(OPENSSL_NO_NEXTPROTONEG) |
1607 | const unsigned char *next_proto_neg; | 1664 | const unsigned char *next_proto_neg; |
1608 | unsigned next_proto_neg_len; | 1665 | unsigned next_proto_neg_len; |
1609 | #endif | 1666 | #endif |
1610 | unsigned char *exportedkeymat; | 1667 | unsigned char *exportedkeymat; |
1611 | 1668 | ||
1612 | |||
1613 | i = SSL_accept(con); | 1669 | i = SSL_accept(con); |
1614 | if (i <= 0) { | 1670 | if (i <= 0) { |
1615 | if (BIO_sock_should_retry(i)) { | 1671 | if (BIO_sock_should_retry(i)) { |
@@ -1642,7 +1698,7 @@ init_ssl_connection(SSL * con) | |||
1642 | str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); | 1698 | str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); |
1643 | BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); | 1699 | BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); |
1644 | 1700 | ||
1645 | #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) | 1701 | #if !defined(OPENSSL_NO_NEXTPROTONEG) |
1646 | SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); | 1702 | SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); |
1647 | if (next_proto_neg) { | 1703 | if (next_proto_neg) { |
1648 | BIO_printf(bio_s_out, "NEXTPROTO is "); | 1704 | BIO_printf(bio_s_out, "NEXTPROTO is "); |