2012-06-05 18:26:04 +02:00
|
|
|
/*
|
2014-03-30 12:09:21 +02:00
|
|
|
* nghttp2 - HTTP/2 C Library
|
2012-06-05 18:26:04 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 2012 Tatsuhiro Tsujikawa
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
* a copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be
|
|
|
|
* included in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
2017-04-01 08:07:32 +02:00
|
|
|
#ifndef SHRPX_TLS_H
|
|
|
|
#define SHRPX_TLS_H
|
2012-06-05 18:26:04 +02:00
|
|
|
|
|
|
|
#include "shrpx.h"
|
|
|
|
|
2013-02-06 15:27:05 +01:00
|
|
|
#include <vector>
|
2015-03-30 16:20:40 +02:00
|
|
|
#include <mutex>
|
2013-02-06 15:27:05 +01:00
|
|
|
|
2012-06-05 18:26:04 +02:00
|
|
|
#include <openssl/ssl.h>
|
|
|
|
#include <openssl/err.h>
|
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
#include <ev.h>
|
2012-06-05 18:26:04 +02:00
|
|
|
|
2015-09-23 12:45:53 +02:00
|
|
|
#ifdef HAVE_NEVERBLEED
|
2018-06-09 09:21:30 +02:00
|
|
|
# include <neverbleed.h>
|
2015-09-23 12:45:53 +02:00
|
|
|
#endif // HAVE_NEVERBLEED
|
|
|
|
|
2016-02-21 07:28:11 +01:00
|
|
|
#include "network.h"
|
2017-02-16 14:46:22 +01:00
|
|
|
#include "shrpx_config.h"
|
2016-06-24 17:28:15 +02:00
|
|
|
#include "shrpx_router.h"
|
2016-02-21 07:28:11 +01:00
|
|
|
|
2012-06-05 18:26:04 +02:00
|
|
|
namespace shrpx {
|
|
|
|
|
|
|
|
class ClientHandler;
|
2015-02-11 11:18:41 +01:00
|
|
|
class Worker;
|
2014-10-13 14:09:00 +02:00
|
|
|
class DownstreamConnectionPool;
|
2015-07-09 19:52:11 +02:00
|
|
|
struct DownstreamAddr;
|
2016-02-07 09:51:53 +01:00
|
|
|
struct UpstreamAddr;
|
2012-06-05 18:26:04 +02:00
|
|
|
|
2017-04-01 08:07:32 +02:00
|
|
|
namespace tls {
|
2012-06-05 18:26:04 +02:00
|
|
|
|
2016-04-28 15:25:55 +02:00
|
|
|
struct TLSSessionCache {
|
|
|
|
// ASN1 representation of SSL_SESSION object. See
|
|
|
|
// i2d_SSL_SESSION(3SSL).
|
|
|
|
std::vector<uint8_t> session_data;
|
|
|
|
// The last time stamp when this cache entry is created or updated.
|
|
|
|
ev_tstamp last_updated;
|
|
|
|
};
|
|
|
|
|
2015-03-30 16:20:40 +02:00
|
|
|
// This struct stores the additional information per SSL_CTX. This is
|
|
|
|
// attached to SSL_CTX using SSL_CTX_set_app_data().
|
|
|
|
struct TLSContextData {
|
2016-10-08 12:03:21 +02:00
|
|
|
// SCT data formatted so that this can be directly sent as
|
|
|
|
// extension_data of signed_certificate_timestamp.
|
|
|
|
std::vector<uint8_t> sct_data;
|
2016-09-20 15:24:12 +02:00
|
|
|
#ifndef HAVE_ATOMIC_STD_SHARED_PTR
|
2015-03-30 16:20:40 +02:00
|
|
|
// Protects ocsp_data;
|
|
|
|
std::mutex mu;
|
2016-09-20 15:24:12 +02:00
|
|
|
#endif // !HAVE_ATOMIC_STD_SHARED_PTR
|
2015-06-04 17:18:29 +02:00
|
|
|
// OCSP response
|
2015-06-12 14:27:12 +02:00
|
|
|
std::shared_ptr<std::vector<uint8_t>> ocsp_data;
|
2015-03-30 16:20:40 +02:00
|
|
|
|
|
|
|
// Path to certificate file
|
|
|
|
const char *cert_file;
|
|
|
|
};
|
|
|
|
|
2015-01-12 14:47:30 +01:00
|
|
|
// Create server side SSL_CTX
|
2016-10-08 12:03:21 +02:00
|
|
|
SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
|
|
|
const std::vector<uint8_t> &sct_data
|
|
|
|
|
2015-09-23 12:45:53 +02:00
|
|
|
#ifdef HAVE_NEVERBLEED
|
|
|
|
,
|
|
|
|
neverbleed_t *nb
|
|
|
|
#endif // HAVE_NEVERBLEED
|
2017-11-23 06:19:12 +01:00
|
|
|
);
|
2012-06-05 18:26:04 +02:00
|
|
|
|
2016-02-28 08:56:14 +01:00
|
|
|
// Create client side SSL_CTX. This does not configure ALPN settings.
|
|
|
|
// |next_proto_select_cb| is for NPN.
|
2015-09-26 14:28:16 +02:00
|
|
|
SSL_CTX *create_ssl_client_context(
|
|
|
|
#ifdef HAVE_NEVERBLEED
|
2016-02-11 10:34:31 +01:00
|
|
|
neverbleed_t *nb,
|
2015-09-26 14:28:16 +02:00
|
|
|
#endif // HAVE_NEVERBLEED
|
2016-02-12 16:20:38 +01:00
|
|
|
const StringRef &cacert, const StringRef &cert_file,
|
2016-02-28 08:56:14 +01:00
|
|
|
const StringRef &private_key_file,
|
2016-02-11 10:34:31 +01:00
|
|
|
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
|
|
|
|
unsigned char *outlen, const unsigned char *in,
|
|
|
|
unsigned int inlen, void *arg));
|
2012-11-18 13:23:13 +01:00
|
|
|
|
2015-02-11 11:18:41 +01:00
|
|
|
ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr,
|
2016-02-07 09:51:53 +01:00
|
|
|
int addrlen, const UpstreamAddr *faddr);
|
2012-06-05 18:26:04 +02:00
|
|
|
|
2016-02-11 14:56:45 +01:00
|
|
|
// Check peer's certificate against given |address| and |host|.
|
|
|
|
int check_cert(SSL *ssl, const Address *addr, const StringRef &host);
|
2016-12-04 15:43:41 +01:00
|
|
|
// Check peer's certificate against given host name described in
|
|
|
|
// |addr| and numeric address in |raddr|. Note that |raddr| might not
|
|
|
|
// point to &addr->addr.
|
|
|
|
int check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr);
|
2012-11-22 13:46:15 +01:00
|
|
|
|
2016-06-24 17:28:15 +02:00
|
|
|
struct WildcardRevPrefix {
|
|
|
|
WildcardRevPrefix(const StringRef &prefix, size_t idx)
|
|
|
|
: prefix(std::begin(prefix), std::end(prefix)), idx(idx) {}
|
|
|
|
|
|
|
|
// "Prefix" of wildcard pattern. It is reversed from original form.
|
|
|
|
// For example, if the original wildcard is "test*.nghttp2.org",
|
|
|
|
// prefix would be "tset".
|
|
|
|
ImmutableString prefix;
|
|
|
|
// The index of SSL_CTX. See ConnectionHandler::get_ssl_ctx().
|
|
|
|
size_t idx;
|
2016-01-16 15:54:21 +01:00
|
|
|
};
|
|
|
|
|
2016-06-24 17:28:15 +02:00
|
|
|
struct WildcardPattern {
|
|
|
|
// Wildcard host sharing only suffix is probably rare, so we just do
|
|
|
|
// linear search.
|
|
|
|
std::vector<WildcardRevPrefix> rev_prefix;
|
2013-02-06 15:27:05 +01:00
|
|
|
};
|
|
|
|
|
2015-02-02 14:47:12 +01:00
|
|
|
class CertLookupTree {
|
|
|
|
public:
|
|
|
|
CertLookupTree();
|
|
|
|
|
2016-06-24 17:28:15 +02:00
|
|
|
// Adds hostname pattern |hostname| to the lookup tree, associating
|
|
|
|
// value |index|. When the queried host matches this pattern,
|
|
|
|
// |index| is returned. We support wildcard pattern. The left most
|
|
|
|
// '*' is considered as wildcard character, and it must match at
|
|
|
|
// least one character. If the same pattern has been already added,
|
2017-02-04 10:59:06 +01:00
|
|
|
// this function does not alter the tree, and returns the existing
|
|
|
|
// matching index.
|
2016-06-24 17:28:15 +02:00
|
|
|
//
|
|
|
|
// The caller should lower-case |hostname| since this function does
|
|
|
|
// do that, and lookup function performs case-sensitive match.
|
|
|
|
//
|
|
|
|
// TODO Treat wildcard pattern described as RFC 6125.
|
2017-02-04 10:59:06 +01:00
|
|
|
//
|
|
|
|
// This function returns the index. It returns -1 if it fails
|
|
|
|
// (e.g., hostname is too long). If the returned index equals to
|
|
|
|
// |index|, then hostname is added to the tree with the value
|
|
|
|
// |index|. If it is not -1, and does not equal to |index|, same
|
|
|
|
// hostname has already been added to the tree.
|
|
|
|
ssize_t add_cert(const StringRef &hostname, size_t index);
|
2016-06-24 17:28:15 +02:00
|
|
|
|
|
|
|
// Looks up index using the given |hostname|. The exact match takes
|
|
|
|
// precedence over wildcard match. For wildcard match, longest
|
|
|
|
// match (sum of matched suffix and prefix length in bytes) is
|
|
|
|
// preferred, breaking a tie with longer suffix.
|
|
|
|
//
|
|
|
|
// The caller should lower-case |hostname| since this function
|
|
|
|
// performs case-sensitive match.
|
|
|
|
ssize_t lookup(const StringRef &hostname);
|
|
|
|
|
|
|
|
// Dumps the contents of this lookup tree to stderr.
|
|
|
|
void dump() const;
|
2015-02-02 14:47:12 +01:00
|
|
|
|
|
|
|
private:
|
2016-06-24 17:28:15 +02:00
|
|
|
// Exact match
|
|
|
|
Router router_;
|
|
|
|
// Wildcard reversed suffix match. The returned index is into
|
|
|
|
// wildcard_patterns_.
|
|
|
|
Router rev_wildcard_router_;
|
|
|
|
// Stores wildcard suffix patterns.
|
|
|
|
std::vector<WildcardPattern> wildcard_patterns_;
|
2013-02-06 15:27:05 +01:00
|
|
|
};
|
|
|
|
|
2017-02-04 10:59:06 +01:00
|
|
|
// Adds hostnames in certificate in |ssl_ctx| to lookup tree |lt|.
|
|
|
|
// The subjectAltNames and commonName are considered as eligible
|
|
|
|
// hostname. If there is at least one dNSName in subjectAltNames,
|
|
|
|
// commonName is not considered. |ssl_ctx| is also added to
|
|
|
|
// |indexed_ssl_ctx|. This function returns 0 if it succeeds, or -1.
|
|
|
|
int cert_lookup_tree_add_ssl_ctx(
|
|
|
|
CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
|
|
|
SSL_CTX *ssl_ctx);
|
2013-02-06 15:27:05 +01:00
|
|
|
|
2016-03-24 16:02:07 +01:00
|
|
|
// Returns true if |proto| is included in the
|
2014-06-08 15:52:27 +02:00
|
|
|
// protocol list |protos|.
|
2016-10-02 15:19:31 +02:00
|
|
|
bool in_proto_list(const std::vector<StringRef> &protos,
|
2016-03-24 16:02:07 +01:00
|
|
|
const StringRef &proto);
|
2014-01-01 16:53:07 +01:00
|
|
|
|
2014-04-26 15:37:48 +02:00
|
|
|
// Returns true if security requirement for HTTP/2 is fulfilled.
|
|
|
|
bool check_http2_requirement(SSL *ssl);
|
|
|
|
|
2014-06-08 15:52:27 +02:00
|
|
|
// Returns SSL/TLS option mask to disable SSL/TLS protocol version not
|
|
|
|
// included in |tls_proto_list|. The returned mask can be directly
|
|
|
|
// passed to SSL_CTX_set_options().
|
2016-10-02 15:21:38 +02:00
|
|
|
long int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list);
|
2014-06-08 15:52:27 +02:00
|
|
|
|
2016-07-31 13:35:10 +02:00
|
|
|
int set_alpn_prefs(std::vector<unsigned char> &out,
|
2016-10-02 15:19:31 +02:00
|
|
|
const std::vector<StringRef> &protos);
|
2014-06-10 16:15:29 +02:00
|
|
|
|
2015-01-12 16:18:27 +01:00
|
|
|
// Setups server side SSL_CTX. This function inspects get_config()
|
|
|
|
// and if upstream_no_tls is true, returns nullptr. Otherwise
|
2015-02-11 11:18:41 +01:00
|
|
|
// construct default SSL_CTX. If subcerts are available
|
|
|
|
// (get_config()->subcerts), caller should provide CertLookupTree
|
2015-03-30 16:20:40 +02:00
|
|
|
// object as |cert_tree| parameter, otherwise SNI does not work. All
|
2017-02-04 10:59:06 +01:00
|
|
|
// the created SSL_CTX is stored into |all_ssl_ctx|. They are also
|
|
|
|
// added to |indexed_ssl_ctx|. |cert_tree| uses its index to
|
|
|
|
// associate hostname to the SSL_CTX.
|
|
|
|
SSL_CTX *
|
|
|
|
setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
|
|
|
std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
|
|
|
|
CertLookupTree *cert_tree
|
2015-09-23 12:45:53 +02:00
|
|
|
#ifdef HAVE_NEVERBLEED
|
2017-02-04 10:59:06 +01:00
|
|
|
,
|
|
|
|
neverbleed_t *nb
|
2015-09-23 12:45:53 +02:00
|
|
|
#endif // HAVE_NEVERBLEED
|
2017-11-23 06:19:12 +01:00
|
|
|
);
|
2015-01-12 16:18:27 +01:00
|
|
|
|
2016-06-03 12:13:02 +02:00
|
|
|
// Setups client side SSL_CTX.
|
2016-02-11 10:34:31 +01:00
|
|
|
SSL_CTX *setup_downstream_client_ssl_context(
|
2015-09-26 14:28:16 +02:00
|
|
|
#ifdef HAVE_NEVERBLEED
|
|
|
|
neverbleed_t *nb
|
|
|
|
#endif // HAVE_NEVERBLEED
|
2017-11-23 06:19:12 +01:00
|
|
|
);
|
2015-01-12 16:18:27 +01:00
|
|
|
|
2016-02-28 08:56:14 +01:00
|
|
|
// Sets ALPN settings in |SSL| suitable for HTTP/2 use.
|
|
|
|
void setup_downstream_http2_alpn(SSL *ssl);
|
|
|
|
// Sets ALPN settings in |SSL| suitable for HTTP/1.1 use.
|
|
|
|
void setup_downstream_http1_alpn(SSL *ssl);
|
|
|
|
|
2015-02-11 11:18:41 +01:00
|
|
|
// Creates CertLookupTree. If frontend is configured not to use TLS,
|
|
|
|
// this function returns nullptr.
|
2016-06-25 16:47:22 +02:00
|
|
|
std::unique_ptr<CertLookupTree> create_cert_lookup_tree();
|
2015-02-11 11:18:41 +01:00
|
|
|
|
2015-08-09 11:33:49 +02:00
|
|
|
SSL *create_ssl(SSL_CTX *ssl_ctx);
|
2015-07-25 15:22:17 +02:00
|
|
|
|
2016-03-23 15:56:09 +01:00
|
|
|
// Returns true if SSL/TLS is enabled on upstream
|
2017-02-16 14:46:22 +01:00
|
|
|
bool upstream_tls_enabled(const ConnectionConfig &connconf);
|
2016-03-23 15:56:09 +01:00
|
|
|
|
2016-03-24 15:16:20 +01:00
|
|
|
// Performs TLS hostname match. |pattern| can contain wildcard
|
|
|
|
// character '*', which matches prefix of target hostname. There are
|
|
|
|
// several restrictions to make wildcard work. The matching algorithm
|
|
|
|
// is based on RFC 6125.
|
|
|
|
bool tls_hostname_match(const StringRef &pattern, const StringRef &hostname);
|
2016-01-16 15:54:21 +01:00
|
|
|
|
2017-03-28 14:06:28 +02:00
|
|
|
// Caches |session|. |session| is serialized into ASN1
|
|
|
|
// representation, and stored. |t| is used as a time stamp.
|
|
|
|
// Depending on the existing cache's time stamp, |session| might not
|
|
|
|
// be cached.
|
|
|
|
void try_cache_tls_session(TLSSessionCache *cache, SSL_SESSION *session,
|
|
|
|
ev_tstamp t);
|
2016-02-21 08:35:43 +01:00
|
|
|
|
|
|
|
// Returns cached session associated |addr|. If no cache entry is
|
|
|
|
// found associated to |addr|, nullptr will be returned.
|
2016-04-28 15:25:55 +02:00
|
|
|
SSL_SESSION *reuse_tls_session(const TLSSessionCache &addr);
|
2016-02-21 08:35:43 +01:00
|
|
|
|
2016-06-25 16:35:12 +02:00
|
|
|
// Loads certificate form file |filename|. The caller should delete
|
|
|
|
// the returned object using X509_free().
|
|
|
|
X509 *load_certificate(const char *filename);
|
|
|
|
|
2017-02-13 15:34:45 +01:00
|
|
|
// Returns TLS version from |v|. The returned value is defined in
|
|
|
|
// OpenSSL header file. This function returns -1 if |v| is not valid
|
|
|
|
// TLS version string.
|
|
|
|
int proto_version_from_string(const StringRef &v);
|
|
|
|
|
2017-05-24 15:20:08 +02:00
|
|
|
// Verifies OCSP response |ocsp_resp| of length |ocsp_resplen|. This
|
|
|
|
// function returns 0 if it succeeds, or -1.
|
|
|
|
int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
|
|
|
|
size_t ocsp_resplen);
|
|
|
|
|
2017-10-31 13:28:16 +01:00
|
|
|
// Stores fingerprint of |x| in |dst| of length |dstlen|. |md|
|
|
|
|
// specifies hash function to use, and |dstlen| must be large enough
|
|
|
|
// to include hash value (e.g., 32 bytes for SHA-256). This function
|
|
|
|
// returns the number of bytes written in |dst|, or -1.
|
|
|
|
ssize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x,
|
|
|
|
const EVP_MD *md);
|
2017-10-28 17:25:20 +02:00
|
|
|
|
|
|
|
// Returns subject name of |x|. If this function fails to get subject
|
|
|
|
// name, it returns an empty string.
|
|
|
|
StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x);
|
|
|
|
|
2017-11-15 15:41:47 +01:00
|
|
|
// Returns issuer name of |x|. If this function fails to get issuer
|
|
|
|
// name, it returns an empty string.
|
|
|
|
StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x);
|
|
|
|
|
2017-11-16 16:02:33 +01:00
|
|
|
// Returns serial number of |x|. If this function fails to get serial
|
2017-11-16 13:11:38 +01:00
|
|
|
// number, it returns an empty string. number
|
|
|
|
StringRef get_x509_serial(BlockAllocator &balloc, X509 *x);
|
|
|
|
|
2018-02-03 09:58:49 +01:00
|
|
|
// Fills NotBefore of |x| in |t|. This function returns 0 if it
|
|
|
|
// succeeds, or -1.
|
|
|
|
int get_x509_not_before(time_t &t, X509 *x);
|
|
|
|
|
|
|
|
// Fills NotAfter of |x| in |t|. This function returns 0 if it
|
|
|
|
// succeeds, or -1.
|
|
|
|
int get_x509_not_after(time_t &t, X509 *x);
|
|
|
|
|
2017-04-01 08:07:32 +02:00
|
|
|
} // namespace tls
|
2012-06-05 18:26:04 +02:00
|
|
|
|
|
|
|
} // namespace shrpx
|
|
|
|
|
2017-04-01 08:07:32 +02:00
|
|
|
#endif // SHRPX_TLS_H
|