ssl-http2.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. *
  21. * Some or all of this file is based on code from nghttp2, which has the
  22. * following license. Since it's more liberal than lws license, you're also
  23. * at liberty to get the original code from
  24. * https://github.com/tatsuhiro-t/nghttp2 under his liberal terms alone.
  25. *
  26. * nghttp2 - HTTP/2.0 C Library
  27. *
  28. * Copyright (c) 2012 Tatsuhiro Tsujikawa
  29. *
  30. * Permission is hereby granted, free of charge, to any person obtaining
  31. * a copy of this software and associated documentation files (the
  32. * "Software"), to deal in the Software without restriction, including
  33. * without limitation the rights to use, copy, modify, merge, publish,
  34. * distribute, sublicense, and/or sell copies of the Software, and to
  35. * permit persons to whom the Software is furnished to do so, subject to
  36. * the following conditions:
  37. *
  38. * The above copyright notice and this permission notice shall be
  39. * included in all copies or substantial portions of the Software.
  40. *
  41. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  42. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  43. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  44. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  45. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  46. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  47. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. */
  49. #include "private-libwebsockets.h"
  50. #ifndef LWS_NO_SERVER
  51. #ifdef LWS_OPENSSL_SUPPORT
  52. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  53. struct alpn_ctx {
  54. unsigned char *data;
  55. unsigned short len;
  56. };
  57. static int
  58. npn_cb(SSL *s, const unsigned char **data, unsigned int *len, void *arg)
  59. {
  60. struct alpn_ctx *alpn_ctx = arg;
  61. lwsl_info("%s\n", __func__);
  62. *data = alpn_ctx->data;
  63. *len = alpn_ctx->len;
  64. return SSL_TLSEXT_ERR_OK;
  65. }
  66. static int
  67. alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
  68. const unsigned char *in, unsigned int inlen, void *arg)
  69. {
  70. struct alpn_ctx *alpn_ctx = arg;
  71. if (SSL_select_next_proto((unsigned char **)out, outlen, alpn_ctx->data,
  72. alpn_ctx->len, in, inlen) !=
  73. OPENSSL_NPN_NEGOTIATED)
  74. return SSL_TLSEXT_ERR_NOACK;
  75. return SSL_TLSEXT_ERR_OK;
  76. }
  77. #endif
  78. LWS_VISIBLE void
  79. lws_context_init_http2_ssl(struct lws_vhost *vhost)
  80. {
  81. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  82. static struct alpn_ctx protos = { (unsigned char *)"\x02h2"
  83. "\x08http/1.1", 6 + 9 };
  84. SSL_CTX_set_next_protos_advertised_cb(vhost->ssl_ctx, npn_cb, &protos);
  85. // ALPN selection callback
  86. SSL_CTX_set_alpn_select_cb(vhost->ssl_ctx, alpn_cb, &protos);
  87. lwsl_notice(" HTTP2 / ALPN enabled\n");
  88. #else
  89. lwsl_notice(
  90. " HTTP2 / ALPN configured but not supported by OpenSSL 0x%lx\n",
  91. OPENSSL_VERSION_NUMBER);
  92. #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
  93. }
  94. void lws_http2_configure_if_upgraded(struct lws *wsi)
  95. {
  96. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  97. struct allocated_headers *ah;
  98. const char *method = "alpn";
  99. const unsigned char *name;
  100. unsigned len;
  101. SSL_get0_alpn_selected(wsi->ssl, &name, &len);
  102. if (!len) {
  103. SSL_get0_next_proto_negotiated(wsi->ssl, &name, &len);
  104. method = "npn";
  105. }
  106. if (!len) {
  107. lwsl_info("no npn/alpn upgrade\n");
  108. return;
  109. }
  110. (void)method;
  111. lwsl_info("negotiated %s using %s\n", name, method);
  112. wsi->use_ssl = 1;
  113. if (strncmp((char *)name, "http/1.1", 8) == 0)
  114. return;
  115. /* http2 */
  116. /* adopt the header info */
  117. ah = wsi->u.hdr.ah;
  118. lws_union_transition(wsi, LWSCM_HTTP2_SERVING);
  119. wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE;
  120. /* http2 union member has http union struct at start */
  121. wsi->u.http.ah = ah;
  122. lws_http2_init(&wsi->u.http2.peer_settings);
  123. lws_http2_init(&wsi->u.http2.my_settings);
  124. /* HTTP2 union */
  125. #endif
  126. }
  127. #endif
  128. #endif