diff options
| author | Lu <[email protected]> | 2018-06-11 10:51:11 +0800 |
|---|---|---|
| committer | Lu <[email protected]> | 2018-06-11 10:51:11 +0800 |
| commit | 72bca3159ec93e2e7d6a9612d8601fe7d40b07f6 (patch) | |
| tree | 45315131f609097296997d5079eb651fc452222a | |
| parent | fe5d92850822671a2988048cdd0ed9e1bc619812 (diff) | |
增加Forge Socket的Listener
| -rw-r--r-- | .idea/codeStyles/Project.xml | 1 | ||||
| -rw-r--r-- | .idea/inspectionProfiles/Project_Default.xml | 8 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | src/cfgparser.cc | 42 | ||||
| -rw-r--r-- | src/cfgparser.h | 37 | ||||
| -rw-r--r-- | src/compat.h | 162 | ||||
| -rw-r--r-- | src/connection.cc | 141 | ||||
| -rw-r--r-- | src/http.h | 34 | ||||
| -rw-r--r-- | src/http1.cc | 141 | ||||
| -rw-r--r-- | src/http2.cc | 159 | ||||
| -rw-r--r-- | src/httpscan.cc | 80 | ||||
| -rw-r--r-- | src/httpscan.h | 1 | ||||
| -rw-r--r-- | src/logger.cc | 1 | ||||
| -rw-r--r-- | src/main.cc | 44 | ||||
| -rw-r--r-- | src/opts.h | 5 | ||||
| -rw-r--r-- | src/proxy.cc | 644 | ||||
| -rw-r--r-- | src/pxyconn.cc | 573 | ||||
| -rw-r--r-- | src/pxyconn.h | 15 |
18 files changed, 1331 insertions, 764 deletions
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index b5725b7..1245a4c 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -17,7 +17,6 @@ <option name="CLASS_CONSTRUCTOR_INIT_LIST_WRAP" value="5" /> <option name="SUPERCLASS_LIST_BEFORE_COLON" value="0" /> <option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" /> - <option name="INSERT_OVERRIDE" value="false" /> <option name="ADD_BRIEF_TAG" value="true" /> </Objective-C> <Objective-C-extensions> diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..a4d36d3 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="ClangTidyInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="clangTidyChecks" value="*,-android-*,-bugprone-bool-pointer-implicit-conversion,-cert-env33-c,-cert-dcl50-cpp,-cert-dcl59-cpp,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-operator,-hicpp-braces-around-statements,-hicpp-named-parameter,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-no-malloc,-hicpp-function-size,-hicpp-special-member-functions,-hicpp-vararg,-llvm-*,-objc-*,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-readability-redundant-member-init,-misc-bool-pointer-implicit-conversion,-misc-definitions-in-headers,-misc-unused-alias-decls,-misc-unused-parameters,-misc-unused-using-decls,-modernize-use-using,-modernize-use-default-member-init,-clang-diagnostic-*,-clang-analyzer-*,-readability-redundant-control-flow" /> + </inspection_tool> + </profile> +</component>
\ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e227370..f4ed9e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ find_package(OpenSSL REQUIRED) add_library(tfe-library base64.cc build.cc cache.cc cachemgr.cc cachessess.cc compat.cc easylogging++.cc - cachedsess.cc cachetgcrt.cc cachefkcrt.cc cert.cc certstore.cc logger.cc - dynbuf.cc nat.cc opts.cc privsep.cc proxy.cc pxythrmgr.cc pxysslshut.cc + cachedsess.cc cachetgcrt.cc cachefkcrt.cc cert.cc certstore.cc logger.cc cfgparser.cc + dynbuf.cc nat.cc opts.cc privsep.cc proxy.cc pxythrmgr.cc pxysslshut.cc pxyconn.cc ssl.cc sys.cc thrqueue.cc url.cc util.cc httpscan.cc httpaction.cc http2.cc http1.cc http.cc) #pxyconn.cc @@ -16,7 +16,8 @@ target_link_libraries(tfe-library libevent-static-pthreads http-parser-static nghttp2-static - MESA_prof_load-static) + MESA_prof_load-static + jsoncpp rdkafka) target_link_libraries(tfe-library maatframe MESA_handle_logger) diff --git a/src/cfgparser.cc b/src/cfgparser.cc new file mode 100644 index 0000000..27e9ccc --- /dev/null +++ b/src/cfgparser.cc @@ -0,0 +1,42 @@ +// +// Created by luqiu on 2018-6-7. +// + +#include "cfgparser.h" + +template<> +std::string TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) +{ + char __str_buffer[TFE_STRING_MAX]; + memset(__str_buffer, 0, sizeof(__str_buffer)); + + int ret = MESA_load_profile_string_nodef(str_cfgfile_.c_str(), str_section.c_str(), str_entry.c_str(), + __str_buffer, sizeof(__str_buffer)); + + if (ret < 0) + throw cfg_lost_entry(str_cfgfile_, str_section, str_entry, ""); + + return std::string(__str_buffer); +} + +template<> +unsigned long TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) +{ + char *__ptr = nullptr; + std::string __str_value = GetValue<std::string>(str_section, str_entry); + + unsigned long __value = strtoul(__str_value.c_str(), &__ptr, 0); + if (__ptr == __str_value.c_str()) + { + throw cfg_invalid_format(str_cfgfile_, str_section, str_entry, + __str_value + " is not valid unsigned number. "); + } + + return __value; +} + +template<> +bool TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) +{ + return GetValue<unsigned long>(str_section, str_entry) != 0; +}
\ No newline at end of file diff --git a/src/cfgparser.h b/src/cfgparser.h index 4853ef2..c7e6729 100644 --- a/src/cfgparser.h +++ b/src/cfgparser.h @@ -40,43 +40,6 @@ private: std::string str_cfgfile_; }; -template<> -std::string TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) -{ - char __str_buffer[TFE_STRING_MAX]; - memset(__str_buffer, 0, sizeof(__str_buffer)); - - int ret = MESA_load_profile_string_nodef(str_cfgfile_.c_str(), str_section.c_str(), str_entry.c_str(), - __str_buffer, sizeof(__str_buffer)); - - if (ret < 0) - throw cfg_lost_entry(str_cfgfile_, str_section, str_entry, ""); - - return std::string(__str_buffer); -} - -template<> -unsigned long TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) -{ - char *__ptr = nullptr; - std::string __str_value = GetValue<std::string>(str_section, str_entry); - - unsigned long __value = strtoul(__str_value.c_str(), &__ptr, 0); - if (__ptr == __str_value.c_str()) - { - throw cfg_invalid_format(str_cfgfile_, str_section, str_entry, - __str_value + " is not valid unsigned number. "); - } - - return __value; -} - -template<> -bool TfeConfigParser::GetValue(const std::string &str_section, const std::string &str_entry) -{ - return GetValue<unsigned long>(str_section, str_entry) != 0; -} - template<typename T> T TfeConfigParser::GetValueWithDefault( const std::string &str_section, diff --git a/src/compat.h b/src/compat.h index 1fcf1e0..5fd2b53 100644 --- a/src/compat.h +++ b/src/compat.h @@ -1,5 +1,6 @@ #pragma once +#include <exception> #include <memory> #include <cstdio> @@ -32,6 +33,163 @@ using evbuffer_unique_ptr_t = std::unique_ptr<struct evbuffer, EventDeleter>; using file_unique_ptr_t = std::unique_ptr<FILE, FileDescriptorDeleter>; using fd_unique_ptr_t = std::unique_ptr<int, FileDescriptorDeleter>; +/* Bufferevent托管类 + * Bufferevent指针用于构造本Class后,即失去对指针的所有权,指针的释放由本类的析构函数完成 */ +class BufferEvent +{ +public: + explicit BufferEvent(struct bufferevent *bev) + { bev_.reset(bev); } + + using data_cb_t = std::function<int(struct bufferevent *bev)>; + using event_cb_t = std::function<int(struct bufferevent *bev, short what)>; + using exception_cb_t = std::function<int(std::exception_ptr ex_ptr)>; + + void SetReadCallback(data_cb_t cb) + { read_cb_ = cb; } + void SetWriteCallback(data_cb_t cb) + { write_cb_ = cb; } + void SetEventCallback(event_cb_t cb) + { event_cb_ = cb; } + void SetExceptionCallback(exception_cb_t cb) + { exception_cb_ = cb; } + + void Enable(short what) + { bufferevent_enable(bev_.get(), what); } + void Disable(short what) + { bufferevent_disable(bev_.get(), what); } + struct bufferevent *Raw() + { return bev_.get(); } + +private: + data_cb_t read_cb_; + data_cb_t write_cb_; + event_cb_t event_cb_; + exception_cb_t exception_cb_; + + struct __bufferevent_deleter + { + void operator()(struct bufferevent *bev) + { bufferevent_free(bev); } + }; + + std::unique_ptr<struct bufferevent, __bufferevent_deleter> bev_; + +private: + static int __wrapper_cb_read(struct bufferevent *bev, void *user) + { + auto *__this = static_cast<BufferEvent *>(user); + std::exception_ptr exp_ptr; + + try + { + return __this->read_cb_(bev); + } + catch (const std::exception & e) + { + exp_ptr = std::current_exception(); + } + + if(__this->exception_cb_ == nullptr) + { + std::rethrow_exception(exp_ptr); + } + + if (__this->exception_cb_ != nullptr && __this->exception_cb_(exp_ptr) != 0) + { + std::rethrow_exception(exp_ptr); + } + + return 0; + } + + static int __wrapper_cb_write(struct bufferevent *bev, void *user) + { + auto *__this = static_cast<BufferEvent *>(user); + std::exception_ptr exp_ptr; + + try + { + return __this->write_cb_(bev); + } + catch (const std::exception & e) + { + exp_ptr = std::current_exception(); + } + + if(__this->exception_cb_ == nullptr) + { + std::rethrow_exception(exp_ptr); + } + + if (__this->exception_cb_ != nullptr && __this->exception_cb_(exp_ptr) != 0) + { + std::rethrow_exception(exp_ptr); + } + + return 0; + } + + static int __wrapper_cb_event(struct bufferevent *bev, short what, void *user) + { + auto *__this = static_cast<BufferEvent *>(user); + std::exception_ptr exp_ptr; + + try + { + return __this->event_cb_(bev, what); + } + catch (const std::exception & e) + { + exp_ptr = std::current_exception(); + } + + if(__this->exception_cb_ == nullptr) + { + std::rethrow_exception(exp_ptr); + } + + if (__this->exception_cb_ != nullptr && __this->exception_cb_(exp_ptr) != 0) + { + std::rethrow_exception(exp_ptr); + } + + return 0; + } +}; + +/* Event托管类 + * Bufferevent指针用于构造本Class后,即失去对指针的所有权,指针的释放由本类的析构函数完成 */ +class Event +{ +public: + explicit Event() = default; + virtual ~Event() = default; + + using event_cb_t = std::function<void(evutil_socket_t fd, short what)>; + void Init(struct event_base * ev_base, evutil_socket_t fd, short en_event, event_cb_t cb) + { + ev_.reset(event_new(ev_base, fd, en_event, __wrapper_event, this)); + } + +private: + event_cb_t event_cb_; + struct __event_deleter + { + void operator()(struct event *ev) + { event_free(ev); } + }; + + std::unique_ptr<struct event, __event_deleter> ev_; + +private: + static void __wrapper_event(evutil_socket_t fd, short what, void * user) + { + auto *__this = static_cast<Event *>(user); + return __this->event_cb_(fd, what); + } +}; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Stream.h内的数据结构转换工具 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,7 +197,7 @@ using fd_unique_ptr_t = std::unique_ptr<int, FileDescriptorDeleter>; struct SappIpAddrDeleter { - void operator()(struct ipaddr * ptr_addr) + void operator()(struct ipaddr *ptr_addr) { if (ptr_addr->addrtype == ADDR_TYPE_IPV4) delete ptr_addr->v4; if (ptr_addr->addrtype == ADDR_TYPE_IPV6) delete ptr_addr->v6; @@ -48,7 +206,7 @@ struct SappIpAddrDeleter }; using sapp_ip_addr_ptr_t = std::unique_ptr<struct ipaddr, SappIpAddrDeleter>; -sapp_ip_addr_ptr_t sockaddr_to_sapp_ipaddr(const struct sockaddr * sk_addr_src, const struct sockaddr * sk_addr_dst); +sapp_ip_addr_ptr_t sockaddr_to_sapp_ipaddr(const struct sockaddr *sk_addr_src, const struct sockaddr *sk_addr_dst); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/connection.cc b/src/connection.cc new file mode 100644 index 0000000..1dbf2f9 --- /dev/null +++ b/src/connection.cc @@ -0,0 +1,141 @@ + +#include <cassert> +#include "compat.h" + +extern "C" +{ +#include <event2/event.h> +#include <event2/bufferevent.h> +#include <openssl/ossl_typ.h> +} + +enum +{ + kDirectionDownstream, + kDirectionUpstream +}; + +class Connection +{ + +}; + +class ConnectionDownstream : std::enable_shared_from_this<ConnectionDownstream> +{ +public: + /* 应用层协议选项 */ + struct option + { + /* 是否自动识别SSL */ + bool can_upgrade_to_ssl; + /* 是否自动识别HttpV1 */ + bool can_upgrade_to_http_v1; + /* 是否自动识别HttpV2,即HttpV2的引导区域 */ + bool can_upgrade_to_http_v2; + }; + + explicit ConnectionDownstream(struct event_base *evbase, evutil_socket_t fd, + const struct option &upgrade_option); + + void Setup(); + void Shutdown(); + +private: + struct option options; + + struct sockaddr_storage local_addr_; + socklen_t local_addrlen_; + struct sockaddr_storage peer_addr_; + socklen_t peer_addrlen_; + + std::unique_ptr<BufferEvent> bev_ptr_; + std::unique_ptr<Event> ev_ptr_; + + evutil_socket_t fd_; + struct event_base * evbase_; + +private: + int cb_read(struct bufferevent *bev); + int cb_write(struct bufferevent *bev); + int cb_event(struct bufferevent *bev, short events); + int cb_exception(std::exception_ptr ex_ptr); + + void cb_scan_clienthello(struct event * ev, short what); + +private: + /* Setup函数,对于SSL需要根据Raw的内容解析SNI */ + void __setup_autograde_callback(); + void __setup_bev_callback(); +}; + +ConnectionDownstream::ConnectionDownstream(struct event_base *evbase, evutil_socket_t fd, + const struct option &upgrade_option) : fd_(fd), options(upgrade_option), evbase_(evbase) +{} + +void ConnectionDownstream::Setup() +{ + return options.can_upgrade_to_ssl ? __setup_autograde_callback() : __setup_bev_callback(); +} + +void ConnectionDownstream::__setup_autograde_callback() +{ + auto shared_this_ptr = shared_from_this(); + ev_ptr_ = std::make_unique<Event>(); + + /* 初始化一个Event,处理TCP上的原始数据,解析SSL ClientHello中的SNI选项 */ + ev_ptr_->Init(evbase_, fd_, EV_READ, [shared_this_ptr](struct event * ev, short what) + { + auto __this_ptr = shared_this_ptr; + return __this_ptr->cb_scan_clienthello(ev, what); + }); + + return; +} + +void ConnectionDownstream::__setup_bev_callback() +{ + /* 对于Plain TCP,创建Bufferevent,调用ReadCb/EventCb直接处理 */ + struct bufferevent *bev_raw = bufferevent_socket_new(evbase_, fd_, BEV_OPT_DEFER_CALLBACKS); + + if (unlikely(bev_raw == nullptr)) + { + throw std::runtime_error("Error creating bufferevent socket"); + } + + /* 托管给Bufferevent */ + bev_ptr_ = std::make_unique<BufferEvent>(bev_raw); + auto shared_this_ptr = shared_from_this(); + + /* 在Callback中保存ConnectionDownstream的指针,当所有回调函数清除时,ConnectionDownstream析构 */ + bev_ptr_->SetReadCallback([shared_this_ptr](struct bufferevent *bev) -> int + { + auto __this_ptr = shared_this_ptr; + return __this_ptr->cb_read(bev); + }); + + bev_ptr_->SetWriteCallback([shared_this_ptr](struct bufferevent *bev) -> int + { + auto __this_ptr = shared_this_ptr; + return __this_ptr->cb_write(bev); + }); + + bev_ptr_->SetEventCallback([shared_this_ptr](struct bufferevent *bev, short what) -> int + { + auto __this_ptr = shared_this_ptr; + return __this_ptr->cb_event(bev, what); + }); + + bev_ptr_->SetExceptionCallback([shared_this_ptr](std::exception_ptr exp_ptr)->int + { + auto __this_ptr = shared_this_ptr; + return __this_ptr->cb_exception(exp_ptr); + }); + + /* 注册EV_READ、EV_WRITE事件,当事件发生时调用cb_read、cb_write处理 */ + bev_ptr_->Enable(EV_READ | EV_WRITE); +} + +void ConnectionDownstream::cb_scan_clienthello(struct event *ev, short what) +{ + +} @@ -1,9 +1,10 @@ #ifndef TFE_HTTP_H #define TFE_HTTP_H +#include <memory> #include <map> #include <string> -#include <memory> +#include <list> class HttpConnection; class HttpSession; @@ -55,7 +56,7 @@ class HttpSession { public: explicit HttpSession(HttpConnection &connection) : http_connection_(connection) {} - ~HttpSession() = default; + virtual ~HttpSession() = default; using http_session_cb_t = std::function<void(HttpSession &)>; @@ -174,4 +175,33 @@ public: std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version); std::unique_ptr<HttpResponse> HttpResponseFactory(int primary_version, int second_version); +#include "pxyconn.h" + +class Http1Connection : public HttpConnection +{ +public: + Http1Connection() = default; + ~Http1Connection() = default; + + void Close() override + { need_to_close_ = true; }; + + int on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_conn_desc_t *conn_this, pxy_conn_desc_t *conn_other); + int on_connection_read_response(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev); + int on_connection_close(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev); + const sockaddr *SockAddrSource() const override; + const sockaddr *SockAddrDest() const override; + +private: + using http_sessions_t = std::list<std::unique_ptr<HttpSession>>; + http_sessions_t http_sessions_; + + HttpSession &create_new_session(); + HttpSession &last_uncomplete_session(); + + void drop_last_session(); + void drop_first_session(); + bool need_to_close_{false}; +}; + #endif //TFE_HTTP_H diff --git a/src/http1.cc b/src/http1.cc index 68934cb..950ff77 100644 --- a/src/http1.cc +++ b/src/http1.cc @@ -1,7 +1,3 @@ -// -// Created by luqiu on 2018-5-22. -// - /* HTTP/HTTP2 Protocol Handler * * Author: Lu Qiuwen<[email protected]> @@ -27,30 +23,6 @@ #include "util.h" #include "easylogging++.h" -class Http1Connection : public HttpConnection -{ -public: - Http1Connection() = default; - ~Http1Connection() = default; - - void Close() override { need_to_close_ = true;} ; - - int on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_conn_desc_t *conn_this, pxy_conn_desc_t *conn_other); - int on_connection_read_response(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev); - int on_connection_close(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev); - -private: - using http_sessions_t = std::list<std::unique_ptr<HttpSession>>; - http_sessions_t http_sessions_; - - HttpSession &create_new_session(); - HttpSession &last_uncomplete_session(); - - void drop_last_session(); - void drop_first_session(); - bool need_to_close_{false}; -}; - class Http1Request : public HttpRequest { public: @@ -75,6 +47,10 @@ public: virtual void ForEachHeader(for_each_header_cb_t cb); bool Complete() override { return request_complete_; } + const std::string &Url() const override; + void Url(const std::string &url) override; + const std::string &HeaderValue(const std::string &field) override; + void HeaderValue(const std::string &field, const std::string &value) override; private: std::string str_uri{}; @@ -92,7 +68,7 @@ private: evbuffer_unique_ptr_t evbuf_content_raw_{evbuffer_unique_ptr_t(evbuffer_new())}; }; -Http1Request::Http1Request() + Http1Request::Http1Request() { http_parser_init(parser_.get(), HTTP_REQUEST); } @@ -128,16 +104,16 @@ ssize_t Http1Request::ConstructFromMemory(const char *buf, size_t buflen) }; static struct http_parser_settings __parser_setting = - { - nullptr, /* on_message_begin */ - __http_parser_cb_on_uri, /* on_url */ - nullptr, /* on_status */ - __http_parser_cb_on_header_field, /* on_header_field */ - __http_parser_cb_on_header_value, /* on_header_value */ - __http_parser_cb_on_message_complete, /* on_headers_complete */ - nullptr, /* on_body */ - nullptr /* on_message_complete */ - }; + { + nullptr, /* on_message_begin */ + __http_parser_cb_on_uri, /* on_url */ + nullptr, /* on_status */ + __http_parser_cb_on_header_field, /* on_header_field */ + __http_parser_cb_on_header_value, /* on_header_value */ + __http_parser_cb_on_message_complete, /* on_headers_complete */ + nullptr, /* on_body */ + nullptr /* on_message_complete */ + }; parser_->data = this; size_t sz_parsed = http_parser_execute(parser_.get(), &__parser_setting, buf, buflen); @@ -184,6 +160,25 @@ void Http1Request::ForEachHeader(HttpRequest::for_each_header_cb_t cb) return; } +const std::string &Http1Request::Url() const +{ + return str_headers["Host"] + str_uri; +} + +void Http1Request::Url(const std::string &url) +{ + str_uri = url; +} + +const std::string &Http1Request::HeaderValue(const std::string &field) +{ + return str_headers[field]; +} + +void Http1Request::HeaderValue(const std::string &field, const std::string &value) +{ + str_headers[field] = value; +} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HTTP Response Parser Implementation for HTTP 1.0/1.1 @@ -279,6 +274,10 @@ public: virtual bool Complete() final { return parse_complete_; } virtual void Construct() final; + void ResponseCode(int code) override; + const std::string &HeaderValue(const std::string &field) override; + void HeaderValue(const std::string &field, const std::string &value) override; + void ForEachHeader(for_each_header_cb_t cb) override; private: int resp_code_; @@ -388,26 +387,46 @@ void Http1Response::Construct() evbuf_content_raw_ = std::move(evbuf_construct); } +void Http1Response::ResponseCode(int code) +{ + resp_code_ = code; +} + +const std::string &Http1Response::HeaderValue(const std::string &field) +{ + return str_headers[field]; +} + +void Http1Response::HeaderValue(const std::string &field, const std::string &value) +{ + str_headers[field] = value; +} + +void Http1Response::ForEachHeader(HttpResponse::for_each_header_cb_t cb) +{ + return; +} + int Http1Connection::on_connection_close(pxy_conn_ctx_t *conn_ctx, struct bufferevent *bev) { return 0; } -int Http1Connection::on_connection_read_request( - pxy_conn_ctx_t *conn_ctx, - pxy_conn_desc_t *conn_this, pxy_conn_desc_t *conn_other) +int Http1Connection::on_connection_read_request(pxy_conn_ctx_t *conn_ctx, pxy_conn_desc_t *conn_this, + pxy_conn_desc_t *conn_other) { /* Get the last session */ - auto http_session_ctx = last_uncomplete_session(); + auto & http_session = last_uncomplete_session(); + auto & request = dynamic_cast<Http1Request &>(http_session.request()); - auto *request = reinterpret_cast<Http1Request *>(http_session_ctx.request()); auto *downstream_evbuf = bufferevent_get_input(conn_this->bev); auto *upstream_evbuf = bufferevent_get_output(conn_other->bev); - ssize_t forward_len = request->ConstructFromEvBuf(downstream_evbuf); + ssize_t forward_len = request.ConstructFromEvBuf(downstream_evbuf); if (forward_len < 0) { + LOG(DEBUG) << "RequestConstructFromEvBuf Failed, connection turns to passthrough"; conn_ctx->passthrough = 1; return 0; } @@ -418,24 +437,24 @@ int Http1Connection::on_connection_read_request( return 0; } - if (request->Complete()) + if (request.Complete()) { - http_session_ctx.CallRequestHeaderCallback(); - http_session_ctx.CallRequestBodyCallback(); + http_session.CallRequestHeaderCallback(); + http_session.CallRequestBodyCallback(); /* 转发请求 */ - if (request->Forward()) + if (request.Forward()) { - auto stolen_raw_evbuf = request->StolenEvbuf(); + auto stolen_raw_evbuf = request.StolenEvbuf(); evbuffer_add_buffer(upstream_evbuf, stolen_raw_evbuf.release()); } return 0; } - if (request->ReadOnly()) + if (request.ReadOnly()) { - evbuffer_add_buffer(upstream_evbuf, request->StolenEvbuf().release()); + evbuffer_add_buffer(upstream_evbuf, request.StolenEvbuf().release()); return 0; } @@ -454,7 +473,7 @@ HttpSession &Http1Connection::create_new_session() __http_session->request(HttpRequestFactory(1, 0)); /* Add to the last record */ - http_sessions_.push_back(__http_session); + http_sessions_.push_back(std::move(__http_session)); return *__http_session; } @@ -464,12 +483,13 @@ HttpSession &Http1Connection::last_uncomplete_session() return create_new_session(); /* 最后一个Session已经处理结束了,新建一个Session */ - auto __session = http_sessions_.back(); - if (__session->request()->request_complete) + auto & __session = http_sessions_.back(); + + if (__session->request().Complete()) return create_new_session(); /* 否则,返回最后一个没有完全处理结束的Session */ - return __session; + return *__session; } void Http1Connection::drop_last_session() @@ -484,6 +504,15 @@ void Http1Connection::drop_first_session() http_sessions_.pop_front(); } +const sockaddr *Http1Connection::SockAddrSource() const +{ + return nullptr; +} +const sockaddr *Http1Connection::SockAddrDest() const +{ + return nullptr; +} + std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version) { if (primary_version == 1 && second_version == 0) diff --git a/src/http2.cc b/src/http2.cc index 2003826..3ef07b8 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -43,6 +43,16 @@ class Http2Request : public HttpRequest public: void Serialize(std::vector<nghttp2_nv> &nv_array_output, nghttp2_data_provider *data_prd); void ConstructContent(const char *content, size_t content_len, bool is_append); + const std::string &Url() const override; + void Url(const std::string &url) override; + const std::string &HeaderValue(const std::string &field) override; + void HeaderValue(const std::string &field, const std::string &value) override; + void ForEachHeader(for_each_header_cb_t cb) override; + bool ReadOnly() override; + void ReadOnly(bool is_readonly) override; + bool Forward() override; + void Forward(bool is_forward) override; + bool Complete() override; private: using header_kv_t = std::pair<std::string, std::string>; @@ -56,7 +66,7 @@ private: void Http2Request::Serialize(std::vector<nghttp2_nv> &nv_array_output, nghttp2_data_provider *data_prd) { /* HTTP2头部序列化 */ - for (auto kv_iterater : header_kv_store_) + for (auto & kv_iterater : header_kv_store_) { const auto &header_k = kv_iterater->first; const auto &header_v = kv_iterater->second; @@ -64,8 +74,8 @@ void Http2Request::Serialize(std::vector<nghttp2_nv> &nv_array_output, nghttp2_d nghttp2_nv __nv; /* 构建NV对,应用程序需保证Name, Value均为小写 */ - __nv.name = static_cast<uint8_t *>(header_k.c_str()); - __nv.value = static_cast<uint8_t *>(header_v.c_str()); + __nv.name = reinterpret_cast<uint8_t *>(const_cast<char *>(header_k.c_str())); + __nv.value = reinterpret_cast<uint8_t *>(const_cast<char *>(header_v.c_str())); __nv.namelen = header_k.length(); __nv.valuelen = header_v.length(); @@ -102,12 +112,10 @@ void Http2Request::Serialize(std::vector<nghttp2_nv> &nv_array_output, nghttp2_d /* 复制到目的缓冲区,并删除缓冲区的已经发送的内容 */ std::copy_n(header_content_ptr->cbegin(), sz_want_to_send, buf); - header_content_ptr->erase(header_content_ptr->cbegin(), header_content_ptr->cbegin() + sz_want_to_send); + header_content_ptr->erase(header_content_ptr->begin(), header_content_ptr->begin() + sz_want_to_send); return sz_want_to_send; }; - - return; } void Http2Request::ConstructContent(const char *content, size_t content_len, bool is_append) @@ -126,19 +134,129 @@ void Http2Request::ConstructContent(const char *content, size_t content_len, boo return; } +const std::string &Http2Request::Url() const +{ + return ""; +} + +void Http2Request::Url(const std::string &url) +{ + +} + +const std::string &Http2Request::HeaderValue(const std::string &field) +{ + return ""; +} + +void Http2Request::HeaderValue(const std::string &field, const std::string &value) +{ + +} + +void Http2Request::ForEachHeader(HttpRequest::for_each_header_cb_t cb) +{ + +} + +bool Http2Request::ReadOnly() +{ + return false; +} + +void Http2Request::ReadOnly(bool is_readonly) +{ + +} + +bool Http2Request::Forward() +{ + return false; +} + +void Http2Request::Forward(bool is_forward) +{ + +} + +bool Http2Request::Complete() +{ + return false; +} + class Http2Response : public HttpResponse { +public: + int ResponseCode() override; + void ResponseCode(int code) override; + const std::string &HeaderValue(const std::string &field) override; + void HeaderValue(const std::string &field, const std::string &value) override; + void ForEachHeader(for_each_header_cb_t cb) override; + bool ReadOnly() override; + void ReadOnly(bool is_readonly) override; + bool Forward() override; + void Forward(bool is_forward) override; + bool Complete() override; + void Construct() override; private: using header_kv_t = std::pair<std::string, std::string>; std::vector<std::unique_ptr<header_kv_t>> header_kv_store_{}; std::map<std::string, header_kv_t &> header_kv_lookup_{}; }; +int Http2Response::ResponseCode() +{ + return 0; +} + +void Http2Response::ResponseCode(int code) +{ + +} + +const std::string &Http2Response::HeaderValue(const std::string &field) +{ + return ""; +} + +void Http2Response::HeaderValue(const std::string &field, const std::string &value) +{ + +} +void Http2Response::ForEachHeader(HttpResponse::for_each_header_cb_t cb) +{ + +} +bool Http2Response::ReadOnly() +{ + return false; +} +void Http2Response::ReadOnly(bool is_readonly) +{ + +} +bool Http2Response::Forward() +{ + return false; +} +void Http2Response::Forward(bool is_forward) +{ + +} +bool Http2Response::Complete() +{ + return false; +} +void Http2Response::Construct() +{ + +} + class Http2Session : public HttpSession { public: explicit Http2Session(Http2Connection &conn) : HttpSession(conn) {} - virtual Http2Session() = default; + virtual ~Http2Session() = default; int32_t stream_id_upstream{0}; int32_t stream_id_downstream{0}; @@ -230,7 +348,7 @@ h2_downstream::h2_downstream(Http2Connection &conn) : conn_(conn) ssize_t h2_downstream::cb_on_send(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data) { - auto *this_ptr = dynamic_cast<h2_downstream *>(user_data); + auto *this_ptr = static_cast<h2_downstream *>(user_data); struct bufferevent *h2_bev = this_ptr->conn_.bev_downstream_; if (bufferevent_write(h2_bev, data, length) < 0) @@ -246,8 +364,8 @@ ssize_t h2_downstream::cb_on_send(nghttp2_session *session, const uint8_t *data, /* Downstream实现 */ int h2_downstream::cb_on_header_begin(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { - auto *this_ptr = dynamic_cast<h2_downstream *>(user_data); - auto h2_connection = this_ptr->conn_; + auto *this_ptr = static_cast<h2_downstream *>(user_data); + auto & h2_connection = this_ptr->conn_; /* 对于Downstream->Upstream的报文,在HTTP Request时建立新上下文 */ if (frame->hd.type != NGHTTP2_HEADERS || frame->headers.cat != NGHTTP2_HCAT_REQUEST) @@ -264,31 +382,28 @@ int h2_downstream::cb_on_header_begin(nghttp2_session *session, const nghttp2_fr int h2_downstream::cb_on_header(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags, void *user_data) { - auto *this_ptr = dynamic_cast<h2_downstream *>(user_data); + auto *this_ptr = static_cast<h2_downstream *>(user_data); auto *h2_session = (Http2Session *) nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); assert(this_ptr != nullptr); assert(h2_session != nullptr); - std::string str_header_name; - std::string str_header_value; - - std::copy_n(name, std::back_inserter(str_header_name), namelen); - std::copy_n(value, std::back_inserter(str_header_value), valuelen); + std::string str_header_name{reinterpret_cast<const char *>(name), namelen}; + std::string str_header_value{reinterpret_cast<const char *>(value), valuelen}; if (frame->hd.type == NGHTTP2_HCAT_REQUEST) { - auto request = h2_session->request(); + auto & request = h2_session->request(); request.HeaderValue(str_header_name, str_header_value); } else if (frame->hd.type == NGHTTP2_HCAT_RESPONSE) { - auto response = h2_session->response(); + auto & response = h2_session->response(); response.HeaderValue(str_header_name, str_header_value); } else if (frame->hd.type == NGHTTP2_HCAT_PUSH_RESPONSE) { - auto response = h2_session->response(); + auto & response = h2_session->response(); response.HeaderValue(str_header_name, str_header_value); } else @@ -333,8 +448,8 @@ int h2_downstream::cb_on_data_chunk_recv(nghttp2_session *session, uint8_t flags /* 构建Http请求内容,由于可能存在Content分为多个DATA帧传输的情况, * 将每片数据采用Append的方式构建HttpRequest对象 */ - auto h2_request = dynamic_cast<Http2Request &>(h2_session->request()); - h2_request.ConstructContent(static_cast<const char *>(data), len, true); + auto & h2_request = dynamic_cast<Http2Request &>(h2_session->request()); + h2_request.ConstructContent(reinterpret_cast<const char *>(data), len, true); return 0; } @@ -347,6 +462,7 @@ h2_upstream::h2_upstream(Http2Connection &conn) : conn_(conn) nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks_new(&callbacks); +#if 0 nghttp2_session_callbacks_set_send_callback(callbacks, cb_on_send); nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, cb_on_frame_recv); @@ -355,6 +471,7 @@ h2_upstream::h2_upstream(Http2Connection &conn) : conn_(conn) nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks, cb_on_header_begin); nghttp2_session_callbacks_set_on_header_callback(callbacks, cb_on_header); +#endif nghttp2_session *__tmp_session_ptr = nullptr; nghttp2_session_client_new(&__tmp_session_ptr, callbacks, this); diff --git a/src/httpscan.cc b/src/httpscan.cc index 8273b02..0ca8b70 100644 --- a/src/httpscan.cc +++ b/src/httpscan.cc @@ -39,24 +39,21 @@ HttpScan::HttpScan(struct tfe_instance *instance, struct tfe_config *config) table_id_ctrl_http_res_body = __maat_table_register_or_throw(maat_feather_ref, "PXY_CTRL_HTTP_RES_BODY"); auto http_module = instance->http_module; - - http_module->SetHttpConnectionNewCallback([this](Http &ht, HttpConnection & ct)->void + http_module->SetHttpConnectionNewCallback([this](Http &ht, HttpConnection &ct) -> void { this->handlerConnectionCreate(ct); }); - http_module->SetHttpConnectionCloseCallback([this](Http & ht, HttpConnection & ct)->void + http_module->SetHttpConnectionCloseCallback([this](Http &ht, HttpConnection &ct) -> void { this->handlerConnectionClose(ct); }); - - return; } void HttpScan::handlerConnectionCreate(HttpConnection &ct) { /* 新Session的创建处理函数 */ - ct.SetSessionNewCallback([this](HttpSession & session)->void + ct.SetSessionNewCallback([this](HttpSession &session) -> void { /* 创建HttpScan的Session Ctx */ auto __scan_ctx = std::make_shared<HttpScanSession>(*this); @@ -66,25 +63,25 @@ void HttpScan::handlerConnectionCreate(HttpConnection &ct) * 这样,回调时始终保持__scan_ctx的引用计数大于等于1, * 避免在回调过程中变更回调函数导致ctx析构。 */ - session.SetRequestHeaderCallback([__scan_ctx](HttpSession & session) + session.SetRequestHeaderCallback([__scan_ctx](HttpSession &session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx_stack->ScanRequestHeader(&session); }); - session.SetRequestBodyCallback([__scan_ctx](HttpSession & session) + session.SetRequestBodyCallback([__scan_ctx](HttpSession &session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanRequestBody(&session); }); - session.SetResponseHeaderCallback([__scan_ctx](HttpSession & session) + session.SetResponseHeaderCallback([__scan_ctx](HttpSession &session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanResponseHeader(&session); }); - session.SetResponseBodyCallback([__scan_ctx](HttpSession & session) + session.SetResponseBodyCallback([__scan_ctx](HttpSession &session) { auto __scan_ctx_stack = __scan_ctx; __scan_ctx->ScanResponseBody(&session); @@ -93,6 +90,30 @@ void HttpScan::handlerConnectionCreate(HttpConnection &ct) /* 不设置SessionClose的回调函数,相应的逻辑在HttpScanSession的析构函数中处理 */ ct.SetSessionCloseCallback(nullptr); +} + +void HttpScan::handlerConnectionClose(HttpConnection &ct) +{ + return; +} + +int HttpScan::connection_bypass_scan() +{ + return 0; +} + +int HttpScan::connection_bypass_do_action() +{ + return 0; +} + +std::unique_ptr<HttpScan> HttpScan::HttpScanFactory(struct tfe_instance *instance, struct tfe_config *config) +{ + std::unique_ptr<HttpScan> __this_ptr = std::make_unique<HttpScan>(instance, config); + + + + return std::move(__this_ptr); }; HttpScanSession::HttpScanSession(const HttpScan &httpscan_module) : @@ -107,13 +128,13 @@ HttpScanSession::~HttpScanSession() void HttpScanSession::ScanRequestHeader(HttpSession *http_session_ctx) { - auto & http_request = http_session_ctx->request(); + auto &http_request = http_session_ctx->request(); int dummy[MAAT_SCAN_RESULT_]; /* 扫描IP地址,获取连接对应的四元组 */ - const auto & connection = http_session_ctx->connection(); - const auto * sockaddr_src = connection.SockAddrSource(); - const auto * sockaddr_dst = connection.SockAddrDest(); + const auto &connection = http_session_ctx->connection(); + const auto *sockaddr_src = connection.SockAddrSource(); + const auto *sockaddr_dst = connection.SockAddrDest(); /* 转换为Sapp中的四元组结构体 */ auto sapp_tuple4_ptr = sockaddr_to_sapp_ipaddr(sockaddr_src, sockaddr_dst); @@ -129,7 +150,7 @@ void HttpScanSession::ScanRequestHeader(HttpSession *http_session_ctx) return hit_scan_error(); /* 扫描HTTP URL */ - const auto & __url = http_request.Url(); + const auto &__url = http_request.Url(); nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref, httpscan_module_ref_.table_id_ctrl_http_url, CHARSET_UTF8, __url.c_str(), (int) __url.length(), @@ -141,7 +162,7 @@ void HttpScanSession::ScanRequestHeader(HttpSession *http_session_ctx) return hit_scan_error(); /* 未命中HTTP URL,继续扫描其他HTTP头部字段 */ - http_request.ForEachHeader([this, http_session_ctx](const std::string & field, const std::string & value) + http_request.ForEachHeader([this, http_session_ctx](const std::string &field, const std::string &value) { /* 增强字符串表,设置区域字段,即Header字段 */ int ret = Maat_set_scan_status(httpscan_module_ref_.maat_feather_ref, &maat_scan_mid_, @@ -192,9 +213,9 @@ void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) if (maat_scan_result_[i].action <= action_type) do_action_id = i; } - Maat_rule_t * hit_maat_rule = &maat_scan_result_[do_action_id]; - auto __action_type = (enum HttpActionType)hit_maat_rule->action; - const char * __action_string = hit_maat_rule->service_defined; + Maat_rule_t *hit_maat_rule = &maat_scan_result_[do_action_id]; + auto __action_type = (enum HttpActionType) hit_maat_rule->action; + const char *__action_string = hit_maat_rule->service_defined; /* 创建HttpAction的对象 */ auto action_object = HttpActionFactory(__action_type, __action_string); @@ -204,25 +225,25 @@ void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) action_object->service_id(hit_maat_rule->service_id); /* 替换HttpSession的事件处理函数,以后的事件由HttpAction处理 */ - http_session_ctx->SetRequestHeaderCallback([action_object](HttpSession & session) + http_session_ctx->SetRequestHeaderCallback([action_object](HttpSession &session) { auto __action_object = action_object; __action_object->OnRequestHeader(&session); }); - http_session_ctx->SetRequestBodyCallback([action_object](HttpSession & session) + http_session_ctx->SetRequestBodyCallback([action_object](HttpSession &session) { auto __action_object = action_object; __action_object->OnRequestBody(&session); }); - http_session_ctx->SetResponseHeaderCallback([action_object](HttpSession & session) + http_session_ctx->SetResponseHeaderCallback([action_object](HttpSession &session) { auto __action_object = action_object; __action_object->OnResponseHeader(&session); }); - http_session_ctx->SetResponseBodyCallback([action_object](HttpSession & session) + http_session_ctx->SetResponseBodyCallback([action_object](HttpSession &session) { auto __action_object = action_object; __action_object->OnResponseBody(&session); @@ -232,21 +253,10 @@ void HttpScanSession::hit_config_and_do_action(HttpSession *http_session_ctx) log_dbg_printf("hit rule: service_id = %d, config_id = %d, action = %d\n", hit_maat_rule->service_id, hit_maat_rule->config_id, hit_maat_rule->action); - if (hit_maat_rule->do_blacklist) - { - - } - - if (hit_maat_rule->do_log) - { - - } - return; } void HttpScanSession::hit_scan_error() { return; -} -#pragma clang diagnostic pop
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/httpscan.h b/src/httpscan.h index 2665084..bef19ae 100644 --- a/src/httpscan.h +++ b/src/httpscan.h @@ -20,7 +20,6 @@ class HttpScan public: HttpScan(struct tfe_instance * instance, struct tfe_config *config); ~HttpScan() = default; - void handlerConnectionCreate(HttpConnection & ct); void handlerConnectionClose(HttpConnection & ct); diff --git a/src/logger.cc b/src/logger.cc index eba741d..17cec5e 100644 --- a/src/logger.cc +++ b/src/logger.cc @@ -8,6 +8,7 @@ extern "C" #include "logger.h" static std::vector<std::string> g_structlogger_topic; +std::vector<std::string> StructLoggerTopicRegister::topic_; void StructLogger::Log(const std::string &topic, Json::Value &struct_log) { diff --git a/src/main.cc b/src/main.cc index 65486af..f5882f0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -48,6 +48,10 @@ #include <openssl/x509.h> #include "httpscan.h" +#include "compat.h" + +#include "easylogging++.h" +INITIALIZE_EASYLOGGINGPP /* * Print version information to stderr. @@ -263,6 +267,7 @@ oom_die(const char *argv0) } struct tfe_instance * g_tfe_instance = new tfe_instance; +struct tfe_config * g_tfe_config = nullptr; /* * Main entry point. @@ -281,11 +286,15 @@ main(int argc, char *argv[]) argv0 = argv[0]; opts = tfe_config_new(); - if (nat_getdefaultname()) { + g_tfe_config = opts; + + if (nat_getdefaultname()) + { natengine = strdup(nat_getdefaultname()); if (!natengine) oom_die(argv0); - } else { + } else + { natengine = NULL; } @@ -571,6 +580,8 @@ main(int argc, char *argv[]) free(opts->contentlog_basedir); if (opts->contentlog) free(opts->contentlog); + +#if 0 if (log_content_split_pathspec(optarg, &lhs, &rhs) == -1) { fprintf(stderr, "%s: Failed to split " @@ -580,6 +591,8 @@ main(int argc, char *argv[]) strerror(errno), errno); exit(EXIT_FAILURE); } +#endif + /* eliminate %% from lhs */ for (p = q = lhs; *p; p++, q++) { if (q < p) @@ -666,10 +679,12 @@ main(int argc, char *argv[]) case 'd': opts->detach = 1; break; +#if 0 case 'D': log_dbg_mode(LOG_DBG_MODE_ERRLOG); opts->debug = 1; break; +#endif case 'V': main_version(); exit(EXIT_SUCCESS); @@ -741,14 +756,6 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } } -#ifdef __APPLE__ - if (opts->dropuser && !!strcmp(opts->dropuser, "root") && - nat_used("pf")) { - fprintf(stderr, "%s: cannot use 'pf' proxyspec with -u due " - "to Apple bug\n", argv0); - exit(EXIT_FAILURE); - } -#endif /* __APPLE__ */ /* prevent multiple instances running */ if (opts->pidfile) { @@ -869,10 +876,14 @@ main(int argc, char *argv[]) fprintf(stderr, "%s: failed to preinit cachemgr.\n", argv0); exit(EXIT_FAILURE); } + +#if 0 if (log_preinit(opts) == -1) { fprintf(stderr, "%s: failed to preinit logging.\n", argv0); exit(EXIT_FAILURE); } +#endif + if (nat_preinit() == -1) { fprintf(stderr, "%s: failed to preinit NAT lookup.\n", argv0); exit(EXIT_FAILURE); @@ -900,7 +911,11 @@ main(int argc, char *argv[]) argv0, strerror(errno)); exit(EXIT_FAILURE); } + +#if 0 log_err_mode(LOG_ERR_MODE_SYSLOG); +#endif + } if (opts->pidfile && (sys_pidf_write(pidfd) == -1)) { @@ -909,7 +924,8 @@ main(int argc, char *argv[]) return -1; } - g_tfe_instance->http_scan_module = new HttpScan(g_tfe_instance, opts); + g_tfe_instance->http_module = std::make_unique<Http>(g_tfe_instance, g_tfe_config); + g_tfe_instance->http_scan_module = std::make_unique<HttpScan>(g_tfe_instance, g_tfe_config); /* Fork into parent monitor process and (potentially unprivileged) * child process doing the actual work. We request 3 privsep client @@ -949,12 +965,16 @@ main(int argc, char *argv[]) goto out_sslreinit_failed; } +#if 0 /* Post-privdrop/chroot/detach initialization, thread spawning */ if (log_init(opts, proxy, clisock[1], clisock[2]) == -1) { fprintf(stderr, "%s: failed to init log facility: %s\n", argv0, strerror(errno)); goto out_log_failed; } + +#endif + if (cachemgr_init() == -1) { log_err_printf("Failed to init cache manager.\n"); goto out_cachemgr_failed; @@ -972,7 +992,9 @@ main(int argc, char *argv[]) out_nat_failed: cachemgr_fini(); out_cachemgr_failed: +#if 0 log_fini(); +#endif out_sslreinit_failed: out_log_failed: out_parent: @@ -37,6 +37,7 @@ #include <sys/socket.h> #include <Maat_rule.h> #include <string> +#include <memory> class HttpScan; class Http; @@ -70,9 +71,9 @@ struct tfe_instance void * maat_logger; /* HTTPSCAN */ - HttpScan * http_scan_module; + std::unique_ptr<HttpScan> http_scan_module; /* Http */ - Http * http_module; + std::unique_ptr<Http> http_module; }; struct tfe_maat_config diff --git a/src/proxy.cc b/src/proxy.cc index 93bd621..80ce3fd 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -51,22 +51,152 @@ #include <event2/bufferevent_ssl.h> #include <event2/buffer.h> #include <event2/thread.h> +#include <sys/un.h> +#include <cassert> /* * Proxy engine, built around libevent 2.x. */ -static int signals[] = { SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1 }; +#define TFE_STRING_MAX 2048 +#define TFE_BACKLOG_DEFAULT 20 + +class ForgeSocketListener +{ +public: + explicit ForgeSocketListener(struct event_base *evbase, const std::string &str_unix_domain); + virtual ~ForgeSocketListener(); + + using fds_arrive_cb_t = std::function<void(int fd1, int fd2)>; + void SetFdsArriveCallback(fds_arrive_cb_t cb) {} + +private: + struct event_base *ev_base_{nullptr}; + struct evconnlistener *ev_listener_{nullptr}; + std::map<evutil_socket_t, std::unique_ptr<Event>> ev_lookup_; + fds_arrive_cb_t fds_arrive_cb_; + +private: + void EventCallback(evutil_socket_t fd, short what); + +private: + /* 回调函数,listener发生错误时回调 */ + static void __listener_cb_error(struct evconnlistener *listener, void *user); + /* 回调函数,listener建立新的unix连接,即处理KNI启动的事件 */ + static void __listener_cb_new_connection(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *sk_addr, int sk_len, void *user); +}; + +ForgeSocketListener::ForgeSocketListener(struct event_base *evbase, const std::string &str_unix_domain) : ev_base_( + evbase) +{ + struct sockaddr_un __sockaddr_un{.sun_family = AF_UNIX}; + str_unix_domain.copy(__sockaddr_un.sun_path, sizeof(__sockaddr_un.sun_path), 0); + + ev_listener_ = evconnlistener_new_bind(ev_base_, __listener_cb_new_connection, this, 0, + TFE_BACKLOG_DEFAULT, static_cast<struct sockaddr *>(&__sockaddr_un), sizeof(__sockaddr_un)); + + if (ev_listener_ == nullptr) + { + throw std::runtime_error(string_format("Failed at create evconnlistener for unix domain socket: %s", + str_unix_domain.c_str())); + } + + return; +} + +ForgeSocketListener::~ForgeSocketListener() +{ + if (ev_listener_ != nullptr) evconnlistener_free(ev_listener_); +} + +void ForgeSocketListener::__listener_cb_new_connection(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *sk_addr, int sk_len, void *user) +{ + auto *__this_ptr = static_cast<ForgeSocketListener *>(user); + std::unique_ptr<Event> ev_ptr = std::make_unique<Event>(); + + ev_ptr->Init(__this_ptr->ev_base_, fd, EV_READ, [__this_ptr](evutil_socket_t fd, short what) + { + __this_ptr->EventCallback(fd, what); + }); + + __this_ptr->ev_lookup_[fd] = std::move(ev_ptr); + return; +} + +void ForgeSocketListener::__listener_cb_error(struct evconnlistener *listener, void *user) +{ + return; +} + +void ForgeSocketListener::EventCallback(evutil_socket_t fd, short what) +{ + assert(what & EV_READ); + assert(fds_arrive_cb_ != nullptr); + + /* 使用IOVEC,接收KNI传来的文件描述符 + * 这是一种特殊的文件描述符传递技巧,可以在多进程之间共享同一个Socket句柄 + */ + constexpr static auto __TRANS_FDS_MAX = 2; + constexpr static auto __CONTROLLEN = CMSG_SPACE(__TRANS_FDS_MAX * sizeof(int)); + + struct iovec __iovec[1]; + char __cmptr[__CONTROLLEN]; + + struct msghdr __msghdr = + { + .msg_iov = __iovec, + .msg_iovlen = 1, + .msg_name = nullptr, + .msg_namelen = 0, + .msg_control = static_cast<void *>(__cmptr), + .msg_controllen = __CONTROLLEN + }; + + ssize_t rd = recvmsg(fd, &__msghdr, 0); + + /* fd的常规套路 */ + if (rd < 0 && errno == EWOULDBLOCK) + { + return; + } + else if (rd < 0) + { + PLOG(ERROR) << string_format("Forge socket connection breaked, conn fd = %d", fd); + goto __close_this_connection; + } + else if (rd == 0) + { + PLOG(INFO) << string_format("Forge socket connection closed, conn fd = %d", fd); + goto __close_this_connection; + } + + struct cmsghdr * __cmsghdr = CMSG_FIRSTHDR(&__msghdr); + assert(__cmsghdr != nullptr); + + /* 接收到的FD对,调用用户注册函数 */ + int * __fds = (int *)(CMSG_DATA(__cmsghdr)); + + LOG(DEBUG) << string_format("Forge Socket FD recieved, fds[0] = %d, fds[1] = %d", __fds[0], __fds[1]); + fds_arrive_cb_(__fds[0], __fds[1]); + +__close_this_connection: + ev_lookup_.erase(fd); + return; +} + +static int signals[] = {SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1}; struct proxy_ctx { tfe_thread_manager_ctx *thrmgr; - struct event_base *evbase; - struct event *sev[sizeof(signals)/sizeof(int)]; - struct event *gcev; - struct proxy_listener_ctx *lctx; - struct tfe_config *opts; + struct event_base *evbase; + struct event *sev[sizeof(signals) / sizeof(int)]; + struct event *gcev; + struct proxy_listener_ctx *lctx; + struct tfe_config *opts; }; /* @@ -75,29 +205,27 @@ struct proxy_ctx typedef struct proxy_listener_ctx { tfe_thread_manager_ctx *thrmgr; - struct proxyspec *spec; - struct tfe_config *opts; - struct evconnlistener *evcl; - struct proxy_listener_ctx *next; - + struct proxyspec *spec; + struct tfe_config *opts; + struct evconnlistener *evcl; + struct proxy_listener_ctx *next; } proxy_listener_ctx_t; static proxy_listener_ctx_t * proxy_listener_ctx_new(tfe_thread_manager_ctx *thrmgr, proxyspec *spec, - tfe_config *opts) MALLOC; + tfe_config *opts) MALLOC; -static proxy_listener_ctx_t * -proxy_listener_ctx_new(tfe_thread_manager_ctx *thrmgr, proxyspec *spec, - tfe_config *opts) +static proxy_listener_ctx_t * proxy_listener_ctx_new( + tfe_thread_manager_ctx *thrmgr, proxyspec *spec, tfe_config *opts) { - proxy_listener_ctx_t *ctx = (proxy_listener_ctx_t *)malloc(sizeof(proxy_listener_ctx_t)); - if (!ctx) - return NULL; - memset(ctx, 0, sizeof(proxy_listener_ctx_t)); - ctx->thrmgr = thrmgr; - ctx->spec = spec; - ctx->opts = opts; - return ctx; + proxy_listener_ctx_t *ctx = (proxy_listener_ctx_t *) malloc(sizeof(proxy_listener_ctx_t)); + if (!ctx) + return NULL; + memset(ctx, 0, sizeof(proxy_listener_ctx_t)); + ctx->thrmgr = thrmgr; + ctx->spec = spec; + ctx->opts = opts; + return ctx; } static void @@ -105,13 +233,15 @@ proxy_listener_ctx_free(proxy_listener_ctx_t *ctx) NONNULL(1); static void proxy_listener_ctx_free(proxy_listener_ctx_t *ctx) { - if (ctx->evcl) { - evconnlistener_free(ctx->evcl); - } - if (ctx->next) { - proxy_listener_ctx_free(ctx->next); - } - free(ctx); + if (ctx->evcl) + { + evconnlistener_free(ctx->evcl); + } + if (ctx->next) + { + proxy_listener_ctx_free(ctx->next); + } + free(ctx); } /* @@ -119,14 +249,12 @@ proxy_listener_ctx_free(proxy_listener_ctx_t *ctx) */ static void proxy_listener_acceptcb(UNUSED struct evconnlistener *listener, - evutil_socket_t fd, - struct sockaddr *peeraddr, int peeraddrlen, - void *arg) + evutil_socket_t fd, + struct sockaddr *peeraddr, int peeraddrlen, + void *arg) { - proxy_listener_ctx_t *cfg = arg; - - pxy_conn_setup(fd, peeraddr, peeraddrlen, cfg->thrmgr, - cfg->spec, cfg->opts); + proxy_listener_ctx_t *cfg = (proxy_listener_ctx_t *) arg; + pxy_conn_setup(fd, peeraddr, peeraddrlen, cfg->thrmgr, cfg->spec, cfg->opts); } /* @@ -135,11 +263,11 @@ proxy_listener_acceptcb(UNUSED struct evconnlistener *listener, static void proxy_listener_errorcb(struct evconnlistener *listener, UNUSED void *ctx) { - struct event_base *evbase = evconnlistener_get_base(listener); - int err = EVUTIL_SOCKET_ERROR(); - log_err_printf("Error %d on listener: %s\n", err, - evutil_socket_error_to_string(err)); - event_base_loopbreak(evbase); + struct event_base *evbase = evconnlistener_get_base(listener); + int err = EVUTIL_SOCKET_ERROR(); + log_err_printf("Error %d on listener: %s\n", err, + evutil_socket_error_to_string(err)); + event_base_loopbreak(evbase); } /* @@ -148,15 +276,15 @@ proxy_listener_errorcb(struct evconnlistener *listener, UNUSED void *ctx) static void proxy_debug_base(const struct event_base *ev_base) { - log_dbg_printf("Using libevent backend '%s'\n", - event_base_get_method(ev_base)); - - enum event_method_feature f; - f = event_base_get_features(ev_base); - log_dbg_printf("Event base supports: edge %s, O(1) %s, anyfd %s\n", - ((f & EV_FEATURE_ET) ? "yes" : "no"), - ((f & EV_FEATURE_O1) ? "yes" : "no"), - ((f & EV_FEATURE_FDS) ? "yes" : "no")); + log_dbg_printf("Using libevent backend '%s'\n", + event_base_get_method(ev_base)); + + enum event_method_feature f; + f = event_base_get_features(ev_base); + log_dbg_printf("Event base supports: edge %s, O(1) %s, anyfd %s\n", + ((f & EV_FEATURE_ET) ? "yes" : "no"), + ((f & EV_FEATURE_O1) ? "yes" : "no"), + ((f & EV_FEATURE_FDS) ? "yes" : "no")); } /* @@ -165,35 +293,38 @@ proxy_debug_base(const struct event_base *ev_base) */ static proxy_listener_ctx_t * proxy_listener_setup(struct event_base *evbase, tfe_thread_manager_ctx *thrmgr, - proxyspec *spec, tfe_config *opts, int clisock) + proxyspec *spec, tfe_config *opts, int clisock) { - proxy_listener_ctx_t *plc; - int fd; - - if ((fd = privsep_client_opensock(clisock, spec)) == -1) { - log_err_printf("Error opening socket: %s (%i)\n", - strerror(errno), errno); - return NULL; - } - - plc = proxy_listener_ctx_new(thrmgr, spec, opts); - if (!plc) { - log_err_printf("Error creating listener context\n"); - evutil_closesocket(fd); - return NULL; - } - - plc->evcl = evconnlistener_new(evbase, proxy_listener_acceptcb, - plc, LEV_OPT_CLOSE_ON_FREE, 1024, fd); - if (!plc->evcl) { - log_err_printf("Error creating evconnlistener: %s\n", - strerror(errno)); - proxy_listener_ctx_free(plc); - evutil_closesocket(fd); - return NULL; - } - evconnlistener_set_error_cb(plc->evcl, proxy_listener_errorcb); - return plc; + proxy_listener_ctx_t *plc; + int fd; + + if ((fd = privsep_client_opensock(clisock, spec)) == -1) + { + log_err_printf("Error opening socket: %s (%i)\n", + strerror(errno), errno); + return NULL; + } + + plc = proxy_listener_ctx_new(thrmgr, spec, opts); + if (!plc) + { + log_err_printf("Error creating listener context\n"); + evutil_closesocket(fd); + return NULL; + } + + plc->evcl = evconnlistener_new(evbase, proxy_listener_acceptcb, + plc, LEV_OPT_CLOSE_ON_FREE, 1024, fd); + if (!plc->evcl) + { + log_err_printf("Error creating evconnlistener: %s\n", + strerror(errno)); + proxy_listener_ctx_free(plc); + evutil_closesocket(fd); + return NULL; + } + evconnlistener_set_error_cb(plc->evcl, proxy_listener_errorcb); + return plc; } /* @@ -202,37 +333,36 @@ proxy_listener_setup(struct event_base *evbase, tfe_thread_manager_ctx *thrmgr, static void proxy_signal_cb(evutil_socket_t fd, UNUSED short what, void *arg) { - proxy_ctx_t *ctx = arg; + proxy_ctx_t *ctx = arg; - if (OPTS_DEBUG(ctx->opts)) { - log_dbg_printf("Received signal %i\n", fd); - } + if (OPTS_DEBUG(ctx->opts)) + { + log_dbg_printf("Received signal %i\n", fd); + } - switch(fd) { - case SIGTERM: - case SIGQUIT: - case SIGINT: - case SIGHUP: - proxy_loopbreak(ctx); - break; + switch (fd) + { + case SIGTERM: + case SIGQUIT: + case SIGINT: + case SIGHUP: proxy_loopbreak(ctx); + break; #if 0 - case SIGUSR1: - if (log_reopen() == -1) { - log_err_printf("Warning: Failed to reopen logs\n"); - } else { - log_dbg_printf("Reopened log files\n"); - } - break; + case SIGUSR1: + if (log_reopen() == -1) { + log_err_printf("Warning: Failed to reopen logs\n"); + } else { + log_dbg_printf("Reopened log files\n"); + } + break; #endif - case SIGPIPE: - log_err_printf("Warning: Received SIGPIPE; ignoring.\n"); - break; - default: - log_err_printf("Warning: Received unexpected signal %i\n", fd); - break; - } + case SIGPIPE: log_err_printf("Warning: Received SIGPIPE; ignoring.\n"); + break; + default: log_err_printf("Warning: Received unexpected signal %i\n", fd); + break; + } } /* @@ -241,15 +371,15 @@ proxy_signal_cb(evutil_socket_t fd, UNUSED short what, void *arg) static void proxy_gc_cb(UNUSED evutil_socket_t fd, UNUSED short what, void *arg) { - proxy_ctx_t *ctx = arg; + proxy_ctx_t *ctx = (proxy_ctx_t *) arg; - if (OPTS_DEBUG(ctx->opts)) - log_dbg_printf("Garbage collecting caches started.\n"); + if (OPTS_DEBUG(ctx->opts)) + log_dbg_printf("Garbage collecting caches started.\n"); - cachemgr_gc(); + cachemgr_gc(); - if (OPTS_DEBUG(ctx->opts)) - log_dbg_printf("Garbage collecting caches done.\n"); + if (OPTS_DEBUG(ctx->opts)) + log_dbg_printf("Garbage collecting caches done.\n"); } /* @@ -257,122 +387,135 @@ proxy_gc_cb(UNUSED evutil_socket_t fd, UNUSED short what, void *arg) * Socket clisock is the privsep client socket used for binding to ports. * Returns ctx on success, or NULL on error. */ -proxy_ctx_t * -proxy_new(tfe_config *opts, int clisock) +proxy_ctx_t *proxy_new(tfe_config *opts, int clisock) { - proxy_listener_ctx_t *head; - proxy_ctx_t *ctx; - struct evdns_base *dnsbase; - int rc; + proxy_listener_ctx_t *head; + proxy_ctx_t *ctx; + struct evdns_base *dnsbase; + int rc; - struct timeval gc_delay = {60, 0}; + struct timeval gc_delay = {60, 0}; - /* adds locking, only required if accessed from separate threads */ - evthread_use_pthreads(); + /* adds locking, only required if accessed from separate threads */ + evthread_use_pthreads(); #ifndef PURIFY - if (OPTS_DEBUG(opts)) { - event_enable_debug_mode(); - } + if (OPTS_DEBUG(opts)) + { + event_enable_debug_mode(); + } #endif /* PURIFY */ - ctx = malloc(sizeof(proxy_ctx_t)); - if (!ctx) { - log_err_printf("Error allocating memory\n"); - goto leave0; - } - memset(ctx, 0, sizeof(proxy_ctx_t)); - - ctx->opts = opts; - ctx->evbase = event_base_new(); - if (!ctx->evbase) { - log_err_printf("Error getting event base\n"); - goto leave1; - } - - if (tfe_config_has_dns_spec(opts)) { - /* create a dnsbase here purely for being able to test parsing - * resolv.conf while we can still alert the user about it. */ - dnsbase = evdns_base_new(ctx->evbase, 0); - if (!dnsbase) { - log_err_printf("Error creating dns event base\n"); - goto leave1b; - } - rc = evdns_base_resolv_conf_parse(dnsbase, DNS_OPTIONS_ALL, - "/etc/resolv.conf"); - evdns_base_free(dnsbase, 0); - if (rc != 0) { - log_err_printf("evdns cannot parse resolv.conf: " - "%s (%d)\n", - rc == 1 ? "failed to open file" : - rc == 2 ? "failed to stat file" : - rc == 3 ? "file too large" : - rc == 4 ? "out of memory" : - rc == 5 ? "short read from file" : - rc == 6 ? "no nameservers in file" : - "unknown error", rc); - goto leave1b; - } - } - - if (OPTS_DEBUG(opts)) { - proxy_debug_base(ctx->evbase); - } - - ctx->thrmgr = tfe_thread_manager_new(opts); - if (!ctx->thrmgr) { - log_err_printf("Error creating thread manager\n"); - goto leave1b; - } - - head = ctx->lctx = NULL; - for (proxyspec *spec = opts->spec; spec; spec = spec->next) { - head = proxy_listener_setup(ctx->evbase, ctx->thrmgr, - spec, opts, clisock); - if (!head) - goto leave2; - head->next = ctx->lctx; - ctx->lctx = head; - } - - for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++) { - ctx->sev[i] = evsignal_new(ctx->evbase, signals[i], - proxy_signal_cb, ctx); - if (!ctx->sev[i]) - goto leave3; - evsignal_add(ctx->sev[i], NULL); - } - - ctx->gcev = event_new(ctx->evbase, -1, EV_PERSIST, proxy_gc_cb, ctx); - if (!ctx->gcev) - goto leave4; - evtimer_add(ctx->gcev, &gc_delay); - - privsep_client_close(clisock); - return ctx; + ctx = malloc(sizeof(proxy_ctx_t)); + if (!ctx) + { + log_err_printf("Error allocating memory\n"); + goto leave0; + } + memset(ctx, 0, sizeof(proxy_ctx_t)); + + ctx->opts = opts; + ctx->evbase = event_base_new(); + if (!ctx->evbase) + { + log_err_printf("Error getting event base\n"); + goto leave1; + } + + if (tfe_config_has_dns_spec(opts)) + { + /* create a dnsbase here purely for being able to test parsing + * resolv.conf while we can still alert the user about it. */ + dnsbase = evdns_base_new(ctx->evbase, 0); + if (!dnsbase) + { + log_err_printf("Error creating dns event base\n"); + goto leave1b; + } + rc = evdns_base_resolv_conf_parse(dnsbase, DNS_OPTIONS_ALL, + "/etc/resolv.conf"); + evdns_base_free(dnsbase, 0); + if (rc != 0) + { + log_err_printf("evdns cannot parse resolv.conf: " + "%s (%d)\n", + rc == 1 ? "failed to open file" : + rc == 2 ? "failed to stat file" : + rc == 3 ? "file too large" : + rc == 4 ? "out of memory" : + rc == 5 ? "short read from file" : + rc == 6 ? "no nameservers in file" : + "unknown error", rc); + goto leave1b; + } + } + + if (OPTS_DEBUG(opts)) + { + proxy_debug_base(ctx->evbase); + } + + ctx->thrmgr = tfe_thread_manager_new(opts); + if (!ctx->thrmgr) + { + log_err_printf("Error creating thread manager\n"); + goto leave1b; + } + + head = ctx->lctx = NULL; + for (proxyspec *spec = opts->spec; spec; spec = spec->next) + { + head = proxy_listener_setup(ctx->evbase, ctx->thrmgr, + spec, opts, clisock); + if (!head) + goto leave2; + head->next = ctx->lctx; + ctx->lctx = head; + } + + for (size_t i = 0; i < (sizeof(signals) / sizeof(int)); i++) + { + ctx->sev[i] = evsignal_new(ctx->evbase, signals[i], + proxy_signal_cb, ctx); + if (!ctx->sev[i]) + goto leave3; + evsignal_add(ctx->sev[i], NULL); + } + + ctx->gcev = event_new(ctx->evbase, -1, EV_PERSIST, proxy_gc_cb, ctx); + if (!ctx->gcev) + goto leave4; + evtimer_add(ctx->gcev, &gc_delay); + + privsep_client_close(clisock); + return ctx; leave4: - if (ctx->gcev) { - event_free(ctx->gcev); - } + if (ctx->gcev) + { + event_free(ctx->gcev); + } leave3: - for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) { - if (ctx->sev[i]) { - event_free(ctx->sev[i]); - } - } + for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) + { + if (ctx->sev[i]) + { + event_free(ctx->sev[i]); + } + } leave2: - if (ctx->lctx) { - proxy_listener_ctx_free(ctx->lctx); - } + if (ctx->lctx) + { + proxy_listener_ctx_free(ctx->lctx); + } tfe_thread_manager_free(ctx->thrmgr); leave1b: - event_base_free(ctx->evbase); + event_base_free(ctx->evbase); leave1: - free(ctx); + free(ctx); leave0: - return NULL; + return NULL; } /* @@ -382,25 +525,30 @@ leave0: void proxy_run(proxy_ctx_t *ctx) { - if (ctx->opts->detach) { - event_reinit(ctx->evbase); - } + if (ctx->opts->detach) + { + event_reinit(ctx->evbase); + } #ifndef PURIFY - if (OPTS_DEBUG(ctx->opts)) { - event_base_dump_events(ctx->evbase, stderr); - } + if (OPTS_DEBUG(ctx->opts)) + { + event_base_dump_events(ctx->evbase, stderr); + } #endif /* PURIFY */ - if (tfe_thread_manager_run(ctx->thrmgr) == -1) { - log_err_printf("Failed to start thread manager\n"); - return; - } - if (OPTS_DEBUG(ctx->opts)) { - log_dbg_printf("Starting main event loop.\n"); - } - event_base_dispatch(ctx->evbase); - if (OPTS_DEBUG(ctx->opts)) { - log_dbg_printf("Main event loop stopped.\n"); - } + if (tfe_thread_manager_run(ctx->thrmgr) == -1) + { + log_err_printf("Failed to start thread manager\n"); + return; + } + if (OPTS_DEBUG(ctx->opts)) + { + log_dbg_printf("Starting main event loop.\n"); + } + event_base_dispatch(ctx->evbase); + if (OPTS_DEBUG(ctx->opts)) + { + log_dbg_printf("Main event loop stopped.\n"); + } } /* @@ -409,7 +557,7 @@ proxy_run(proxy_ctx_t *ctx) void proxy_loopbreak(proxy_ctx_t *ctx) { - event_base_loopbreak(ctx->evbase); + event_base_loopbreak(ctx->evbase); } /* @@ -418,24 +566,30 @@ proxy_loopbreak(proxy_ctx_t *ctx) void proxy_free(proxy_ctx_t *ctx) { - if (ctx->gcev) { - event_free(ctx->gcev); - } - if (ctx->lctx) { - proxy_listener_ctx_free(ctx->lctx); - } - for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) { - if (ctx->sev[i]) { - event_free(ctx->sev[i]); - } - } - if (ctx->thrmgr) { + if (ctx->gcev) + { + event_free(ctx->gcev); + } + if (ctx->lctx) + { + proxy_listener_ctx_free(ctx->lctx); + } + for (size_t i = 0; i < (sizeof(ctx->sev) / sizeof(ctx->sev[0])); i++) + { + if (ctx->sev[i]) + { + event_free(ctx->sev[i]); + } + } + if (ctx->thrmgr) + { tfe_thread_manager_free(ctx->thrmgr); - } - if (ctx->evbase) { - event_base_free(ctx->evbase); - } - free(ctx); + } + if (ctx->evbase) + { + event_base_free(ctx->evbase); + } + free(ctx); } /* vim: set noet ft=c: */ diff --git a/src/pxyconn.cc b/src/pxyconn.cc index 6833865..28d9469 100644 --- a/src/pxyconn.cc +++ b/src/pxyconn.cc @@ -38,6 +38,7 @@ #include "url.h" #include "compat.h" #include "attrib.h" +#include "http.h" #include <netinet/in.h> #include <stdlib.h> @@ -76,35 +77,16 @@ static unsigned long ssl_session_context = 0x31415926; #endif /* USE_SSL_SESSION_ID_CONTEXT */ -#ifdef HAVE_LOCAL_PROCINFO -/* local process data - filled in iff pid != -1 */ -typedef struct pxy_conn_lproc_desc { - struct sockaddr_storage srcaddr; - socklen_t srcaddrlen; - - pid_t pid; - uid_t uid; - gid_t gid; - - /* derived log strings */ - char *exec_path; - char *user; - char *group; -} pxy_conn_lproc_desc_t; -#endif /* HAVE_LOCAL_PROCINFO */ - #define WANT_CONNECT_LOG(ctx) ((ctx)->opts->connectlog||!(ctx)->opts->detach) #define WANT_CONTENT_LOG(ctx) ((ctx)->opts->contentlog&&!(ctx)->passthrough) static pxy_conn_ctx_t * -pxy_conn_ctx_new( - proxyspec *spec, tfe_config *opts, - tfe_thread_manager_ctx *thrmgr, evutil_socket_t fd) +pxy_conn_ctx_new(proxyspec *spec, tfe_config *opts, tfe_thread_manager_ctx *thrmgr, evutil_socket_t fd) MALLOC NONNULL(1, 2, 3); static pxy_conn_ctx_t * pxy_conn_ctx_new(proxyspec *spec, tfe_config *opts, tfe_thread_manager_ctx *thrmgr, evutil_socket_t fd) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)malloc(sizeof(pxy_conn_ctx_t)); + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) malloc(sizeof(pxy_conn_ctx_t)); if (!ctx) return NULL; memset(ctx, 0, sizeof(pxy_conn_ctx_t)); @@ -127,19 +109,11 @@ pxy_conn_ctx_new(proxyspec *spec, tfe_config *opts, tfe_thread_manager_ctx *thrm static void NONNULL(1) pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor) { -#ifdef DEBUG_PROXY - if (OPTS_DEBUG(ctx->opts)) { + if (OPTS_DEBUG(ctx->opts)) + { log_dbg_printf("%p pxy_conn_ctx_free\n", (void*)ctx); } -#endif /* DEBUG_PROXY */ - if (WANT_CONTENT_LOG(ctx) && ctx->logctx) - { - if (log_content_close(&ctx->logctx, by_requestor) == -1) - { - log_err_printf("Warning: Content log close failed\n"); - } - } tfe_thread_manager_detach(ctx->thrmgr, ctx->thridx); @@ -211,6 +185,7 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor) { free(ctx->sni); } + free(ctx); } @@ -256,7 +231,8 @@ static void pxy_debug_crt(X509 *crt) if (!(fpr = ssl_x509_fingerprint(crt, 1))) { log_err_printf("Warning: Error generating X509 fingerprint\n"); - } else + } + else { log_dbg_printf("Fingerprint: %s\n", fpr); free(fpr); @@ -273,27 +249,8 @@ static void pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx) { char *msg; -#ifdef HAVE_LOCAL_PROCINFO - char *lpi = NULL; -#endif /* HAVE_LOCAL_PROCINFO */ int rv; -#ifdef HAVE_LOCAL_PROCINFO - if (ctx->opts->lprocinfo) { - rv = asprintf(&lpi, "lproc:%i:%s:%s:%s", - ctx->lproc.pid, - STRORDASH(ctx->lproc.user), - STRORDASH(ctx->lproc.group), - STRORDASH(ctx->lproc.exec_path)); - if ((rv < 0) || !lpi) { - ctx->enomem = 1; - goto out; - } - } else { - lpi = ""; - } -#endif /* HAVE_LOCAL_PROCINFO */ - /* * The following ifdef's within asprintf arguments list generates * warnings with -Wembedded-directive on some compilers. @@ -307,41 +264,32 @@ pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx) " %s" #endif /* HAVE_LOCAL_PROCINFO */ "\n", - ctx->passthrough ? "passthrough" : "tcp", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str) -#ifdef HAVE_LOCAL_PROCINFO - , lpi -#endif /* HAVE_LOCAL_PROCINFO */ + ctx->passthrough ? "passthrough" : "tcp", + STRORDASH(ctx->srchost_str), + STRORDASH(ctx->srcport_str), + STRORDASH(ctx->dsthost_str), + STRORDASH(ctx->dstport_str) ); - } else + } + else { rv = asprintf(&msg, "%s %s %s %s %s " "sni:%s names:%s " "sproto:%s:%s dproto:%s:%s " - "origcrt:%s usedcrt:%s" - #ifdef HAVE_LOCAL_PROCINFO - " %s" - #endif /* HAVE_LOCAL_PROCINFO */ - "\n", - ctx->clienthello_found ? "upgrade" : "ssl", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->sni), - STRORDASH(ctx->ssl_names), - SSL_get_version(ctx->src.ssl), - SSL_get_cipher(ctx->src.ssl), - SSL_get_version(ctx->dst.ssl), - SSL_get_cipher(ctx->dst.ssl), - STRORDASH(ctx->origcrtfpr), - STRORDASH(ctx->usedcrtfpr) -#ifdef HAVE_LOCAL_PROCINFO - , lpi -#endif /* HAVE_LOCAL_PROCINFO */ + "origcrt:%s usedcrt:%s\n", + ctx->clienthello_found ? "upgrade" : "ssl", + STRORDASH(ctx->srchost_str), + STRORDASH(ctx->srcport_str), + STRORDASH(ctx->dsthost_str), + STRORDASH(ctx->dstport_str), + STRORDASH(ctx->sni), + STRORDASH(ctx->ssl_names), + SSL_get_version(ctx->src.ssl), + SSL_get_cipher(ctx->src.ssl), + SSL_get_version(ctx->dst.ssl), + SSL_get_cipher(ctx->dst.ssl), + STRORDASH(ctx->origcrtfpr), + STRORDASH(ctx->usedcrtfpr) ); } if ((rv < 0) || !msg) @@ -355,21 +303,12 @@ pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx) } if (ctx->opts->connectlog) { - if (log_connect_print_free(msg) == -1) - { - free(msg); - log_err_printf("Warning: Connection logging failed\n"); - } - } else + } + else { free(msg); } out: -#ifdef HAVE_LOCAL_PROCINFO - if (lpi && ctx->opts->lprocinfo) { - free(lpi); - } -#endif /* HAVE_LOCAL_PROCINFO */ return; } @@ -397,17 +336,18 @@ pxy_log_connect_http(pxy_conn_ctx_t *ctx) if (!ctx->spec->ssl) { rv = asprintf(&msg, "http %s %s %s %s %s %s %s %s %s %s\n", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->http_host), - STRORDASH(ctx->http_method), - STRORDASH(ctx->http_uri), - STRORDASH(ctx->http_status_code), - STRORDASH(ctx->http_content_length), - ctx->ocsp_denied ? " ocsp:denied" : ""); - } else + STRORDASH(ctx->srchost_str), + STRORDASH(ctx->srcport_str), + STRORDASH(ctx->dsthost_str), + STRORDASH(ctx->dstport_str), + STRORDASH(ctx->http_host), + STRORDASH(ctx->http_method), + STRORDASH(ctx->http_uri), + STRORDASH(ctx->http_status_code), + STRORDASH(ctx->http_content_length), + ctx->ocsp_denied ? " ocsp:denied" : ""); + } + else { rv = asprintf(&msg, "https %s %s %s %s %s %s %s %s %s " "sni:%s names:%s " @@ -417,24 +357,24 @@ pxy_log_connect_http(pxy_conn_ctx_t *ctx) " %s" #endif /* HAVE_LOCAL_PROCINFO */ "%s\n", - STRORDASH(ctx->srchost_str), - STRORDASH(ctx->srcport_str), - STRORDASH(ctx->dsthost_str), - STRORDASH(ctx->dstport_str), - STRORDASH(ctx->http_host), - STRORDASH(ctx->http_method), - STRORDASH(ctx->http_uri), - STRORDASH(ctx->http_status_code), - STRORDASH(ctx->http_content_length), - STRORDASH(ctx->sni), - STRORDASH(ctx->ssl_names), - SSL_get_version(ctx->src.ssl), - SSL_get_cipher(ctx->src.ssl), - SSL_get_version(ctx->dst.ssl), - SSL_get_cipher(ctx->dst.ssl), - STRORDASH(ctx->origcrtfpr), - STRORDASH(ctx->usedcrtfpr), - ctx->ocsp_denied ? " ocsp:denied" : ""); + STRORDASH(ctx->srchost_str), + STRORDASH(ctx->srcport_str), + STRORDASH(ctx->dsthost_str), + STRORDASH(ctx->dstport_str), + STRORDASH(ctx->http_host), + STRORDASH(ctx->http_method), + STRORDASH(ctx->http_uri), + STRORDASH(ctx->http_status_code), + STRORDASH(ctx->http_content_length), + STRORDASH(ctx->sni), + STRORDASH(ctx->ssl_names), + SSL_get_version(ctx->src.ssl), + SSL_get_cipher(ctx->src.ssl), + SSL_get_version(ctx->dst.ssl), + SSL_get_cipher(ctx->dst.ssl), + STRORDASH(ctx->origcrtfpr), + STRORDASH(ctx->usedcrtfpr), + ctx->ocsp_denied ? " ocsp:denied" : ""); } if ((rv < 0) || !msg) { @@ -447,12 +387,9 @@ pxy_log_connect_http(pxy_conn_ctx_t *ctx) } if (ctx->opts->connectlog) { - if (log_connect_print_free(msg) == -1) - { - free(msg); - log_err_printf("Warning: Connection logging failed\n"); - } - } else + } + + else { free(msg); } @@ -539,7 +476,7 @@ pxy_ossl_sessget_cb(UNUSED SSL *ssl, const unsigned char *id, int idlen, int *co #endif /* DEBUG_SESSION_CACHE */ *copy = 0; /* SSL should not increment reference count of session */ - sess = (SSL_SESSION *)cachemgr_ssess_get(id, idlen); + sess = (SSL_SESSION *) cachemgr_ssess_get(id, idlen); #ifdef DEBUG_SESSION_CACHE if (sess) { @@ -619,7 +556,7 @@ pxy_sslctx_setoptions(SSL_CTX *sslctx, pxy_conn_ctx_t *ctx) * Create and set up a new SSL_CTX instance for terminating SSL. * Set up all the necessary callbacks, the certificate, the cert chain and key. */ -static SSL_CTX * pxy_srcsslctx_create( +static SSL_CTX *pxy_srcsslctx_create( pxy_conn_ctx_t *ctx, X509 *crt, STACK_OF(X509) *chain, EVP_PKEY *key) { @@ -656,7 +593,8 @@ static SSL_CTX * pxy_srcsslctx_create( if (ctx->opts->dh) { SSL_CTX_set_tmp_dh(sslctx, ctx->opts->dh); - } else + } + else { SSL_CTX_set_tmp_dh_callback(sslctx, ssl_tmp_dh_callback); } @@ -667,7 +605,8 @@ static SSL_CTX * pxy_srcsslctx_create( EC_KEY *ecdh = ssl_ec_by_name(ctx->opts->ecdhcurve); SSL_CTX_set_tmp_ecdh(sslctx, ecdh); EC_KEY_free(ecdh); - } else + } + else { EC_KEY *ecdh = ssl_ec_by_name(NULL); SSL_CTX_set_tmp_ecdh(sslctx, ecdh); @@ -716,20 +655,21 @@ pxy_srccert_write_to_gendir(pxy_conn_ctx_t *ctx, X509 *crt, int is_orig) if (is_orig) { rv = asprintf(&fn, "%s/%s.crt", ctx->opts->certgendir, - ctx->origcrtfpr); - } else + ctx->origcrtfpr); + } + else { if (!ctx->usedcrtfpr) return -1; rv = asprintf(&fn, "%s/%s-%s.crt", ctx->opts->certgendir, - ctx->origcrtfpr, ctx->usedcrtfpr); + ctx->origcrtfpr, ctx->usedcrtfpr); } if (rv == -1) { ctx->enomem = 1; return -1; } - rv = log_cert_submit(fn, crt); + free(fn); return rv; } @@ -739,7 +679,7 @@ static void pxy_srccert_write(pxy_conn_ctx_t *ctx) if (ctx->opts->certgen_writeall || ctx->generated_cert) { if (pxy_srccert_write_to_gendir(ctx, - SSL_get_certificate(ctx->src.ssl), 0) == -1) + SSL_get_certificate(ctx->src.ssl), 0) == -1) { log_err_printf("Failed to write used certificate\n"); } @@ -753,14 +693,14 @@ static void pxy_srccert_write(pxy_conn_ctx_t *ctx) } } -static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) +static cert_t *pxy_srccert_create(pxy_conn_ctx_t *ctx) { cert_t *cert = NULL; if (ctx->opts->tgcrtdir) { if (ctx->sni) { - cert = (cert_t *)cachemgr_tgcrt_get(ctx->sni); + cert = (cert_t *) cachemgr_tgcrt_get(ctx->sni); if (!cert) { char *wildcarded = ssl_wildcardify(ctx->sni); @@ -769,7 +709,7 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) ctx->enomem = 1; return NULL; } - cert = (cert_t *)cachemgr_tgcrt_get(wildcarded); + cert = (cert_t *) cachemgr_tgcrt_get(wildcarded); free(wildcarded); } if (cert && OPTS_DEBUG(ctx->opts)) @@ -784,7 +724,7 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) { if (!cert) { - cert = (cert_t *)cachemgr_tgcrt_get(*p); + cert = (cert_t *) cachemgr_tgcrt_get(*p); } if (!cert) { @@ -792,7 +732,8 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) if (!wildcarded) { ctx->enomem = 1; - } else + } + else { cert = (cert_t *) (wildcarded); free(wildcarded); @@ -820,7 +761,7 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) if (!cert && ctx->origcrt && ctx->opts->key) { cert = cert_new(); - cert->crt = (X509 *)cachemgr_fkcrt_get(ctx->origcrt); + cert->crt = (X509 *) cachemgr_fkcrt_get(ctx->origcrt); if (cert->crt) { @@ -830,11 +771,11 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) { 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); + ctx->opts->cakey, + ctx->origcrt, + ctx->opts->key, + NULL, + ctx->opts->crlurl); cachemgr_fkcrt_set(ctx->origcrt, cert->crt); } @@ -855,7 +796,7 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) { ctx->usedcrtfpr = ssl_x509_fingerprint(cert->crt, 0); if (!ctx->usedcrtfpr) - ctx->enomem = 1; + ctx->enomem = 1; } return cert; @@ -866,13 +807,13 @@ static cert_t * pxy_srccert_create(pxy_conn_ctx_t *ctx) * destination SSL certificate. * Returns NULL if no suitable certificate could be found. */ -static SSL * pxy_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl) +static SSL *pxy_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl) { cert_t *cert; cachemgr_dsess_set((struct sockaddr *) &ctx->addr, - ctx->addrlen, ctx->sni, - SSL_get0_session(origssl)); + ctx->addrlen, ctx->sni, + SSL_get0_session(origssl)); ctx->origcrt = SSL_get_peer_certificate(origssl); @@ -882,7 +823,8 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl) { log_dbg_printf("===> Original server certificate:\n"); pxy_debug_crt(ctx->origcrt); - } else + } + else { log_dbg_printf("===> Original server has no cert!\n"); } @@ -908,7 +850,7 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl) } SSL_CTX *sslctx = pxy_srcsslctx_create(ctx, cert->crt, cert->chain, - cert->key); + cert->key); cert_free(cert); if (!sslctx) { @@ -940,7 +882,7 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl) */ static int pxy_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; const char *sn; X509 *sslcrt; @@ -996,8 +938,8 @@ static int pxy_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg) "(SNI mismatch)\n"); } newcrt = ssl_x509_forge(ctx->opts->cacrt, ctx->opts->cakey, - sslcrt, ctx->opts->key, - sn, ctx->opts->crlurl); + sslcrt, ctx->opts->key, + sn, ctx->opts->crlurl); if (!newcrt) { ctx->enomem = 1; @@ -1037,7 +979,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); + ctx->opts->key); if (!newsslctx) { X509_free(newcrt); @@ -1047,7 +989,8 @@ static int pxy_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg) SSL_set_SSL_CTX(ssl, newsslctx); /* decr's old incr new refc */ SSL_CTX_free(newsslctx); X509_free(newcrt); - } else if (OPTS_DEBUG(ctx->opts)) + } + else if (OPTS_DEBUG(ctx->opts)) { log_dbg_printf("Certificate cache: KEEP (SNI match or " "target mode)\n"); @@ -1110,7 +1053,7 @@ pxy_dstssl_create(pxy_conn_ctx_t *ctx) /* session resuming based on remote endpoint address and port */ sess = (SSL_SESSION *) cachemgr_dsess_get((struct sockaddr *) &ctx->addr, - ctx->addrlen, ctx->sni); /* new sess inst */ + ctx->addrlen, ctx->sni); /* new sess inst */ if (sess) { if (OPTS_DEBUG(ctx->opts)) @@ -1151,7 +1094,8 @@ bufferevent_free_and_close_fd(struct bufferevent *bev, pxy_conn_ctx_t *ctx) if (ssl) { pxy_ssl_shutdown(ctx->opts, ctx->evbase, ssl, fd); - } else + } + else { evutil_closesocket(fd); } @@ -1176,13 +1120,14 @@ pxy_bufferevent_setup(pxy_conn_ctx_t *ctx, evutil_socket_t fd, SSL *ssl) if (ssl) { bev = bufferevent_openssl_socket_new(ctx->evbase, fd, ssl, - ((fd == -1) ? BUFFEREVENT_SSL_CONNECTING - : BUFFEREVENT_SSL_ACCEPTING), - BEV_OPT_DEFER_CALLBACKS); - } else + ((fd == -1) ? BUFFEREVENT_SSL_CONNECTING + : BUFFEREVENT_SSL_ACCEPTING), + BEV_OPT_DEFER_CALLBACKS); + } + else { bev = bufferevent_socket_new(ctx->evbase, fd, - BEV_OPT_DEFER_CALLBACKS); + BEV_OPT_DEFER_CALLBACKS); } if (!bev) { @@ -1198,7 +1143,7 @@ pxy_bufferevent_setup(pxy_conn_ctx_t *ctx, evutil_socket_t fd, SSL *ssl) } #endif /* LIBEVENT_VERSION_NUMBER >= 0x02010000 */ bufferevent_setcb(bev, pxy_bev_readcb, pxy_bev_writecb, - pxy_bev_eventcb, ctx); + pxy_bev_eventcb, ctx); bufferevent_enable(bev, EV_READ | EV_WRITE); #ifdef DEBUG_PROXY if (OPTS_DEBUG(ctx->opts)) { @@ -1219,7 +1164,7 @@ static int pxy_ocsp_is_valid_uri(const char *uri, pxy_conn_ctx_t *ctx) size_t sz_asn1; int ret; - buf_url = (char *)strrchr(uri, '/'); + buf_url = (char *) strrchr(uri, '/'); if (!buf_url) return 0; buf_url++; @@ -1287,7 +1232,7 @@ static void pxy_ocsp_deny(pxy_conn_ctx_t *ctx) if (!strncasecmp(ctx->http_method, "POST", 4) && ctx->http_content_type && !strncasecmp(ctx->http_content_type, - "application/ocsp-request", 24)) + "application/ocsp-request", 24)) goto deny; return; @@ -1297,46 +1242,14 @@ deny: if (evbuffer_get_length(inbuf) > 0) { - if (WANT_CONTENT_LOG(ctx)) - { - logbuf_t *lb; - lb = logbuf_new_alloc(evbuffer_get_length(inbuf), - NULL, NULL); - if (lb && - (evbuffer_copyout(inbuf, lb->buf, lb->sz) != -1)) - { - if (log_content_submit(ctx->logctx, lb, - 1/*req*/) == -1) - { - logbuf_free(lb); - log_err_printf("Warning: Content log " - "submission failed\n"); - } - } - } evbuffer_drain(inbuf, evbuffer_get_length(inbuf)); } + bufferevent_free_and_close_fd(ctx->dst.bev, ctx); ctx->dst.bev = NULL; ctx->dst.closed = 1; evbuffer_add_printf(outbuf, ocspresp); ctx->ocsp_denied = 1; - if (WANT_CONTENT_LOG(ctx)) - { - logbuf_t *lb; - lb = logbuf_new_copy(ocspresp, sizeof(ocspresp) - 1, - NULL, NULL); - if (lb) - { - if (log_content_submit(ctx->logctx, lb, - 0/*resp*/) == -1) - { - logbuf_free(lb); - log_err_printf("Warning: Content log " - "submission failed\n"); - } - } - } } /* @@ -1367,8 +1280,8 @@ pxy_conn_autossl_peek_and_upgrade(pxy_conn_ctx_t *ctx) inbuf = bufferevent_get_input(ctx->src.bev); if (evbuffer_peek(inbuf, 1024, 0, vec_out, 1)) { - if (ssl_tls_clienthello_parse((const unsigned char *)vec_out[0].iov_base, - vec_out[0].iov_len, 0, &chello, &ctx->sni) == 0) + if (ssl_tls_clienthello_parse((const unsigned char *) vec_out[0].iov_base, + vec_out[0].iov_len, 0, &chello, &ctx->sni) == 0) { if (OPTS_DEBUG(ctx->opts)) { @@ -1390,19 +1303,20 @@ pxy_conn_autossl_peek_and_upgrade(pxy_conn_ctx_t *ctx) return 0; } bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb, - pxy_bev_writecb, pxy_bev_eventcb, - ctx); + pxy_bev_writecb, pxy_bev_eventcb, + ctx); bufferevent_enable(ctx->dst.bev, EV_READ | EV_WRITE); if (OPTS_DEBUG(ctx->opts)) { log_err_printf("Replaced dst bufferevent, new " "one is %p\n", - (void *) ctx->dst.bev); + (void *) ctx->dst.bev); } ctx->clienthello_search = 0; ctx->clienthello_found = 1; return 1; - } else + } + else { if (OPTS_DEBUG(ctx->opts)) { @@ -1418,7 +1332,7 @@ static void pxy_conn_terminate_free(pxy_conn_ctx_t *ctx, int is_requestor) { log_err_printf("Terminating connection%s!\n", - ctx->enomem ? " (out of memory)" : ""); + ctx->enomem ? " (out of memory)" : ""); if (ctx->dst.bev && !ctx->dst.closed) { bufferevent_free_and_close_fd(ctx->dst.bev, ctx); @@ -1440,16 +1354,14 @@ extern int pxy_http_read_cb(pxy_conn_ctx_t *ctx, struct bufferevent *bev); */ static void pxy_bev_readcb(struct bufferevent *bev, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; - pxy_conn_desc_t * conn_this = (bev == ctx->src.bev) ? &ctx->src : &ctx->dst; - pxy_conn_desc_t * conn_other = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src; + pxy_conn_desc_t *conn_this = (bev == ctx->src.bev) ? &ctx->src : &ctx->dst; + pxy_conn_desc_t *conn_other = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src; if (!ctx->connected) { - log_err_printf("readcb called when other end not connected - " - "aborting.\n"); - log_exceptcb(); + log_err_printf("readcb called when other end not connected - aborting.\n"); return; } @@ -1475,13 +1387,13 @@ static void pxy_bev_readcb(struct bufferevent *bev, void *arg) if (ctx->spec->http && (bev == ctx->src.bev) && !ctx->passthrough) { - auto * http1_connection = reinterpret_cast<Http1Connection *>(ctx->protocol_conn_ctx); + auto *http1_connection = reinterpret_cast<Http1Connection *>(ctx->protocol_conn_ctx); http1_connection->on_connection_read_request(ctx, conn_this, conn_other); } if (ctx->spec->http && (bev == ctx->dst.bev) && !ctx->passthrough) { - auto * http1_connection = reinterpret_cast<Http1Connection *>(ctx->protocol_conn_ctx); + auto *http1_connection = reinterpret_cast<Http1Connection *>(ctx->protocol_conn_ctx); http1_connection->on_connection_read_response(ctx, bev); } @@ -1496,28 +1408,13 @@ static void pxy_bev_readcb(struct bufferevent *bev, void *arg) if (evbuffer_get_length(inbuf) == 0) return; - if (WANT_CONTENT_LOG(ctx)) - { - logbuf_t *lb; - lb = logbuf_new_alloc(evbuffer_get_length(inbuf), NULL, NULL); - if (lb && (evbuffer_copyout(inbuf, lb->buf, lb->sz) != -1)) - { - if (log_content_submit(ctx->logctx, lb, - (bev == ctx->src.bev)) == -1) - { - logbuf_free(lb); - log_err_printf("Warning: Content log " - "submission failed\n"); - } - } - } evbuffer_add_buffer(outbuf, inbuf); if (evbuffer_get_length(outbuf) >= OUTBUF_LIMIT) { /* temporarily disable data source; * set an appropriate watermark. */ bufferevent_setwatermark(conn_other->bev, EV_WRITE, - OUTBUF_LIMIT / 2, OUTBUF_LIMIT); + OUTBUF_LIMIT / 2, OUTBUF_LIMIT); bufferevent_disable(bev, EV_READ); } } @@ -1530,7 +1427,7 @@ static void pxy_bev_readcb(struct bufferevent *bev, void *arg) static void pxy_bev_writecb(struct bufferevent *bev, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; pxy_conn_desc_t *other = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src; #ifdef DEBUG_PROXY @@ -1568,7 +1465,7 @@ pxy_bev_writecb(struct bufferevent *bev, void *arg) */ static void pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; pxy_conn_desc_t *this_conn = (bev == ctx->src.bev) ? &ctx->src : &ctx->dst; pxy_conn_desc_t *other_conn = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src; @@ -1636,20 +1533,21 @@ static void pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) ctx->evbase, ctx->src.bev, ctx->src.ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS); + if (ctx->src.bev) { bufferevent_setcb(ctx->src.bev, - pxy_bev_readcb, - pxy_bev_writecb, - pxy_bev_eventcb, - ctx); - bufferevent_enable(ctx->src.bev, - EV_READ | EV_WRITE); + pxy_bev_readcb, + pxy_bev_writecb, + pxy_bev_eventcb, + ctx); + bufferevent_enable(ctx->src.bev, EV_READ | EV_WRITE); } - } else + } + else { ctx->src.bev = pxy_bufferevent_setup(ctx, ctx->fd, - ctx->src.ssl); + ctx->src.ssl); } if (!ctx->src.bev) { @@ -1668,9 +1566,9 @@ static void pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) if (WANT_CONNECT_LOG(ctx) || WANT_CONTENT_LOG(ctx)) { if (sys_sockaddr_str((struct sockaddr *) - &ctx->addr, ctx->addrlen, - &ctx->dsthost_str, - &ctx->dstport_str) != 0) + &ctx->addr, ctx->addrlen, + &ctx->dsthost_str, + &ctx->dstport_str) != 0) { ctx->enomem = 1; pxy_conn_terminate_free(ctx, 1); @@ -1678,18 +1576,6 @@ static void pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg) } } - if (WANT_CONTENT_LOG(ctx)) - { - if (log_content_open(&ctx->logctx, ctx->opts, - ctx->srchost_str, ctx->srcport_str, - ctx->dsthost_str, ctx->dstport_str, NULL, NULL, NULL) == -1) - { - if (errno == ENOMEM) - ctx->enomem = 1; - pxy_conn_terminate_free(ctx, 1); - return; - } - } connected: /* log connection if we don't analyze any headers */ @@ -1713,11 +1599,9 @@ connected: { char *keystr; keystr = ssl_ssl_masterkey_to_str(this_conn->ssl); - if ((keystr == NULL) || - (log_masterkey_print_free(keystr) == -1)) + if ((keystr == NULL)) { - if (errno == ENOMEM) - ctx->enomem = 1; + if (errno == ENOMEM) ctx->enomem = 1; pxy_conn_terminate_free(ctx, 1); return; } @@ -1732,23 +1616,24 @@ connected: /* for SSL, we get two connect events */ log_dbg_printf("SSL connected %s [%s]:%s" " %s %s\n", - bev == ctx->dst.bev ? - "to" : "from", - bev == ctx->dst.bev ? - ctx->dsthost_str : - ctx->srchost_str, - bev == ctx->dst.bev ? - ctx->dstport_str : - ctx->srcport_str, - SSL_get_version(this_conn->ssl), - SSL_get_cipher(this_conn->ssl), this_conn); + bev == ctx->dst.bev ? + "to" : "from", + bev == ctx->dst.bev ? + ctx->dsthost_str : + ctx->srchost_str, + bev == ctx->dst.bev ? + ctx->dstport_str : + ctx->srcport_str, + SSL_get_version(this_conn->ssl), + SSL_get_cipher(this_conn->ssl), this_conn); keystr = ssl_ssl_masterkey_to_str(this_conn->ssl); if (keystr) { log_dbg_print_free(keystr); } - } else + } + else { /* for TCP, we get only a dst connect event, * since src was already connected from the @@ -1756,11 +1641,11 @@ connected: * in order not to confuse anyone who might be * looking closely at the output */ log_dbg_printf("TCP connected to [%s]:%s\n", - ctx->dsthost_str, - ctx->dstport_str); + ctx->dsthost_str, + ctx->dstport_str); log_dbg_printf("TCP connected from [%s]:%s\n", - ctx->srchost_str, - ctx->srcport_str); + ctx->srchost_str, + ctx->srcport_str); } } @@ -1790,67 +1675,69 @@ connected: log_dbg_printf("Unclean SSL shutdown.\n"); } #endif /* LIBEVENT_VERSION_NUMBER < 0x02010000 */ - } else if (ERR_GET_REASON(sslerr) == + } + else if (ERR_GET_REASON(sslerr) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) { /* these can happen due to client cert auth, * only log error if debugging is activated */ log_dbg_printf("Error from %s bufferevent: " "%i:%s %lu:%i:%s:%i:%s:%i:%s\n", - (bev == ctx->src.bev) ? "src" : "dst", - errno, - errno ? strerror(errno) : "-", - sslerr, - ERR_GET_REASON(sslerr), - sslerr ? - ERR_reason_error_string(sslerr) : "-", - ERR_GET_LIB(sslerr), - sslerr ? - ERR_lib_error_string(sslerr) : "-", - ERR_GET_FUNC(sslerr), - sslerr ? - ERR_func_error_string(sslerr) : "-"); + (bev == ctx->src.bev) ? "src" : "dst", + errno, + errno ? strerror(errno) : "-", + sslerr, + ERR_GET_REASON(sslerr), + sslerr ? + ERR_reason_error_string(sslerr) : "-", + ERR_GET_LIB(sslerr), + sslerr ? + ERR_lib_error_string(sslerr) : "-", + ERR_GET_FUNC(sslerr), + sslerr ? + ERR_func_error_string(sslerr) : "-"); while ((sslerr = bufferevent_get_openssl_error(bev))) { log_dbg_printf("Additional SSL error: " "%lu:%i:%s:%i:%s:%i:%s\n", - sslerr, - ERR_GET_REASON(sslerr), - ERR_reason_error_string(sslerr), - ERR_GET_LIB(sslerr), - ERR_lib_error_string(sslerr), - ERR_GET_FUNC(sslerr), - ERR_func_error_string(sslerr)); + sslerr, + ERR_GET_REASON(sslerr), + ERR_reason_error_string(sslerr), + ERR_GET_LIB(sslerr), + ERR_lib_error_string(sslerr), + ERR_GET_FUNC(sslerr), + ERR_func_error_string(sslerr)); } - } else + } + else { /* real errors */ log_err_printf("Error from %s bufferevent: " "%i:%s %lu:%i:%s:%i:%s:%i:%s\n", - (bev == ctx->src.bev) ? "src" : "dst", - errno, - errno ? strerror(errno) : "-", - sslerr, - ERR_GET_REASON(sslerr), - sslerr ? - ERR_reason_error_string(sslerr) : "-", - ERR_GET_LIB(sslerr), - sslerr ? - ERR_lib_error_string(sslerr) : "-", - ERR_GET_FUNC(sslerr), - sslerr ? - ERR_func_error_string(sslerr) : "-"); + (bev == ctx->src.bev) ? "src" : "dst", + errno, + errno ? strerror(errno) : "-", + sslerr, + ERR_GET_REASON(sslerr), + sslerr ? + ERR_reason_error_string(sslerr) : "-", + ERR_GET_LIB(sslerr), + sslerr ? + ERR_lib_error_string(sslerr) : "-", + ERR_GET_FUNC(sslerr), + sslerr ? + ERR_func_error_string(sslerr) : "-"); while ((sslerr = bufferevent_get_openssl_error(bev))) { log_err_printf("Additional SSL error: " "%lu:%i:%s:%i:%s:%i:%s\n", - sslerr, - ERR_GET_REASON(sslerr), - ERR_reason_error_string(sslerr), - ERR_GET_LIB(sslerr), - ERR_lib_error_string(sslerr), - ERR_GET_FUNC(sslerr), - ERR_func_error_string(sslerr)); + sslerr, + ERR_GET_REASON(sslerr), + ERR_reason_error_string(sslerr), + ERR_GET_LIB(sslerr), + ERR_lib_error_string(sslerr), + ERR_GET_FUNC(sslerr), + ERR_func_error_string(sslerr)); } } @@ -1875,7 +1762,8 @@ connected: } evutil_closesocket(ctx->fd); other_conn->closed = 1; - } else if (!other_conn->closed) + } + else if (!other_conn->closed) { /* if the other end is still open and doesn't have data * to send, close it, otherwise its writecb will close @@ -1917,7 +1805,8 @@ connected: "connection establishment\n"); evutil_closesocket(ctx->fd); other_conn->closed = 1; - } else if (!other_conn->closed) + } + else if (!other_conn->closed) { /* if there is data pending in the closed connection, * handle it here, otherwise it will be lost. */ @@ -1948,11 +1837,11 @@ leave: if (OPTS_DEBUG(ctx->opts)) { log_dbg_printf("%s disconnected to [%s]:%s\n", - this_conn->ssl ? "SSL" : "TCP", - ctx->dsthost_str, ctx->dstport_str); + this_conn->ssl ? "SSL" : "TCP", + ctx->dsthost_str, ctx->dstport_str); log_dbg_printf("%s disconnected from [%s]:%s\n", - this_conn->ssl ? "SSL" : "TCP", - ctx->srchost_str, ctx->srcport_str); + this_conn->ssl ? "SSL" : "TCP", + ctx->srchost_str, ctx->srcport_str); } this_conn->closed = 1; @@ -2007,10 +1896,11 @@ static void pxy_conn_connect(pxy_conn_ctx_t *ctx) { char *host, *port; if (sys_sockaddr_str((struct sockaddr *) &ctx->addr, - ctx->addrlen, &host, &port) != 0) + ctx->addrlen, &host, &port) != 0) { log_dbg_printf("Connecting to [?]:?\n"); - } else + } + else { log_dbg_printf("Connecting to [%s]:%s\n", host, port); free(host); @@ -2020,8 +1910,8 @@ static void pxy_conn_connect(pxy_conn_ctx_t *ctx) /* initiate connection */ bufferevent_socket_connect(ctx->dst.bev, - (struct sockaddr *) &ctx->addr, - ctx->addrlen); + (struct sockaddr *) &ctx->addr, + ctx->addrlen); } /* @@ -2030,12 +1920,12 @@ static void pxy_conn_connect(pxy_conn_ctx_t *ctx) */ static void pxy_sni_resolve_cb(int errcode, struct evutil_addrinfo *ai, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; if (errcode) { log_err_printf("Cannot resolve SNI hostname '%s': %s\n", - ctx->sni, evutil_gai_strerror(errcode)); + ctx->sni, evutil_gai_strerror(errcode)); evutil_closesocket(ctx->fd); pxy_conn_ctx_free(ctx, 1); return; @@ -2055,7 +1945,7 @@ static void pxy_sni_resolve_cb(int errcode, struct evutil_addrinfo *ai, void *ar */ static void pxy_fd_readcb(evutil_socket_t fd, short what, void *arg) { - pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *)arg; + pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) arg; /* for SSL, peek ClientHello and parse SNI from it */ if (ctx->spec->ssl && !ctx->passthrough /*&& ctx->ev*/) @@ -2095,9 +1985,9 @@ static void pxy_fd_readcb(evutil_socket_t fd, short what, void *arg) if (OPTS_DEBUG(ctx->opts)) { log_dbg_printf("SNI peek: [%s] [%s]\n", - ctx->sni ? ctx->sni : "n/a", - ((rv == 1) && chello) ? - "incomplete" : "complete"); + ctx->sni ? ctx->sni : "n/a", + ((rv == 1) && chello) ? + "incomplete" : "complete"); } if ((rv == 1) && chello && (ctx->sni_peek_retries++ < 50)) { @@ -2113,7 +2003,7 @@ static void pxy_fd_readcb(evutil_socket_t fd, short what, void *arg) event_free(ctx->ev); ctx->ev = event_new(ctx->evbase, fd, 0, - pxy_fd_readcb, ctx); + pxy_fd_readcb, ctx); if (!ctx->ev) { log_err_printf("Error creating retry " @@ -2143,7 +2033,7 @@ static void pxy_fd_readcb(evutil_socket_t fd, short what, void *arg) snprintf(sniport, sizeof(sniport), "%i", ctx->spec->sni_port); evdns_getaddrinfo(ctx->dnsbase, ctx->sni, sniport, &hints, - pxy_sni_resolve_cb, ctx); + pxy_sni_resolve_cb, ctx); return; } @@ -2183,7 +2073,7 @@ void pxy_conn_setup(evutil_socket_t fd, struct sockaddr *peeraddr, int peeraddrl /* NAT engine lookup */ ctx->addrlen = sizeof(struct sockaddr_storage); if (spec->natlookup((struct sockaddr *) &ctx->addr, &ctx->addrlen, - fd, peeraddr, peeraddrlen) == -1) + fd, peeraddr, peeraddrlen) == -1) { log_err_printf("Connection not found in NAT " "state table, aborting connection\n"); @@ -2216,8 +2106,8 @@ void pxy_conn_setup(evutil_socket_t fd, struct sockaddr *peeraddr, int peeraddrl if (WANT_CONNECT_LOG(ctx) || WANT_CONTENT_LOG(ctx)) { if (sys_sockaddr_str(peeraddr, peeraddrlen, - &ctx->srchost_str, - &ctx->srcport_str) != 0) + &ctx->srchost_str, + &ctx->srcport_str) != 0) goto memout; } @@ -2225,11 +2115,12 @@ void pxy_conn_setup(evutil_socket_t fd, struct sockaddr *peeraddr, int peeraddrl if (ctx->spec->ssl) { ctx->ev = event_new(ctx->evbase, fd, EV_READ, pxy_fd_readcb, - ctx); + ctx); if (!ctx->ev) goto memout; event_add(ctx->ev, NULL); - } else + } + else { pxy_fd_readcb(fd, 0, ctx); } diff --git a/src/pxyconn.h b/src/pxyconn.h index ca09a24..d7e4691 100644 --- a/src/pxyconn.h +++ b/src/pxyconn.h @@ -48,7 +48,8 @@ */ /* single dst or src socket bufferevent descriptor */ -typedef struct pxy_conn_desc { +typedef struct pxy_conn_desc +{ struct bufferevent *bev; SSL *ssl; unsigned int closed : 1; @@ -57,7 +58,8 @@ typedef struct pxy_conn_desc { /* actual proxy connection state consisting of two connection descriptors, * connection-wide state and the specs and options */ -typedef struct pxy_conn_ctx { +typedef struct pxy_conn_ctx +{ /* per-connection state */ struct pxy_conn_desc src; struct pxy_conn_desc dst; @@ -122,15 +124,14 @@ typedef struct pxy_conn_ctx { proxyspec *spec; tfe_config *opts; - tfe_instance * instance; + tfe_instance *instance; /* Protocol Ctxs*/ - void * protocol_conn_ctx; + void *protocol_conn_ctx; } pxy_conn_ctx_t; -void pxy_conn_setup(evutil_socket_t, struct sockaddr *, int, - tfe_thread_manager_ctx *, proxyspec *, tfe_config *) - NONNULL(2,4,5,6); +void pxy_conn_setup(evutil_socket_t fd, struct sockaddr *peeraddr, int peeraddrlen, + tfe_thread_manager_ctx *thrmgr, proxyspec *spec, tfe_config *opts); #endif /* !PXYCONN_H */ |
