• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #ifndef SHRPX_TLS_H
26 #define SHRPX_TLS_H
27 
28 #include "shrpx.h"
29 
30 #include <vector>
31 #include <mutex>
32 
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 
36 #include <ev.h>
37 
38 #ifdef HAVE_NEVERBLEED
39 #  include <neverbleed.h>
40 #endif // HAVE_NEVERBLEED
41 
42 #include "network.h"
43 #include "shrpx_config.h"
44 #include "shrpx_router.h"
45 
46 namespace shrpx {
47 
48 class ClientHandler;
49 class Worker;
50 class DownstreamConnectionPool;
51 struct DownstreamAddr;
52 struct UpstreamAddr;
53 
54 namespace tls {
55 
56 struct TLSSessionCache {
57   // ASN1 representation of SSL_SESSION object.  See
58   // i2d_SSL_SESSION(3SSL).
59   std::vector<uint8_t> session_data;
60   // The last time stamp when this cache entry is created or updated.
61   std::chrono::steady_clock::time_point last_updated;
62 };
63 
64 // This struct stores the additional information per SSL_CTX.  This is
65 // attached to SSL_CTX using SSL_CTX_set_app_data().
66 struct TLSContextData {
67   // SCT data formatted so that this can be directly sent as
68   // extension_data of signed_certificate_timestamp.
69   std::vector<uint8_t> sct_data;
70 #ifndef HAVE_ATOMIC_STD_SHARED_PTR
71   // Protects ocsp_data;
72   std::mutex mu;
73 #endif // !HAVE_ATOMIC_STD_SHARED_PTR
74   // OCSP response
75   std::shared_ptr<std::vector<uint8_t>> ocsp_data;
76 
77   // Path to certificate file
78   const char *cert_file;
79 };
80 
81 // Create server side SSL_CTX
82 SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
83                             const std::vector<uint8_t> &sct_data
84 
85 #ifdef HAVE_NEVERBLEED
86                             ,
87                             neverbleed_t *nb
88 #endif // HAVE_NEVERBLEED
89 );
90 
91 // Create client side SSL_CTX.  This does not configure ALPN settings.
92 // |next_proto_select_cb| is for NPN.
93 SSL_CTX *create_ssl_client_context(
94 #ifdef HAVE_NEVERBLEED
95     neverbleed_t *nb,
96 #endif // HAVE_NEVERBLEED
97     const StringRef &cacert, const StringRef &cert_file,
98     const StringRef &private_key_file,
99     int (*next_proto_select_cb)(SSL *s, unsigned char **out,
100                                 unsigned char *outlen, const unsigned char *in,
101                                 unsigned int inlen, void *arg));
102 
103 #ifdef ENABLE_HTTP3
104 SSL_CTX *create_quic_ssl_client_context(
105 #  ifdef HAVE_NEVERBLEED
106     neverbleed_t *nb,
107 #  endif // HAVE_NEVERBLEED
108     const StringRef &cacert, const StringRef &cert_file,
109     const StringRef &private_key_file,
110     int (*next_proto_select_cb)(SSL *s, unsigned char **out,
111                                 unsigned char *outlen, const unsigned char *in,
112                                 unsigned int inlen, void *arg));
113 #endif // ENABLE_HTTP3
114 
115 ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr,
116                                  int addrlen, const UpstreamAddr *faddr);
117 
118 // Check peer's certificate against given |address| and |host|.
119 int check_cert(SSL *ssl, const Address *addr, const StringRef &host);
120 // Check peer's certificate against given host name described in
121 // |addr| and numeric address in |raddr|.  Note that |raddr| might not
122 // point to &addr->addr.
123 int check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr);
124 
125 // Verify |cert| using numeric IP address.  |hostname| and |addr|
126 // should contain the same numeric IP address.  This function returns
127 // 0 if it succeeds, or -1.
128 int verify_numeric_hostname(X509 *cert, const StringRef &hostname,
129                             const Address *addr);
130 
131 // Verify |cert| using DNS name hostname.  This function returns 0 if
132 // it succeeds, or -1.
133 int verify_dns_hostname(X509 *cert, const StringRef &hostname);
134 
135 struct WildcardRevPrefix {
WildcardRevPrefixWildcardRevPrefix136   WildcardRevPrefix(const StringRef &prefix, size_t idx)
137       : prefix(std::begin(prefix), std::end(prefix)), idx(idx) {}
138 
139   // "Prefix" of wildcard pattern.  It is reversed from original form.
140   // For example, if the original wildcard is "test*.nghttp2.org",
141   // prefix would be "tset".
142   ImmutableString prefix;
143   // The index of SSL_CTX.  See ConnectionHandler::get_ssl_ctx().
144   size_t idx;
145 };
146 
147 struct WildcardPattern {
148   // Wildcard host sharing only suffix is probably rare, so we just do
149   // linear search.
150   std::vector<WildcardRevPrefix> rev_prefix;
151 };
152 
153 class CertLookupTree {
154 public:
155   CertLookupTree();
156 
157   // Adds hostname pattern |hostname| to the lookup tree, associating
158   // value |index|.  When the queried host matches this pattern,
159   // |index| is returned.  We support wildcard pattern.  The left most
160   // '*' is considered as wildcard character, and it must match at
161   // least one character.  If the same pattern has been already added,
162   // this function does not alter the tree, and returns the existing
163   // matching index.
164   //
165   // The caller should lower-case |hostname| since this function does
166   // do that, and lookup function performs case-sensitive match.
167   //
168   // TODO Treat wildcard pattern described as RFC 6125.
169   //
170   // This function returns the index.  It returns -1 if it fails
171   // (e.g., hostname is too long).  If the returned index equals to
172   // |index|, then hostname is added to the tree with the value
173   // |index|.  If it is not -1, and does not equal to |index|, same
174   // hostname has already been added to the tree.
175   ssize_t add_cert(const StringRef &hostname, size_t index);
176 
177   // Looks up index using the given |hostname|.  The exact match takes
178   // precedence over wildcard match.  For wildcard match, longest
179   // match (sum of matched suffix and prefix length in bytes) is
180   // preferred, breaking a tie with longer suffix.
181   //
182   // The caller should lower-case |hostname| since this function
183   // performs case-sensitive match.
184   ssize_t lookup(const StringRef &hostname);
185 
186   // Dumps the contents of this lookup tree to stderr.
187   void dump() const;
188 
189 private:
190   // Exact match
191   Router router_;
192   // Wildcard reversed suffix match.  The returned index is into
193   // wildcard_patterns_.
194   Router rev_wildcard_router_;
195   // Stores wildcard suffix patterns.
196   std::vector<WildcardPattern> wildcard_patterns_;
197 };
198 
199 // Adds hostnames in certificate in |ssl_ctx| to lookup tree |lt|.
200 // The subjectAltNames and commonName are considered as eligible
201 // hostname.  If there is at least one dNSName in subjectAltNames,
202 // commonName is not considered.  |ssl_ctx| is also added to
203 // |indexed_ssl_ctx|.  This function returns 0 if it succeeds, or -1.
204 int cert_lookup_tree_add_ssl_ctx(
205     CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
206     SSL_CTX *ssl_ctx);
207 
208 // Returns true if |proto| is included in the
209 // protocol list |protos|.
210 bool in_proto_list(const std::vector<StringRef> &protos,
211                    const StringRef &proto);
212 
213 // Returns true if security requirement for HTTP/2 is fulfilled.
214 bool check_http2_requirement(SSL *ssl);
215 
216 // Returns SSL/TLS option mask to disable SSL/TLS protocol version not
217 // included in |tls_proto_list|.  The returned mask can be directly
218 // passed to SSL_CTX_set_options().
219 long int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list);
220 
221 int set_alpn_prefs(std::vector<unsigned char> &out,
222                    const std::vector<StringRef> &protos);
223 
224 // Setups server side SSL_CTX.  This function inspects get_config()
225 // and if upstream_no_tls is true, returns nullptr.  Otherwise
226 // construct default SSL_CTX.  If subcerts are available
227 // (get_config()->subcerts), caller should provide CertLookupTree
228 // object as |cert_tree| parameter, otherwise SNI does not work.  All
229 // the created SSL_CTX is stored into |all_ssl_ctx|.  They are also
230 // added to |indexed_ssl_ctx|.  |cert_tree| uses its index to
231 // associate hostname to the SSL_CTX.
232 SSL_CTX *
233 setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
234                          std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
235                          CertLookupTree *cert_tree
236 #ifdef HAVE_NEVERBLEED
237                          ,
238                          neverbleed_t *nb
239 #endif // HAVE_NEVERBLEED
240 );
241 
242 #ifdef ENABLE_HTTP3
243 SSL_CTX *setup_quic_server_ssl_context(
244     std::vector<SSL_CTX *> &all_ssl_ctx,
245     std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
246     CertLookupTree *cert_tree
247 #  ifdef HAVE_NEVERBLEED
248     ,
249     neverbleed_t *nb
250 #  endif // HAVE_NEVERBLEED
251 );
252 #endif // ENABLE_HTTP3
253 
254 // Setups client side SSL_CTX.
255 SSL_CTX *setup_downstream_client_ssl_context(
256 #ifdef HAVE_NEVERBLEED
257     neverbleed_t *nb
258 #endif // HAVE_NEVERBLEED
259 );
260 
261 // Sets ALPN settings in |SSL| suitable for HTTP/2 use.
262 void setup_downstream_http2_alpn(SSL *ssl);
263 // Sets ALPN settings in |SSL| suitable for HTTP/1.1 use.
264 void setup_downstream_http1_alpn(SSL *ssl);
265 
266 // Creates CertLookupTree.  If frontend is configured not to use TLS,
267 // this function returns nullptr.
268 std::unique_ptr<CertLookupTree> create_cert_lookup_tree();
269 
270 SSL *create_ssl(SSL_CTX *ssl_ctx);
271 
272 // Returns true if SSL/TLS is enabled on upstream
273 bool upstream_tls_enabled(const ConnectionConfig &connconf);
274 
275 // Performs TLS hostname match.  |pattern| can contain wildcard
276 // character '*', which matches prefix of target hostname.  There are
277 // several restrictions to make wildcard work.  The matching algorithm
278 // is based on RFC 6125.
279 bool tls_hostname_match(const StringRef &pattern, const StringRef &hostname);
280 
281 // Caches |session|.  |session| is serialized into ASN1
282 // representation, and stored.  |t| is used as a time stamp.
283 // Depending on the existing cache's time stamp, |session| might not
284 // be cached.
285 void try_cache_tls_session(TLSSessionCache *cache, SSL_SESSION *session,
286                            const std::chrono::steady_clock::time_point &t);
287 
288 // Returns cached session associated |addr|.  If no cache entry is
289 // found associated to |addr|, nullptr will be returned.
290 SSL_SESSION *reuse_tls_session(const TLSSessionCache &addr);
291 
292 // Loads certificate form file |filename|.  The caller should delete
293 // the returned object using X509_free().
294 X509 *load_certificate(const char *filename);
295 
296 // Returns TLS version from |v|.  The returned value is defined in
297 // OpenSSL header file.  This function returns -1 if |v| is not valid
298 // TLS version string.
299 int proto_version_from_string(const StringRef &v);
300 
301 // Verifies OCSP response |ocsp_resp| of length |ocsp_resplen|.  This
302 // function returns 0 if it succeeds, or -1.
303 int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
304                          size_t ocsp_resplen);
305 
306 // Stores fingerprint of |x| in |dst| of length |dstlen|.  |md|
307 // specifies hash function to use, and |dstlen| must be large enough
308 // to include hash value (e.g., 32 bytes for SHA-256).  This function
309 // returns the number of bytes written in |dst|, or -1.
310 ssize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x,
311                              const EVP_MD *md);
312 
313 // Returns subject name of |x|.  If this function fails to get subject
314 // name, it returns an empty string.
315 StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x);
316 
317 // Returns issuer name of |x|.  If this function fails to get issuer
318 // name, it returns an empty string.
319 StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x);
320 
321 // Returns serial number of |x|.  If this function fails to get serial
322 // number, it returns an empty string.  number
323 StringRef get_x509_serial(BlockAllocator &balloc, X509 *x);
324 
325 // Fills NotBefore of |x| in |t|.  This function returns 0 if it
326 // succeeds, or -1.
327 int get_x509_not_before(time_t &t, X509 *x);
328 
329 // Fills NotAfter of |x| in |t|.  This function returns 0 if it
330 // succeeds, or -1.
331 int get_x509_not_after(time_t &t, X509 *x);
332 
333 } // namespace tls
334 
335 } // namespace shrpx
336 
337 #endif // SHRPX_TLS_H
338