diff options
| author | Lu <[email protected]> | 2018-08-15 20:58:55 +0800 |
|---|---|---|
| committer | Lu <[email protected]> | 2018-08-15 20:58:55 +0800 |
| commit | 0185ccff6675752c99a4a03c3d4ff72e18ab306a (patch) | |
| tree | ca47e4181cdb262db5e89e4e314f1e18c372d497 /src | |
| parent | 143373018ef0443cf8c02b7f5bae8a393bfac819 (diff) | |
增加源站证书有效性校验功能,关闭根据SNI添加SAN证书字段的功能。
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/cert.cc | 513 | ||||
| -rw-r--r-- | src/cert.h | 53 | ||||
| -rw-r--r-- | src/main.cc | 110 | ||||
| -rw-r--r-- | src/opts.cc | 98 | ||||
| -rw-r--r-- | src/opts.h | 11 | ||||
| -rw-r--r-- | src/pxyconn.cc | 35 | ||||
| -rw-r--r-- | src/pxyconn.h | 5 |
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: */ @@ -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); @@ -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, |
