summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLu <[email protected]>2018-08-15 20:58:55 +0800
committerLu <[email protected]>2018-08-15 20:58:55 +0800
commit0185ccff6675752c99a4a03c3d4ff72e18ab306a (patch)
treeca47e4181cdb262db5e89e4e314f1e18c372d497 /src
parent143373018ef0443cf8c02b7f5bae8a393bfac819 (diff)
增加源站证书有效性校验功能,关闭根据SNI添加SAN证书字段的功能。
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/cert.cc513
-rw-r--r--src/cert.h53
-rw-r--r--src/main.cc110
-rw-r--r--src/opts.cc98
-rw-r--r--src/opts.h11
-rw-r--r--src/pxyconn.cc35
-rw-r--r--src/pxyconn.h5
8 files changed, 475 insertions, 355 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8f6c432..05de6c5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,17 +7,16 @@ add_library(tfe-library base64.cc build.cc cache.cc cachemgr.cc cachessess.cc co
target_compile_definitions(tfe-library PUBLIC -DELPP_THREAD_SAFE -DELPP_FEATURE_ALL)
target_link_libraries(tfe-library
- openssl-crypto-static
openssl-ssl-static
+ openssl-crypto-static
pthread
libevent-static
libevent-static-openssl
libevent-static-pthreads
http-parser-static
- nghttp2-static
MESA_prof_load-static
MESA_field_stat2
- jsoncpp rdkafka pcrecpp)
+ jsoncpp rdkafka pcrecpp dl)
target_link_libraries(tfe-library maatframe MESA_handle_logger)
diff --git a/src/cert.cc b/src/cert.cc
index 8a5ba5f..ac50e5c 100644
--- a/src/cert.cc
+++ b/src/cert.cc
@@ -27,8 +27,8 @@
*/
#include "cert.h"
-
#include "ssl.h"
+#include "easylogging++.h"
#include <string.h>
@@ -39,17 +39,18 @@
cert_t *
cert_new(void)
{
- cert_t *c;
+ cert_t * c;
- if (!(c = (cert_t *)malloc(sizeof(cert_t))))
- return NULL;
- memset(c, 0, sizeof(cert_t));
- if (pthread_mutex_init(&c->mutex, NULL)) {
- free(c);
- return NULL;
- }
- c->references = 1;
- return c;
+ if (!(c = (cert_t *) malloc(sizeof(cert_t))))
+ return NULL;
+ memset(c, 0, sizeof(cert_t));
+ if (pthread_mutex_init(&c->mutex, NULL))
+ {
+ free(c);
+ return NULL;
+ }
+ c->references = 1;
+ return c;
}
/*
@@ -57,21 +58,22 @@ cert_new(void)
* incremented, stack will not be duplicated.
*/
cert_t *
-cert_new3(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
+cert_new3(EVP_PKEY * key, X509 * crt, STACK_OF(X509) * chain)
{
- cert_t *c;
+ cert_t * c;
- if (!(c = (cert_t *)malloc(sizeof(cert_t))))
- return NULL;
- if (pthread_mutex_init(&c->mutex, NULL)) {
- free(c);
- return NULL;
- }
- c->key = key;
- c->crt = crt;
- c->chain = chain;
- c->references = 1;
- return c;
+ if (!(c = (cert_t *) malloc(sizeof(cert_t))))
+ return NULL;
+ if (pthread_mutex_init(&c->mutex, NULL))
+ {
+ free(c);
+ return NULL;
+ }
+ c->key = key;
+ c->crt = crt;
+ c->chain = chain;
+ c->references = 1;
+ return c;
}
/*
@@ -79,143 +81,390 @@ cert_new3(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
* incremented, stack will be duplicated.
*/
cert_t *
-cert_new3_copy(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
-{
- cert_t *c;
-
- if (!(c = (cert_t *)malloc(sizeof(cert_t))))
- return NULL;
- if (pthread_mutex_init(&c->mutex, NULL)) {
- free(c);
- return NULL;
- }
- c->key = key;
- ssl_key_refcount_inc(c->key);
- c->crt = crt;
- ssl_x509_refcount_inc(c->crt);
- c->chain = sk_X509_dup(chain);
- for (int i = 0; i < sk_X509_num(c->chain); i++) {
- ssl_x509_refcount_inc(sk_X509_value(c->chain, i));
- }
- c->references = 1;
- return c;
+cert_new3_copy(EVP_PKEY * key, X509 * crt, STACK_OF(X509) * chain)
+{
+ cert_t * c;
+
+ if (!(c = (cert_t *) malloc(sizeof(cert_t))))
+ return NULL;
+ if (pthread_mutex_init(&c->mutex, NULL))
+ {
+ free(c);
+ return NULL;
+ }
+ c->key = key;
+ ssl_key_refcount_inc(c->key);
+ c->crt = crt;
+ ssl_x509_refcount_inc(c->crt);
+ c->chain = sk_X509_dup(chain);
+ for (int i = 0; i < sk_X509_num(c->chain); i++)
+ {
+ ssl_x509_refcount_inc(sk_X509_value(c->chain, i));
+ }
+ c->references = 1;
+ return c;
}
/*
* Load cert_t from file.
*/
cert_t *
-cert_new_load(const char *filename)
-{
- cert_t *c;
-
- if (!(c = (cert_t *)malloc(sizeof(cert_t))))
- return NULL;
- memset(c, 0, sizeof(cert_t));
- if (pthread_mutex_init(&c->mutex, NULL)) {
- free(c);
- return NULL;
- }
-
- if (ssl_x509chain_load(&c->crt, &c->chain, filename) == -1) {
- free(c);
- return NULL;
- }
- c->key = ssl_key_load(filename);
- if (!c->key) {
- X509_free(c->crt);
- if (c->chain) {
- sk_X509_pop_free(c->chain, X509_free);
- }
- free(c);
- return NULL;
- }
- c->references = 1;
- return c;
+cert_new_load(const char * filename)
+{
+ cert_t * c;
+
+ if (!(c = (cert_t *) malloc(sizeof(cert_t))))
+ return NULL;
+ memset(c, 0, sizeof(cert_t));
+ if (pthread_mutex_init(&c->mutex, NULL))
+ {
+ free(c);
+ return NULL;
+ }
+
+ if (ssl_x509chain_load(&c->crt, &c->chain, filename) == -1)
+ {
+ free(c);
+ return NULL;
+ }
+ c->key = ssl_key_load(filename);
+ if (!c->key)
+ {
+ X509_free(c->crt);
+ if (c->chain)
+ {
+ sk_X509_pop_free(c->chain, X509_free);
+ }
+ free(c);
+ return NULL;
+ }
+ c->references = 1;
+ return c;
}
/*
* Increment reference count.
*/
void
-cert_refcount_inc(cert_t *c)
+cert_refcount_inc(cert_t * c)
{
- pthread_mutex_lock(&c->mutex);
- c->references++;
- pthread_mutex_unlock(&c->mutex);
+ pthread_mutex_lock(&c->mutex);
+ c->references++;
+ pthread_mutex_unlock(&c->mutex);
}
/*
* Thread-safe setter functions; they copy the value (refcounts are inc'd).
*/
void
-cert_set_key(cert_t *c, EVP_PKEY *key)
-{
- pthread_mutex_lock(&c->mutex);
- if (c->key) {
- EVP_PKEY_free(c->key);
- }
- c->key = key;
- if (c->key) {
- ssl_key_refcount_inc(c->key);
- }
- pthread_mutex_unlock(&c->mutex);
+cert_set_key(cert_t * c, EVP_PKEY * key)
+{
+ pthread_mutex_lock(&c->mutex);
+ if (c->key)
+ {
+ EVP_PKEY_free(c->key);
+ }
+ c->key = key;
+ if (c->key)
+ {
+ ssl_key_refcount_inc(c->key);
+ }
+ pthread_mutex_unlock(&c->mutex);
}
void
-cert_set_crt(cert_t *c, X509 *crt)
-{
- pthread_mutex_lock(&c->mutex);
- if (c->crt) {
- X509_free(c->crt);
- }
- c->crt = crt;
- if (c->crt) {
- ssl_x509_refcount_inc(c->crt);
- }
- pthread_mutex_unlock(&c->mutex);
+cert_set_crt(cert_t * c, X509 * crt)
+{
+ pthread_mutex_lock(&c->mutex);
+ if (c->crt)
+ {
+ X509_free(c->crt);
+ }
+ c->crt = crt;
+ if (c->crt)
+ {
+ ssl_x509_refcount_inc(c->crt);
+ }
+ pthread_mutex_unlock(&c->mutex);
}
void
-cert_set_chain(cert_t *c, STACK_OF(X509) *chain)
-{
- pthread_mutex_lock(&c->mutex);
- if (c->chain) {
- sk_X509_pop_free(c->chain, X509_free);
- }
- if (chain) {
- c->chain = sk_X509_dup(chain);
- for (int i = 0; i < sk_X509_num(c->chain); i++) {
- ssl_x509_refcount_inc(sk_X509_value(c->chain, i));
- }
- } else {
- c->chain = NULL;
- }
- pthread_mutex_unlock(&c->mutex);
+cert_set_chain(cert_t * c, STACK_OF(X509) * chain)
+{
+ pthread_mutex_lock(&c->mutex);
+ if (c->chain)
+ {
+ sk_X509_pop_free(c->chain, X509_free);
+ }
+ if (chain)
+ {
+ c->chain = sk_X509_dup(chain);
+ for (int i = 0; i < sk_X509_num(c->chain); i++)
+ {
+ ssl_x509_refcount_inc(sk_X509_value(c->chain, i));
+ }
+ }
+ else
+ {
+ c->chain = NULL;
+ }
+ pthread_mutex_unlock(&c->mutex);
}
/*
* Free cert including internal objects.
*/
void
-cert_free(cert_t *c)
-{
- pthread_mutex_lock(&c->mutex);
- c->references--;
- if (c->references) {
- pthread_mutex_unlock(&c->mutex);
- return;
- }
- pthread_mutex_unlock(&c->mutex);
- pthread_mutex_destroy(&c->mutex);
- if (c->key) {
- EVP_PKEY_free(c->key);
- }
- if (c->crt) {
- X509_free(c->crt);
- }
- if (c->chain) {
- sk_X509_pop_free(c->chain, X509_free);
- }
- free(c);
+cert_free(cert_t * c)
+{
+ pthread_mutex_lock(&c->mutex);
+ c->references--;
+ if (c->references)
+ {
+ pthread_mutex_unlock(&c->mutex);
+ return;
+ }
+ pthread_mutex_unlock(&c->mutex);
+ pthread_mutex_destroy(&c->mutex);
+ if (c->key)
+ {
+ EVP_PKEY_free(c->key);
+ }
+ if (c->crt)
+ {
+ X509_free(c->crt);
+ }
+ if (c->chain)
+ {
+ sk_X509_pop_free(c->chain, X509_free);
+ }
+ free(c);
+}
+
+#include <memory>
+#include <exception>
+#include <system_error>
+#include "cfgparser.h"
+
+void __throw_ssl_load_exception(int err, std::string what)
+{
+ /* 系统错误 */
+ if (err)
+ {
+ throw std::system_error(err, std::generic_category(), what);
+ }
+
+ /* SSL错误 */
+ std::string ssl_err_info;
+ ERR_print_errors_cb([](const char * str, size_t len, void * u) -> int
+ {
+ std::string * __str_err_info_ptr = static_cast<std::string *>(u);
+ *__str_err_info_ptr = std::string(str, len);
+ return 0;
+ }, static_cast<void *>(&ssl_err_info));
+
+ throw std::runtime_error(what + ":" + ssl_err_info);
+}
+
+void __debug_dump_crt(const char * str_leader, X509 * crt)
+{
+ LOG(INFO) << str_leader;
+ char * sj = ssl_x509_subject(crt);
+ if (sj)
+ {
+ LOG(INFO) << string_format("Subject DN: %s", sj);
+ free(sj);
+ }
+
+ char * names = ssl_x509_names_to_str(crt);
+ if (names)
+ {
+ LOG(INFO) << string_format("Common Names: %s", names);
+ free(names);
+ }
+
+ char * fpr;
+ if (!(fpr = ssl_x509_fingerprint(crt, 1)))
+ {
+ LOG(INFO) << string_format("Warning: Error generating X509 fingerprint");
+ }
+ else
+ {
+ LOG(INFO) << string_format("Fingerprint: %s\n", fpr);
+ free(fpr);
+ }
+
+ return;
+}
+
+int CertCA::__load_cakey_from_file(CertCA::ca_handlers * ca_config, const std::string & cakey_filepath)
+{
+ if (ca_config->cakey)
+ {
+ EVP_PKEY_free(ca_config->cakey);
+ }
+
+ ca_config->cakey = ssl_key_load(cakey_filepath.c_str());
+ if (!ca_config->cakey)
+ {
+ __throw_ssl_load_exception(errno, string_format("Error loading CA keys from %s", cakey_filepath.c_str()));
+ }
+
+ if (!ca_config->cacrt)
+ {
+ ca_config->cacrt = ssl_x509_load(cakey_filepath.c_str());
+ if (ca_config->cacrt)
+ {
+ ssl_x509_refcount_inc(ca_config->cacrt);
+ sk_X509_insert(ca_config->chain, ca_config->cacrt, 0);
+ }
+ }
+
+ return 0;
+}
+int CertCA::__load_cacert_from_file(CertCA::ca_handlers * ca_config, const std::string & cacrt_filepath)
+{
+ if (ca_config->cacrt)
+ {
+ X509_free(ca_config->cacrt);
+ }
+
+ ca_config->cacrt = ssl_x509_load(cacrt_filepath.c_str());
+ if (!ca_config->cacrt)
+ {
+ __throw_ssl_load_exception(errno, string_format("error loading CA cert from %s", cacrt_filepath.c_str()));
+ }
+
+ ssl_x509_refcount_inc(ca_config->cacrt);
+ sk_X509_insert(ca_config->chain, ca_config->cacrt, 0);
+
+ if (!ca_config->cakey)
+ {
+ ca_config->cakey = ssl_key_load(cacrt_filepath.c_str());
+ }
+
+ return 0;
+}
+
+void CertCA::__throw_ssl_load_exception(int err, std::string what)
+{
+ /* 系统错误 */
+ if (err)
+ {
+ throw std::system_error(err, std::generic_category(), what);
+ }
+
+ /* SSL错误 */
+ std::string ssl_err_info;
+ ERR_print_errors_cb([](const char * str, size_t len, void * u) -> int
+ {
+ auto * __str_err_info_ptr = static_cast<std::string *>(u);
+ *__str_err_info_ptr = std::string(str, len);
+ return 0;
+ }, static_cast<void *>(&ssl_err_info));
+
+ throw std::runtime_error(what + ":" + ssl_err_info);
+}
+
+std::unique_ptr<CertCA> CertCA::Factory(TfeConfigParser & cfg_parser)
+{
+ /* 调用Private的构造函数 */
+ std::unique_ptr<CertCA> __this_object = std::unique_ptr<CertCA>(new CertCA);
+
+ /* 加载可信根证书、不可信根证书证书、密钥 */
+ auto trust_ca_key_ret = cfg_parser.TryGetValue<std::string>("ca", "trust_ca_key");
+ if (trust_ca_key_ret.first)
+ {
+ __load_cakey_from_file(&__this_object->trust_ca_handlers_, trust_ca_key_ret.second);
+ }
+
+ auto trust_ca_crt_ret = cfg_parser.TryGetValue<std::string>("ca", "trust_ca_crt");
+ if (trust_ca_crt_ret.first)
+ {
+ __load_cacert_from_file(&__this_object->trust_ca_handlers_, trust_ca_crt_ret.second);
+ }
+
+ auto untrust_ca_key_ret = cfg_parser.TryGetValue<std::string>("ca", "untrust_ca_key");
+ if (untrust_ca_key_ret.first)
+ {
+ __load_cakey_from_file(&__this_object->untrust_ca_handlers_, untrust_ca_key_ret.second);
+ }
+
+ auto untrust_ca_crt_ret = cfg_parser.TryGetValue<std::string>("ca", "untrust_ca_crt");
+ if (untrust_ca_crt_ret.first)
+ {
+ __load_cacert_from_file(&__this_object->untrust_ca_handlers_, untrust_ca_crt_ret.second);
+ }
+
+ /* 根证书库,用于证书真伪认证 */
+ auto ca_root_filepath = cfg_parser.TryGetValue<std::string>("ca", "root_ca_store_file");
+ if (ca_root_filepath.first)
+ {
+ __this_object->is_ca_root_filepath_set_ = true;
+ __this_object->ca_root_filepath_ = ca_root_filepath.second;
+ }
+
+ auto ca_root_dirpath = cfg_parser.TryGetValue<std::string>("ca", "root_ca_store_dir");
+ if (ca_root_dirpath.first)
+ {
+ __this_object->is_ca_root_dirpath_set_ = true;
+ __this_object->ca_root_dirpath_ = ca_root_dirpath.second;
+ }
+
+ /* 加载根证书库 */
+ decltype(__this_object->x509_store_) x509_store{X509_STORE_new()};
+ if (unlikely(x509_store == nullptr))
+ {
+ throw std::runtime_error("Failed at creating X509_STORE");
+ }
+
+
+ int ret = X509_STORE_set_default_paths(x509_store.get());
+ if (unlikely(ret == 0))
+ {
+ throw std::runtime_error("Failed at setting default paths for X509_STORE");
+ }
+
+ ret = X509_STORE_load_locations(x509_store.get(),
+ __this_object->is_ca_root_filepath_set_ ? __this_object->ca_root_filepath_.c_str() : nullptr,
+ __this_object->is_ca_root_dirpath_set_ ? __this_object->ca_root_dirpath_.c_str() : nullptr);
+
+ if (unlikely(ret == 0))
+ {
+ throw std::runtime_error("Failed at setting load locations for X509_STORE");
+ }
+
+ __this_object->x509_store_ = std::move(x509_store);
+
+ LOG(INFO) << string_format("Trust CA Cert Location: %s", trust_ca_crt_ret.second.c_str());
+ __debug_dump_crt("Trust CA Cert Information: ", __this_object->trust_ca_handlers_.cacrt);
+
+ LOG(INFO) << string_format("Unrust CA Cert Location: %s", untrust_ca_crt_ret.second.c_str());
+ __debug_dump_crt("Untrust CA Cert Information: ", __this_object->untrust_ca_handlers_.cacrt);
+
+ return __this_object;
+}
+
+bool CertCA::SSLConnectionVerify(const SSL * ssl_connection)
+{
+ STACK_OF(X509) * cert_chain = SSL_get_peer_cert_chain(ssl_connection);
+ if (unlikely(cert_chain == nullptr))
+ {
+ LOG(DEBUG) << string_format("No SSL cert chain found, ssl: %p", ssl_connection);
+ return true;
+ }
+
+ std::unique_ptr<X509_STORE_CTX, __x509_store_deleter> x509_store_ctx{ X509_STORE_CTX_new()};
+ if (unlikely(x509_store_ctx == nullptr))
+ {
+ throw std::runtime_error("Failed at creating X509_STORE_CTX");
+ }
+
+ X509 * cert = sk_X509_value(cert_chain, 0);
+ if (!X509_STORE_CTX_init(x509_store_ctx.get(), x509_store_.get(), cert, cert_chain))
+ {
+ throw std::runtime_error("Failed at initializing X509_STORE_CTX");
+ }
+
+ return X509_verify_cert(x509_store_ctx.get()) != 0;
}
/* vim: set noet ft=c: */
diff --git a/src/cert.h b/src/cert.h
index 841a11c..dd93aca 100644
--- a/src/cert.h
+++ b/src/cert.h
@@ -34,6 +34,10 @@
#include <openssl/ssl.h>
#include <pthread.h>
+#include <memory>
+#include <string>
+#include "cfgparser.h"
+
typedef struct cert {
EVP_PKEY *key;
X509 *crt;
@@ -52,6 +56,55 @@ void cert_set_crt(cert_t *, X509 *) NONNULL(1);
void cert_set_chain(cert_t *, STACK_OF(X509) *) NONNULL(1);
void cert_free(cert_t *) NONNULL(1);
+class CertCA
+{
+public:
+ struct ca_handlers
+ {
+ X509 * cacrt{nullptr};
+ EVP_PKEY * cakey{nullptr};
+ STACK_OF(X509) * chain{sk_X509_new_null()};
+ };
+
+ bool SSLConnectionVerify(const SSL * ssl_connection);
+ const struct ca_handlers * CaHandlersGet(bool ssl_verify_result) const
+ {
+ return ssl_verify_result ? &trust_ca_handlers_ : &untrust_ca_handlers_;
+ }
+
+public:
+ virtual ~CertCA() = default;
+
+public:
+ static std::unique_ptr<CertCA> Factory(TfeConfigParser & parsre);
+
+private:
+ CertCA() = default;
+
+private:
+ struct ca_handlers trust_ca_handlers_{};
+ struct ca_handlers untrust_ca_handlers_{};
+
+ bool is_ca_root_filepath_set_{false};
+ bool is_ca_root_dirpath_set_{false};
+
+ std::string ca_root_filepath_{};
+ std::string ca_root_dirpath_{};
+
+ struct __x509_store_deleter
+ {
+ void operator()(X509_STORE * x509_store)
+ { X509_STORE_free(x509_store); }
+ void operator()(X509_STORE_CTX * x509_store_ctx)
+ { X509_STORE_CTX_free(x509_store_ctx); }
+ };
+
+ std::unique_ptr<X509_STORE, struct __x509_store_deleter> x509_store_;
+ static int __load_cakey_from_file(struct ca_handlers * ca_config, const std::string & cakey_filepath);
+ static int __load_cacert_from_file(struct ca_handlers * ca_config, const std::string & cacrt_filepath);
+ static void __throw_ssl_load_exception(int err, std::string what);
+};
+
#endif /* !CERT_H */
/* vim: set noet ft=c: */
diff --git a/src/main.cc b/src/main.cc
index a37ffed..2dbd72e 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -319,79 +319,6 @@ main(int argc, char *argv[])
while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z OPT_i "k:c:C:K:t:"
"OPs:r:R:e:Eu:m:j:p:l:L:S:F:M:dDVhW:w:q:")) != -1) {
switch (ch) {
- case 'c':
- if (opts->cacrt)
- X509_free(opts->cacrt);
- opts->cacrt = ssl_x509_load(optarg);
- if (!opts->cacrt) {
- fprintf(stderr, "%s: error loading CA "
- "cert from '%s':\n",
- argv0, optarg);
- if (errno) {
- fprintf(stderr, "%s\n",
- strerror(errno));
- } else {
- ERR_print_errors_fp(stderr);
- }
- exit(EXIT_FAILURE);
- }
- ssl_x509_refcount_inc(opts->cacrt);
- sk_X509_insert(opts->chain, opts->cacrt, 0);
- if (!opts->cakey) {
- opts->cakey = ssl_key_load(optarg);
- }
-#ifndef OPENSSL_NO_DH
- if (!opts->dh) {
- opts->dh = ssl_dh_load(optarg);
- }
-#endif /* !OPENSSL_NO_DH */
- break;
- case 'k':
- if (opts->cakey)
- EVP_PKEY_free(opts->cakey);
- opts->cakey = ssl_key_load(optarg);
- if (!opts->cakey) {
- fprintf(stderr, "%s: error loading CA "
- "key from '%s':\n",
- argv0, optarg);
- if (errno) {
- fprintf(stderr, "%s\n",
- strerror(errno));
- } else {
- ERR_print_errors_fp(stderr);
- }
- exit(EXIT_FAILURE);
- }
- if (!opts->cacrt) {
- opts->cacrt = ssl_x509_load(optarg);
- if (opts->cacrt) {
- ssl_x509_refcount_inc(
- opts->cacrt);
- sk_X509_insert(opts->chain,
- opts->cacrt, 0);
- }
- }
-#ifndef OPENSSL_NO_DH
- if (!opts->dh) {
- opts->dh = ssl_dh_load(optarg);
- }
-#endif /* !OPENSSL_NO_DH */
- break;
- case 'C':
- if (ssl_x509chain_load(NULL, &opts->chain,
- optarg) == -1) {
- fprintf(stderr, "%s: error loading "
- "chain from '%s':\n",
- argv0, optarg);
- if (errno) {
- fprintf(stderr, "%s\n",
- strerror(errno));
- } else {
- ERR_print_errors_fp(stderr);
- }
- exit(EXIT_FAILURE);
- }
- break;
case 'K':
if (opts->key)
EVP_PKEY_free(opts->key);
@@ -728,29 +655,14 @@ main(int argc, char *argv[])
spec->natlookup = nat_getlookupcb(spec->natengine);
spec->natsocket = nat_getsocketcb(spec->natengine);
}
- if (tfe_config_has_ssl_spec(opts)) {
+
+ if (tfe_config_has_ssl_spec(opts))
+ {
if (ssl_init() == -1) {
fprintf(stderr, "%s: failed to initialize OpenSSL.\n",
argv0);
exit(EXIT_FAILURE);
}
- if ((opts->cacrt || !opts->tgcrtdir) && !opts->cakey) {
- fprintf(stderr, "%s: no CA key specified (-k).\n",
- argv0);
- exit(EXIT_FAILURE);
- }
- if (opts->cakey && !opts->cacrt) {
- fprintf(stderr, "%s: no CA cert specified (-c).\n",
- argv0);
- exit(EXIT_FAILURE);
- }
- if (opts->cakey && opts->cacrt &&
- (X509_check_private_key(opts->cacrt, opts->cakey) != 1)) {
- fprintf(stderr, "%s: CA cert does not match key.\n",
- argv0);
- ERR_print_errors_fp(stderr);
- exit(EXIT_FAILURE);
- }
}
/* prevent multiple instances running */
@@ -776,7 +688,9 @@ main(int argc, char *argv[])
if (!opts->dropuser)
oom_die(argv0);
}
- if (tfe_config_has_ssl_spec(opts) && opts->cakey && !opts->key) {
+
+ if (tfe_config_has_ssl_spec(opts) && !opts->key)
+ {
/*
* While browsers still generally accept it, use a leaf key
* size of 1024 bit for leaf keys. When browsers start to
@@ -851,17 +765,6 @@ main(int argc, char *argv[])
log_dbg_printf("- %s\n", specstr);
free(specstr);
}
- if (opts->cacrt) {
- char *subj = ssl_x509_subject(opts->cacrt);
- log_dbg_printf("Loaded CA: '%s'\n", subj);
- free(subj);
-#ifdef DEBUG_CERTIFICATE
- log_dbg_print_free(ssl_x509_to_str(opts->cacrt));
- log_dbg_print_free(ssl_x509_to_pem(opts->cacrt));
-#endif /* DEBUG_CERTIFICATE */
- } else {
- log_dbg_printf("No CA loaded.\n");
- }
}
/*
@@ -948,6 +851,7 @@ main(int argc, char *argv[])
}
g_tfe_instance->struct_logger_module = StructLogger::Factory(__config_parser);
+ g_tfe_instance->cert_ca_module = CertCA::Factory(__config_parser);
/* close pidfile in child */
if (opts->pidfile)
diff --git a/src/opts.cc b/src/opts.cc
index 3ec872c..5a45619 100644
--- a/src/opts.cc
+++ b/src/opts.cc
@@ -61,7 +61,6 @@ struct tfe_config * tfe_config_new()
memset(__config, 0, sizeof(struct tfe_config));
__config->sslcomp = 1;
- __config->chain = sk_X509_new_null();
__config->sslmethod = SSLv23_method;
return __config;
}
@@ -134,81 +133,6 @@ static int __proxyspec_parse_each_entry(tfe_config * cfg, TfeConfigParser & ini_
return 0;
}
-void __throw_ssl_load_exception(int err, std::string what)
-{
- /* 系统错误 */
- if (err)
- {
- throw std::system_error(err,std::generic_category(), what);
- }
-
- /* SSL错误 */
- std::string ssl_err_info;
- ERR_print_errors_cb([](const char *str, size_t len, void *u)->int
- {
- std::string * __str_err_info_ptr = static_cast<std::string *>(u);
- * __str_err_info_ptr = std::string(str, len);
- return 0;
- },static_cast<void *>(&ssl_err_info));
-
- throw std::runtime_error(what + ":" + ssl_err_info);
-}
-
-static int __ssl_protocol_load_cakey(tfe_config * cfg, const std::string & str_cakey)
-{
- if (cfg->cakey)
- {
- EVP_PKEY_free(cfg->cakey);
- }
-
- cfg->cakey = ssl_key_load(str_cakey.c_str());
- if (!cfg->cakey)
- {
- __throw_ssl_load_exception(errno, string_format("Error loading CA keys from %s", str_cakey.c_str()));
- }
-
- if (!cfg->cacrt)
- {
- cfg->cacrt = ssl_x509_load(str_cakey.c_str());
- if (cfg->cacrt)
- {
- ssl_x509_refcount_inc(cfg->cacrt);
- sk_X509_insert(cfg->chain, cfg->cacrt, 0);
- }
- }
-
- return 0;
-}
-
-static int __ssl_protocol_load_cacert(tfe_config * cfg, const std::string & str_cacrt)
-{
- if (cfg->cacrt)
- {
- X509_free(cfg->cacrt);
- }
-
- cfg->cacrt = ssl_x509_load(str_cacrt.c_str());
- if (!cfg->cacrt)
- {
- __throw_ssl_load_exception(errno, string_format("error loading CA cert from %s", str_cacrt.c_str()));
- }
-
- ssl_x509_refcount_inc(cfg->cacrt);
- sk_X509_insert(cfg->chain, cfg->cacrt, 0);
-
- if (!cfg->cakey)
- {
- cfg->cakey = ssl_key_load(str_cacrt.c_str());
- }
-
- if (!cfg->dh)
- {
- cfg->dh = ssl_dh_load(str_cacrt.c_str());
- }
-
- return 0;
-}
-
static int __ssl_protocol_load_from_file(tfe_config * cfg, TfeConfigParser & cfg_parser)
{
bool __en_tls_1_0 = true;
@@ -229,18 +153,6 @@ static int __ssl_protocol_load_from_file(tfe_config * cfg, TfeConfigParser & cfg
if (!__en_ssl_v2) cfg->no_ssl2 = 1;
if (!__en_ssl_v3) cfg->no_ssl3 = 1;
- auto ca_key_ret = cfg_parser.TryGetValue<std::string>("ssl_protocol", "ca_key");
- if (ca_key_ret.first)
- {
- __ssl_protocol_load_cakey(cfg, ca_key_ret.second);
- }
-
- auto ca_crt_ret = cfg_parser.TryGetValue<std::string>("ssl_protocol", "ca_crt");
- if (ca_crt_ret.first)
- {
- __ssl_protocol_load_cacert(cfg, ca_crt_ret.second);
- }
-
return 0;
}
@@ -248,7 +160,7 @@ static int __maatframe_load_from_file(tfe_config * cfg, TfeConfigParser & cfg_pa
{
if (cfg->maat_config == nullptr)
{
- cfg->maat_config = new() tfe_maat_config;
+ cfg->maat_config = new tfe_maat_config;
}
tfe_maat_config * __maat_config = cfg->maat_config;
@@ -443,14 +355,6 @@ void tfe_config_parse_args(tfe_config * tfe, int argc, char ** argv)
void tfe_config_free(tfe_config * opts)
{
- sk_X509_pop_free(opts->chain, X509_free);
-
- if (opts->cacrt)
- X509_free(opts->cacrt);
-
- if (opts->cakey)
- EVP_PKEY_free(opts->cakey);
-
if (opts->key)
EVP_PKEY_free(opts->key);
diff --git a/src/opts.h b/src/opts.h
index 79e122c..b3ed79b 100644
--- a/src/opts.h
+++ b/src/opts.h
@@ -33,6 +33,7 @@
#include "ssl.h"
#include "attrib.h"
#include "logger.h"
+#include "cert.h"
#include <sys/types.h>
#include <sys/socket.h>
@@ -80,6 +81,9 @@ struct tfe_instance
std::unique_ptr<Http> http_module;
/* Struct Logger */
std::unique_ptr<StructLogger> struct_logger_module;
+ /* CertCA */
+ std::unique_ptr<CertCA> cert_ca_module;
+
/* stat handler */
struct tfe_stat_ctx * stat_module;
};
@@ -160,13 +164,12 @@ struct tfe_config
char * masterkeylog;
CONST_SSL_METHOD * (* sslmethod)(void);
int sslversion;
- X509 * cacrt;
- EVP_PKEY * cakey;
+
+ /* Private Key */
EVP_PKEY * key;
- STACK_OF(X509) * chain;
+
DH * dh;
char * ecdhcurve;
-
struct proxyspec * spec;
char * crlurl;
diff --git a/src/pxyconn.cc b/src/pxyconn.cc
index 7e58886..e5deb41 100644
--- a/src/pxyconn.cc
+++ b/src/pxyconn.cc
@@ -795,17 +795,13 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t * ctx)
else
{
if (OPTS_DEBUG(ctx->opts)) log_dbg_printf("Certificate cache: MISS\n");
- cert->crt = ssl_x509_forge(ctx->opts->cacrt,
- ctx->opts->cakey,
- ctx->origcrt,
- ctx->opts->key,
- NULL,
- ctx->opts->crlurl);
+ cert->crt = ssl_x509_forge(ctx->cacrt, ctx->cakey, ctx->origcrt, ctx->opts->key,
+ NULL, ctx->opts->crlurl);
cachemgr_fkcrt_set(ctx->origcrt, cert->crt);
}
cert_set_key(cert, ctx->opts->key);
- cert_set_chain(cert, ctx->opts->chain);
+ cert_set_chain(cert, ctx->chain);
ctx->generated_cert = 1;
}
@@ -840,7 +836,16 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t * ctx, SSL * origssl)
ctx->addrlen, ctx->sni,
SSL_get0_session(origssl));
+
+ /* 校验证书 */
+ auto verify_result = g_tfe_instance->cert_ca_module->SSLConnectionVerify(origssl);
+ auto verify_ca = g_tfe_instance->cert_ca_module->CaHandlersGet(verify_result);
+
ctx->origcrt = SSL_get_peer_certificate(origssl);
+ ctx->cacrt = verify_ca->cacrt;
+ ctx->cakey = verify_ca->cakey;
+ ctx->chain = verify_ca->chain;
+
if (OPTS_DEBUG(ctx->opts))
{
if (ctx->origcrt)
@@ -873,8 +878,7 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t * ctx, SSL * origssl)
ctx->enomem = 1;
}
- SSL_CTX * sslctx = pxy_srcsslctx_create(ctx, cert->crt, cert->chain,
- cert->key);
+ SSL_CTX * sslctx = pxy_srcsslctx_create(ctx, cert->crt, cert->chain, cert->key);
cert_free(cert);
if (!sslctx)
{
@@ -948,6 +952,7 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg)
}
}
+#if 0
/* generate a new certificate with sn as additional altSubjectName
* and replace it both in the current SSL ctx and in the cert cache */
if (!ctx->immutable_cert &&
@@ -961,9 +966,7 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg)
log_dbg_printf("Certificate cache: UPDATE "
"(SNI mismatch)\n");
}
- newcrt = ssl_x509_forge(ctx->opts->cacrt, ctx->opts->cakey,
- sslcrt, ctx->opts->key,
- sn, ctx->opts->crlurl);
+ newcrt = ssl_x509_forge(ctx->cacrt, ctx->cakey, sslcrt, ctx->opts->key, sn, ctx->opts->crlurl);
if (!newcrt)
{
ctx->enomem = 1;
@@ -973,10 +976,10 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg)
ctx->generated_cert = 1;
if (OPTS_DEBUG(ctx->opts))
{
- log_dbg_printf("===> Updated forged server "
- "certificate:\n");
+ log_dbg_printf("===> Updated forged server certificate:\n");
pxy_debug_crt(newcrt);
}
+
if (WANT_CONNECT_LOG(ctx))
{
if (ctx->ssl_names)
@@ -1002,8 +1005,7 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg)
}
}
- newsslctx = pxy_srcsslctx_create(ctx, newcrt, ctx->opts->chain,
- ctx->opts->key);
+ newsslctx = pxy_srcsslctx_create(ctx, newcrt, ctx->chain, ctx->opts->key);
if (!newsslctx)
{
X509_free(newcrt);
@@ -1020,6 +1022,7 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg)
"target mode)\n");
}
+#endif
return SSL_TLSEXT_ERR_OK;
}
diff --git a/src/pxyconn.h b/src/pxyconn.h
index 05daebf..1475672 100644
--- a/src/pxyconn.h
+++ b/src/pxyconn.h
@@ -161,6 +161,11 @@ typedef struct pxy_conn_ctx
void * protocol_conn_ctx;
struct pxy_conn_ctx_extend * extend;
+ /* SSL CA */
+ X509 * cacrt;
+ EVP_PKEY * cakey;
+ STACK_OF(X509) * chain;
+
} pxy_conn_ctx_t;
void pxy_conn_setup(evutil_socket_t fd_downstream, evutil_socket_t fd_upstream, struct sockaddr *peeraddr,