summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/.name1
-rw-r--r--.idea/codeStyles/Project.xml70
-rw-r--r--.idea/codeStyles/codeStyleConfig.xml5
-rw-r--r--.idea/deployment.xml28
-rw-r--r--.idea/misc.xml7
-rw-r--r--.idea/modules.xml8
-rw-r--r--.idea/tfe-sslsplit.iml2
-rw-r--r--.idea/vcs.xml6
-rw-r--r--.idea/webServers.xml23
-rw-r--r--CMakeLists.txt17
-rw-r--r--opts.c560
-rw-r--r--proc.c462
-rw-r--r--proc.h65
-rw-r--r--pxyconn.h48
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/attrib.h (renamed from attrib.h)0
-rw-r--r--src/base64.cc (renamed from base64.c)4
-rw-r--r--src/base64.h (renamed from base64.h)0
-rw-r--r--src/build.cc (renamed from build.c)0
-rw-r--r--src/build.h (renamed from build.h)0
-rw-r--r--src/cache.cc (renamed from cache.c)2
-rw-r--r--src/cache.h (renamed from cache.h)0
-rw-r--r--src/cachedsess.cc (renamed from cachedsess.c)12
-rw-r--r--src/cachedsess.h (renamed from cachedsess.h)0
-rw-r--r--src/cachefkcrt.cc (renamed from cachefkcrt.c)8
-rw-r--r--src/cachefkcrt.h (renamed from cachefkcrt.h)0
-rw-r--r--src/cachemgr.cc (renamed from cachemgr.c)2
-rw-r--r--src/cachemgr.h (renamed from cachemgr.h)0
-rw-r--r--src/cachessess.cc (renamed from cachessess.c)12
-rw-r--r--src/cachessess.h (renamed from cachessess.h)0
-rw-r--r--src/cachetgcrt.cc (renamed from cachetgcrt.c)8
-rw-r--r--src/cachetgcrt.h (renamed from cachetgcrt.h)0
-rw-r--r--src/cert.cc (renamed from cert.c)8
-rw-r--r--src/cert.h (renamed from cert.h)0
-rw-r--r--src/cfgparser.h123
-rw-r--r--src/defaults.h (renamed from defaults.h)0
-rw-r--r--src/dynbuf.cc (renamed from dynbuf.c)14
-rw-r--r--src/dynbuf.h (renamed from dynbuf.h)0
-rw-r--r--src/khash.h (renamed from khash.h)0
-rw-r--r--src/log.cc (renamed from log.c)35
-rw-r--r--src/log.h (renamed from log.h)7
-rw-r--r--src/logbuf.cc (renamed from logbuf.c)14
-rw-r--r--src/logbuf.h (renamed from logbuf.h)0
-rw-r--r--src/logger.cc (renamed from logger.c)6
-rw-r--r--src/logger.h (renamed from logger.h)0
-rw-r--r--src/main.cc (renamed from main.c)32
-rw-r--r--src/nat.cc (renamed from nat.c)5
-rw-r--r--src/nat.h (renamed from nat.h)0
-rw-r--r--src/opts.cc550
-rw-r--r--src/opts.h (renamed from opts.h)59
-rw-r--r--src/privsep.cc (renamed from privsep.c)24
-rw-r--r--src/privsep.h (renamed from privsep.h)4
-rw-r--r--src/proxy.cc (renamed from proxy.c)34
-rw-r--r--src/proxy.h (renamed from proxy.h)2
-rw-r--r--src/pxyconn.cc (renamed from pxyconn.c)256
-rw-r--r--src/pxyconn.h145
-rw-r--r--src/pxyhttp.cc182
-rw-r--r--src/pxyhttp.h4
-rw-r--r--src/pxysslshut.cc (renamed from pxysslshut.c)6
-rw-r--r--src/pxysslshut.h (renamed from pxysslshut.h)2
-rw-r--r--src/pxythrmgr.cc (renamed from pxythrmgr.c)6
-rw-r--r--src/pxythrmgr.h (renamed from pxythrmgr.h)2
-rw-r--r--src/ssl.cc (renamed from ssl.c)24
-rw-r--r--src/ssl.h (renamed from ssl.h)0
-rw-r--r--src/sys.cc (renamed from sys.c)5
-rw-r--r--src/sys.h (renamed from sys.h)5
-rw-r--r--src/thrqueue.cc (renamed from thrqueue.c)0
-rw-r--r--src/thrqueue.h (renamed from thrqueue.h)0
-rw-r--r--src/url.cc (renamed from url.c)0
-rw-r--r--src/url.h (renamed from url.h)0
-rw-r--r--src/util.cc (renamed from util.c)0
-rw-r--r--src/util.h (renamed from util.h)0
-rw-r--r--test/base64.t.c (renamed from base64.t.c)0
-rw-r--r--test/cachedsess.t.c (renamed from cachedsess.t.c)0
-rw-r--r--test/cachefkcrt.t.c (renamed from cachefkcrt.t.c)0
-rw-r--r--test/cachemgr.t.c (renamed from cachemgr.t.c)0
-rw-r--r--test/cachessess.t.c (renamed from cachessess.t.c)0
-rw-r--r--test/cachetgcrt.t.c (renamed from cachetgcrt.t.c)0
-rw-r--r--test/cert.t.c (renamed from cert.t.c)0
-rw-r--r--test/dynbuf.t.c (renamed from dynbuf.t.c)0
-rw-r--r--test/main.t.c (renamed from main.t.c)0
-rw-r--r--test/opts.t.c (renamed from opts.t.c)36
-rw-r--r--test/pxythrmgr.t.c (renamed from pxythrmgr.t.c)0
-rw-r--r--test/ssl.t.c (renamed from ssl.t.c)0
-rw-r--r--test/sys.t.c (renamed from sys.t.c)0
-rw-r--r--test/url.t.c (renamed from url.t.c)0
-rw-r--r--test/util.t.c (renamed from util.t.c)0
-rw-r--r--vendor/CMakeLists.txt103
-rw-r--r--vendor/MESA_prof_load-3b2bfd.tar.gzbin0 -> 8125 bytes
-rw-r--r--vendor/check-0.12.0.tar.gzbin0 -> 764043 bytes
-rw-r--r--vendor/googletest-release-1.8.0.tar.gzbin0 -> 1281617 bytes
-rw-r--r--vendor/http-parser-2.8.1.tar.gzbin0 -> 50731 bytes
-rw-r--r--vendor/libevent-2.1.8-stable.tar.gzbin0 -> 1026485 bytes
93 files changed, 1515 insertions, 1543 deletions
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..4e3c827
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+tfe \ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..910d7c2
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,70 @@
+<component name="ProjectCodeStyleConfiguration">
+ <code_scheme name="Project" version="173">
+ <option name="LINE_SEPARATOR" value="&#10;" />
+ <Objective-C>
+ <option name="INDENT_NAMESPACE_MEMBERS" value="0" />
+ <option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" />
+ <option name="KEEP_CASE_EXPRESSIONS_IN_ONE_LINE" value="true" />
+ <option name="NAMESPACE_BRACE_PLACEMENT" value="2" />
+ <option name="FUNCTION_BRACE_PLACEMENT" value="2" />
+ <option name="BLOCK_BRACE_PLACEMENT" value="5" />
+ <option name="FUNCTION_NON_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+ <option name="FUNCTION_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+ <option name="FUNCTION_PARAMETERS_WRAP" value="5" />
+ <option name="FUNCTION_PARAMETERS_NEW_LINE_AFTER_LPAR" value="true" />
+ <option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5" />
+ <option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true" />
+ <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="ADD_BRIEF_TAG" value="true" />
+ </Objective-C>
+ <Objective-C-extensions>
+ <file>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+ </file>
+ <class>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+ </class>
+ <extensions>
+ <pair source="cc" header="h" fileNamingConvention="NONE" />
+ <pair source="c" header="h" fileNamingConvention="NONE" />
+ </extensions>
+ </Objective-C-extensions>
+ <codeStyleSettings language="ObjectiveC">
+ <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
+ <option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
+ <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
+ <option name="BLANK_LINES_BEFORE_IMPORTS" value="0" />
+ <option name="BLANK_LINES_AFTER_IMPORTS" value="0" />
+ <option name="BLANK_LINES_AROUND_CLASS" value="0" />
+ <option name="BLANK_LINES_AROUND_METHOD" value="0" />
+ <option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
+ <option name="BRACE_STYLE" value="5" />
+ <option name="CLASS_BRACE_STYLE" value="2" />
+ <option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false" />
+ <option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="false" />
+ <option name="METHOD_CALL_CHAIN_WRAP" value="1" />
+ <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
+ <option name="FOR_STATEMENT_WRAP" value="1" />
+ <option name="ASSIGNMENT_WRAP" value="1" />
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="true" />
+ </indentOptions>
+ </codeStyleSettings>
+ </code_scheme>
+</component> \ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+ <state>
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+ </state>
+</component> \ No newline at end of file
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
new file mode 100644
index 0000000..5984ae4
--- /dev/null
+++ b/.idea/deployment.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="PublishConfigData" autoUpload="Always" serverName="192.168.10.8">
+ <serverData>
+ <paths name="192.168.10.8">
+ <serverdata>
+ <mappings>
+ <mapping deploy="/home/luqiuwen/tfe-sslsplit" local="$PROJECT_DIR$" web="/" />
+ </mappings>
+ <excludedPaths>
+ <excludedPath local="true" path="$PROJECT_DIR$/cmake-build-debug" />
+ </excludedPaths>
+ </serverdata>
+ </paths>
+ <paths name="tencent-server">
+ <serverdata>
+ <mappings>
+ <mapping deploy="tfe-sslsplit" local="$PROJECT_DIR$" web="/" />
+ </mappings>
+ <excludedPaths>
+ <excludedPath local="true" path="$PROJECT_DIR$/cmake-build-debug" />
+ </excludedPaths>
+ </serverdata>
+ </paths>
+ </serverData>
+ <option name="myAutoUpload" value="ALWAYS" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..8822db8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
+ <component name="JavaScriptSettings">
+ <option name="languageLevel" value="ES6" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..0bba2df
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/tfe-sslsplit.iml" filepath="$PROJECT_DIR$/.idea/tfe-sslsplit.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/tfe-sslsplit.iml b/.idea/tfe-sslsplit.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/tfe-sslsplit.iml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module classpath="CMake" type="CPP_MODULE" version="4" /> \ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/webServers.xml b/.idea/webServers.xml
new file mode 100644
index 0000000..2aa1a52
--- /dev/null
+++ b/.idea/webServers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="WebServers">
+ <option name="servers">
+ <webServer id="6f5fcf3d-6a79-444e-983a-d7c3e9244f55" name="tencent-server" url="http://tcn.racimecore.org">
+ <fileTransfer host="tcn.racimecore.org" port="22" privateKey="E:\我的坚果云\License\id_rsa_2048" rootFolder="/home/ubuntu" accessType="SFTP" keyPair="true">
+ <advancedOptions>
+ <advancedOptions dataProtectionLevel="Private" />
+ </advancedOptions>
+ <option name="port" value="22" />
+ </fileTransfer>
+ </webServer>
+ <webServer id="c2739693-9faa-43db-93c3-ffb0f69c0233" name="192.168.10.8" url="http://192.168.10.8">
+ <fileTransfer host="192.168.10.8" port="22" accessType="SFTP">
+ <advancedOptions>
+ <advancedOptions dataProtectionLevel="Private" />
+ </advancedOptions>
+ <option name="port" value="22" />
+ </fileTransfer>
+ </webServer>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a8909b..ec9885d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.5)
project(tfe)
-find_package(OpenSSL REQUIRED)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_C_STANDARD 11)
add_definitions(-DPKGLABEL="tfe")
add_definitions(-DBUILD_PKGNAME="tfe")
@@ -12,13 +13,9 @@ add_definitions(-DBUILD_FEATURES="")
### GNU ###
add_definitions(-D_GNU_SOURCE)
-add_definitions(-fPIC)
+add_definitions(-DHAVE_NETFILTER)
+add_definitions(-fpermissive)
-### Tango Frontend Target ###
-add_executable(tfe base64.c build.c cache.c cachemgr.c cachessess.c cachedsess.c cachetgcrt.c cachefkcrt.c cert.c
- dynbuf.c logbuf.c log.c logger.c main.c nat.c opts.c privsep.c proc.c proxy.c pxyconn.c pxythrmgr.c pxysslshut.c
- ssl.c sys.c thrqueue.c url.c util.c)
-
-target_include_directories(tfe PRIVATE ${OPENSSL_INCLUDE_DIR})
-target_link_libraries(tfe ${OPENSSL_LIBRARIES})
-target_link_libraries(tfe event event_openssl event_pthreads pthread) \ No newline at end of file
+###
+add_subdirectory(vendor)
+add_subdirectory(src) \ No newline at end of file
diff --git a/opts.c b/opts.c
deleted file mode 100644
index 053112d..0000000
--- a/opts.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*-
- * SSLsplit - transparent SSL/TLS interception
- * https://www.roe.ch/SSLsplit
- *
- * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "opts.h"
-
-#include "sys.h"
-#include "log.h"
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifndef OPENSSL_NO_DH
-#include <openssl/dh.h>
-#endif /* !OPENSSL_NO_DH */
-#include <openssl/x509.h>
-
-opts_t *
-opts_new(void)
-{
- opts_t *opts;
-
- opts = malloc(sizeof(opts_t));
- memset(opts, 0, sizeof(opts_t));
-
- opts->sslcomp = 1;
- opts->chain = sk_X509_new_null();
- opts->sslmethod = SSLv23_method;
-
- return opts;
-}
-
-void
-opts_free(opts_t *opts)
-{
- sk_X509_pop_free(opts->chain, X509_free);
- if (opts->cacrt) {
- X509_free(opts->cacrt);
- }
- if (opts->cakey) {
- EVP_PKEY_free(opts->cakey);
- }
- if (opts->key) {
- EVP_PKEY_free(opts->key);
- }
-#ifndef OPENSSL_NO_DH
- if (opts->dh) {
- DH_free(opts->dh);
- }
-#endif /* !OPENSSL_NO_DH */
-#ifndef OPENSSL_NO_ECDH
- if (opts->ecdhcurve) {
- free(opts->ecdhcurve);
- }
-#endif /* !OPENSSL_NO_ECDH */
- if (opts->spec) {
- proxyspec_free(opts->spec);
- }
- if (opts->ciphers) {
- free(opts->ciphers);
- }
- if (opts->tgcrtdir) {
- free(opts->tgcrtdir);
- }
- if (opts->crlurl) {
- free(opts->crlurl);
- }
- if (opts->dropuser) {
- free(opts->dropuser);
- }
- if (opts->dropgroup) {
- free(opts->dropgroup);
- }
- if (opts->jaildir) {
- free(opts->jaildir);
- }
- if (opts->pidfile) {
- free(opts->pidfile);
- }
- if (opts->connectlog) {
- free(opts->connectlog);
- }
- if (opts->contentlog) {
- free(opts->contentlog);
- }
- if (opts->certgendir) {
- free(opts->certgendir);
- }
- if (opts->contentlog_basedir) {
- free(opts->contentlog_basedir);
- }
- if (opts->masterkeylog) {
- free(opts->masterkeylog);
- }
- memset(opts, 0, sizeof(opts_t));
- free(opts);
-}
-
-/*
- * Return 1 if opts_t contains a proxyspec that (eventually) uses SSL/TLS,
- * 0 otherwise. When 0, it is safe to assume that no SSL/TLS operations
- * will take place with this configuration.
- */
-int
-opts_has_ssl_spec(opts_t *opts)
-{
- proxyspec_t *p = opts->spec;
-
- while (p) {
- if (p->ssl || p->upgrade)
- return 1;
- p = p->next;
- }
-
- return 0;
-}
-
-/*
- * Return 1 if opts_t contains a proxyspec with dns, 0 otherwise.
- */
-int
-opts_has_dns_spec(opts_t *opts)
-{
- proxyspec_t *p = opts->spec;
-
- while (p) {
- if (p->dns)
- return 1;
- p = p->next;
- }
-
- return 0;
-}
-
-/*
- * Parse SSL proto string in optarg and look up the corresponding SSL method.
- * Calls exit() on failure.
- */
-void
-opts_proto_force(opts_t *opts, const char *optarg, const char *argv0)
-{
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- if (opts->sslmethod != SSLv23_method) {
-#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
- if (opts->sslversion) {
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
- fprintf(stderr, "%s: cannot use -r multiple times\n", argv0);
- exit(EXIT_FAILURE);
- }
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-#ifdef HAVE_SSLV2
- if (!strcmp(optarg, "ssl2")) {
- opts->sslmethod = SSLv2_method;
- } else
-#endif /* HAVE_SSLV2 */
-#ifdef HAVE_SSLV3
- if (!strcmp(optarg, "ssl3")) {
- opts->sslmethod = SSLv3_method;
- } else
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
- if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
- opts->sslmethod = TLSv1_method;
- } else
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
- if (!strcmp(optarg, "tls11")) {
- opts->sslmethod = TLSv1_1_method;
- } else
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
- if (!strcmp(optarg, "tls12")) {
- opts->sslmethod = TLSv1_2_method;
- } else
-#endif /* HAVE_TLSV12 */
-#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
-/*
- * Support for SSLv2 and the corresponding SSLv2_method(),
- * SSLv2_server_method() and SSLv2_client_method() functions were
- * removed in OpenSSL 1.1.0.
- */
-#ifdef HAVE_SSLV3
- if (!strcmp(optarg, "ssl3")) {
- opts->sslversion = SSL3_VERSION;
- } else
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
- if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
- opts->sslversion = TLS1_VERSION;
- } else
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
- if (!strcmp(optarg, "tls11")) {
- opts->sslversion = TLS1_1_VERSION;
- } else
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
- if (!strcmp(optarg, "tls12")) {
- opts->sslversion = TLS1_2_VERSION;
- } else
-#endif /* HAVE_TLSV12 */
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
- {
- fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
- argv0, optarg);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Parse SSL proto string in optarg and set the corresponding no_foo bit.
- * Calls exit() on failure.
- */
-void
-opts_proto_disable(opts_t *opts, const char *optarg, const char *argv0)
-{
-#ifdef HAVE_SSLV2
- if (!strcmp(optarg, "ssl2")) {
- opts->no_ssl2 = 1;
- } else
-#endif /* HAVE_SSLV2 */
-#ifdef HAVE_SSLV3
- if (!strcmp(optarg, "ssl3")) {
- opts->no_ssl3 = 1;
- } else
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
- if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
- opts->no_tls10 = 1;
- } else
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
- if (!strcmp(optarg, "tls11")) {
- opts->no_tls11 = 1;
- } else
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
- if (!strcmp(optarg, "tls12")) {
- opts->no_tls12 = 1;
- } else
-#endif /* HAVE_TLSV12 */
- {
- fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
- argv0, optarg);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Dump the SSL/TLS protocol related configuration to the debug log.
- */
-void
-opts_proto_dbg_dump(opts_t *opts)
-{
- log_dbg_printf("SSL/TLS protocol: %s%s%s%s%s%s\n",
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-#ifdef HAVE_SSLV2
- (opts->sslmethod == SSLv2_method) ? "ssl2" :
-#endif /* HAVE_SSLV2 */
-#ifdef HAVE_SSLV3
- (opts->sslmethod == SSLv3_method) ? "ssl3" :
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
- (opts->sslmethod == TLSv1_method) ? "tls10" :
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
- (opts->sslmethod == TLSv1_1_method) ? "tls11" :
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
- (opts->sslmethod == TLSv1_2_method) ? "tls12" :
-#endif /* HAVE_TLSV12 */
-#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
-#ifdef HAVE_SSLV3
- (opts->sslversion == SSL3_VERSION) ? "ssl3" :
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
- (opts->sslversion == TLS1_VERSION) ? "tls10" :
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
- (opts->sslversion == TLS1_1_VERSION) ? "tls11" :
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
- (opts->sslversion == TLS1_2_VERSION) ? "tls12" :
-#endif /* HAVE_TLSV12 */
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
- "negotiate",
-#ifdef HAVE_SSLV2
- opts->no_ssl2 ? " -ssl2" :
-#endif /* HAVE_SSLV2 */
- "",
-#ifdef HAVE_SSLV3
- opts->no_ssl3 ? " -ssl3" :
-#endif /* HAVE_SSLV3 */
- "",
-#ifdef HAVE_TLSV10
- opts->no_tls10 ? " -tls10" :
-#endif /* HAVE_TLSV10 */
- "",
-#ifdef HAVE_TLSV11
- opts->no_tls11 ? " -tls11" :
-#endif /* HAVE_TLSV11 */
- "",
-#ifdef HAVE_TLSV12
- opts->no_tls12 ? " -tls12" :
-#endif /* HAVE_TLSV12 */
- "");
-}
-
-
-/*
- * Parse proxyspecs using a simple state machine.
- * Returns NULL if parsing failed.
- */
-proxyspec_t *
-proxyspec_parse(int *argc, char **argv[], const char *natengine)
-{
- proxyspec_t *curspec, *spec = NULL;
- char *addr = NULL;
- int af = AF_UNSPEC;
- int state = 0;
-
- while ((*argc)--) {
- switch (state) {
- default:
- case 0:
- /* tcp | ssl | http | https | autossl */
- curspec = malloc(sizeof(proxyspec_t));
- memset(curspec, 0, sizeof(proxyspec_t));
- curspec->next = spec;
- spec = curspec;
- if (!strcmp(**argv, "tcp")) {
- spec->ssl = 0;
- spec->http = 0;
- spec->upgrade = 0;
- } else
- if (!strcmp(**argv, "ssl")) {
- spec->ssl = 1;
- spec->http = 0;
- spec->upgrade = 0;
- } else
- if (!strcmp(**argv, "http")) {
- spec->ssl = 0;
- spec->http = 1;
- spec->upgrade = 0;
- } else
- if (!strcmp(**argv, "https")) {
- spec->ssl = 1;
- spec->http = 1;
- spec->upgrade = 0;
- } else
- if (!strcmp(**argv, "autossl")) {
- spec->ssl = 0;
- spec->http = 0;
- spec->upgrade = 1;
- } else {
- fprintf(stderr, "Unknown connection "
- "type '%s'\n", **argv);
- exit(EXIT_FAILURE);
- }
- state++;
- break;
- case 1:
- /* listenaddr */
- addr = **argv;
- state++;
- break;
- case 2:
- /* listenport */
- if (strstr(addr, ":"))
- af = AF_INET6;
- else if (!strpbrk(addr, "abcdefghijklmnopqrstu"
- "vwxyzABCDEFGHIJKLMNOP"
- "QRSTUVWXYZ-"))
- af = AF_INET;
- else
- af = AF_UNSPEC;
- af = sys_sockaddr_parse(&spec->listen_addr,
- &spec->listen_addrlen,
- addr, **argv, af,
- EVUTIL_AI_PASSIVE);
- if (af == -1) {
- exit(EXIT_FAILURE);
- }
- if (natengine) {
- spec->natengine = strdup(natengine);
- if (!spec->natengine) {
- fprintf(stderr,
- "Out of memory"
- "\n");
- exit(EXIT_FAILURE);
- }
- } else {
- spec->natengine = NULL;
- }
- state++;
- break;
- case 3:
- /* [ natengine | dstaddr ] */
- if (!strcmp(**argv, "tcp") ||
- !strcmp(**argv, "ssl") ||
- !strcmp(**argv, "http") ||
- !strcmp(**argv, "https") ||
- !strcmp(**argv, "autossl")) {
- /* implicit default natengine */
- (*argv)--; (*argc)++; /* rewind */
- state = 0;
- } else
- if (!strcmp(**argv, "sni")) {
- free(spec->natengine);
- spec->natengine = NULL;
- if (!spec->ssl) {
- fprintf(stderr,
- "SNI hostname lookup "
- "only works for ssl "
- "and https proxyspecs"
- "\n");
- exit(EXIT_FAILURE);
- }
- state = 5;
- } else
- if (nat_exist(**argv)) {
- /* natengine */
- free(spec->natengine);
- spec->natengine = strdup(**argv);
- if (!spec->natengine) {
- fprintf(stderr,
- "Out of memory"
- "\n");
- exit(EXIT_FAILURE);
- }
- state = 0;
- } else {
- /* explicit target address */
- free(spec->natengine);
- spec->natengine = NULL;
- addr = **argv;
- state++;
- }
- break;
- case 4:
- /* dstport */
- af = sys_sockaddr_parse(&spec->connect_addr,
- &spec->connect_addrlen,
- addr, **argv, af, 0);
- if (af == -1) {
- exit(EXIT_FAILURE);
- }
- state = 0;
- break;
- case 5:
- /* SNI dstport */
- spec->sni_port = atoi(**argv);
- if (!spec->sni_port) {
- fprintf(stderr, "Invalid port '%s'\n",
- **argv);
- exit(EXIT_FAILURE);
- }
- spec->dns = 1;
- state = 0;
- break;
- }
- (*argv)++;
- }
- if (state != 0 && state != 3) {
- fprintf(stderr, "Incomplete proxyspec!\n");
- exit(EXIT_FAILURE);
- }
-
- return spec;
-}
-
-/*
- * Clear and free a proxy spec.
- */
-void
-proxyspec_free(proxyspec_t *spec)
-{
- do {
- proxyspec_t *next = spec->next;
- if (spec->natengine)
- free(spec->natengine);
- memset(spec, 0, sizeof(proxyspec_t));
- free(spec);
- spec = next;
- } while (spec);
-}
-
-/*
- * Return text representation of proxy spec for display to the user.
- * Returned string must be freed by caller.
- */
-char *
-proxyspec_str(proxyspec_t *spec)
-{
- char *s;
- char *lhbuf, *lpbuf;
- char *cbuf = NULL;
- if (sys_sockaddr_str((struct sockaddr *)&spec->listen_addr,
- spec->listen_addrlen, &lhbuf, &lpbuf) != 0) {
- return NULL;
- }
- if (spec->connect_addrlen) {
- char *chbuf, *cpbuf;
- if (sys_sockaddr_str((struct sockaddr *)&spec->connect_addr,
- spec->connect_addrlen,
- &chbuf, &cpbuf) != 0) {
- return NULL;
- }
- if (asprintf(&cbuf, "[%s]:%s", chbuf, cpbuf) < 0) {
- return NULL;
- }
- free(chbuf);
- free(cpbuf);
- }
- if (spec->sni_port) {
- if (asprintf(&cbuf, "sni %i", spec->sni_port) < 0) {
- return NULL;
- }
- }
- if (asprintf(&s, "[%s]:%s %s%s%s %s", lhbuf, lpbuf,
- (spec->ssl ? "ssl" : "tcp"),
- (spec->upgrade ? "|upgrade" : ""),
- (spec->http ? "|http" : ""),
- (spec->natengine ? spec->natengine : cbuf)) < 0) {
- s = NULL;
- }
- free(lhbuf);
- free(lpbuf);
- if (cbuf)
- free(cbuf);
- return s;
-}
-
-/* vim: set noet ft=c: */
diff --git a/proc.c b/proc.c
deleted file mode 100644
index 234875d..0000000
--- a/proc.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*-
- * SSLsplit - transparent SSL/TLS interception
- * https://www.roe.ch/SSLsplit
- *
- * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef __FreeBSD__
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/user.h>
-
-#include <netinet/in.h>
-#include <netinet/in_pcb.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_var.h>
-#include <arpa/inet.h>
-#endif /* __FreeBSD__ */
-
-#include "proc.h"
-
-#include "log.h"
-#include "attrib.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#ifdef HAVE_DARWIN_LIBPROC
-#include <libproc.h>
-#endif /* HAVE_DARWIN_LIBPROC */
-
-
-/*
- * Local process lookup.
- */
-
-
-#ifdef __FreeBSD__
-
-/*
- * Get the list of open files from the kernel and do basic consistency checks.
- * If successful, returns 0, and *pxfiles will receive a pointer to the
- * received xfiles structure and *pnxfiles the number of file records in it.
- * If unsuccessful, returns -1 and *pxfiles will be NULL.
- * Caller is responsible to free() *pxfiles after use.
- */
-static int
-proc_freebsd_getfiles(struct xfile **pxfiles, int *pnxfiles)
-{
- int mib[4];
- size_t sz;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_FILE;
- mib[2] = mib[3] = 0;
-
- for (;;) {
- if (sysctl(mib, 2, NULL, &sz, NULL, 0) < 0) {
- *pxfiles = NULL;
- return -1;
- }
- if (!(*pxfiles = malloc(sz))) {
- return -1;
- }
- if (sysctl(mib, 2, *pxfiles, &sz, NULL, 0) < 0) {
- free(*pxfiles);
- if (errno == ENOMEM)
- continue;
- *pxfiles = NULL;
- return -1;
- }
- break;
- }
-
- if (sz > 0 && (*pxfiles)->xf_size != sizeof **pxfiles) {
- log_err_printf("struct xfile size mismatch\n");
- return -1;
- }
- *pnxfiles = sz / sizeof **pxfiles;
-
- return 0;
-}
-
-/*
- * Get the list of active TCP connections and do basic consistency checks.
- * If successful, returns 0, and *pxig will receive a pointer to the
- * received data structure, *pexig a pointer to the end of the buffer.
- * If unsuccessful, returns -1 and *pxig will be NULL.
- * Caller is responsible to free() *pxig after use.
- */
-static int
-proc_freebsd_gettcppcblist(struct xinpgen **pxig, struct xinpgen **pexig)
-{
- int mib[4];
- size_t sz;
- int retry = 5;
-
- mib[0] = CTL_NET;
- mib[1] = PF_INET;
- mib[2] = IPPROTO_TCP;
- mib[3] = TCPCTL_PCBLIST;
- do {
- for (;;) {
- if (sysctl(mib, 4, NULL, &sz, NULL, 0) < 0) {
- *pxig = NULL;
- return -1;
- }
- if (!(*pxig = malloc(sz))) {
- return -1;
- }
- if (sysctl(mib, 4, *pxig, &sz, NULL, 0) < 0) {
- free(*pxig);
- if (errno == ENOMEM)
- continue;
- *pxig = NULL;
- return -1;
- }
- break;
- }
-
- *pexig = (struct xinpgen *)(void *)
- ((char *)(*pxig) + sz - sizeof(**pexig));
- if ((*pxig)->xig_len != sizeof(**pxig) ||
- (*pexig)->xig_len != sizeof(**pexig)) {
- log_err_printf("struct xinpgen size mismatch\n");
- free(*pxig);
- *pxig = NULL;
- return -1;
- }
- } while ((*pxig)->xig_gen != (*pexig)->xig_gen && retry--);
-
- /* check if first and last record are from same generation */
- if ((*pxig)->xig_gen != (*pexig)->xig_gen) {
- log_err_printf("Warning: data inconsistent "
- "(xig->xig_gen != exig->xig_gen)\n");
- }
-
- return 0;
-}
-
-int
-proc_freebsd_pid_for_addr(pid_t *result, struct sockaddr *src_addr,
- UNUSED socklen_t src_addrlen)
-{
- struct xfile *xfiles;
- int nxfiles;
- struct xfile *xf;
-
- struct xinpgen *xig, *exig, *txig;
- struct xtcpcb *xtp;
-#if __FreeBSD_version >= 1200026
- struct xinpcb *inp;
-#else
- struct inpcb *inp;
-#endif
- struct xsocket *so;
-
- if (proc_freebsd_getfiles(&xfiles, &nxfiles) == -1) {
- return -1;
- }
-
- if (proc_freebsd_gettcppcblist(&xig, &exig) == -1) {
- free(xfiles);
- return -1;
- }
-
- for (txig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
- txig < exig;
- txig = (struct xinpgen *)(void *)((char *)txig + txig->xig_len)) {
- xtp = (struct xtcpcb *)txig;
- if (xtp->xt_len != sizeof *xtp) {
- free(xfiles);
- free(xig);
- return -1;
- }
- inp = &xtp->xt_inp;
-#if __FreeBSD_version >= 1200026
- so = &inp->xi_socket;
-#else
- so = &xtp->xt_socket;
-#endif
-
- if (!(so->so_state & SS_ISCONNECTED))
- /* we are only interested in connected sockets */
- continue;
-
- if ((inp->inp_vflag & INP_IPV4) &&
- (src_addr->sa_family == AF_INET)) {
- struct sockaddr_in *src_sai =
- (struct sockaddr_in *)src_addr;
-
- if (src_sai->sin_addr.s_addr != inp->inp_laddr.s_addr) {
- continue;
- }
-
- if (src_sai->sin_port != inp->inp_lport) {
- continue;
- }
- } else if ((inp->inp_vflag & INP_IPV6) &&
- (src_addr->sa_family == AF_INET6)) {
- struct sockaddr_in6 *src_sai =
- (struct sockaddr_in6 *)src_addr;
-
- if (memcmp(src_sai->sin6_addr.s6_addr, inp->in6p_laddr.s6_addr, 16) != 0) {
- continue;
- }
-
- if (src_sai->sin6_port != inp->inp_lport) {
- continue;
- }
- } else {
- /* other address family */
- continue;
- }
-
- /* valid match */
-
- /* only do this if we have a match */
- xf = NULL;
- for (int i = 0; i < nxfiles; ++i) {
- if (so->xso_so == xfiles[i].xf_data) {
- /* there can be several processes sharing a
- * connected socket file descriptor */
- xf = &xfiles[i];
- }
- }
- if (!xf)
- continue;
- *result = xf->xf_pid;
- break;
- }
-
- free(xfiles);
- free(xig);
- return 0;
-}
-
-int
-proc_freebsd_get_info(pid_t pid, char **path, uid_t *uid, gid_t *gid) {
- static struct kinfo_proc proc;
- size_t len;
- int mib[4];
- char buf[PATH_MAX + 1];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PATHNAME;
- mib[3] = (int)pid;
- len = sizeof(buf);
- if (sysctl(mib, 4, buf, &len, NULL, 0) == -1) {
- if (errno != ESRCH) {
- log_err_printf("Failed to get proc pathname: %s (%i)",
- strerror(errno), errno);
- }
- *path = NULL;
- } else {
- *path = strdup(buf);
- }
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = (int)pid;
- len = sizeof proc;
- if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
- if (errno != ESRCH) {
- log_err_printf("Failed to get proc info: %s (%i)",
- strerror(errno), errno);
- }
- *uid = -1;
- *gid = -1;
- } else {
- if (*path == NULL)
- *path = strdup(proc.ki_comm);
- *uid = proc.ki_uid;
- *gid = proc.ki_groups[0];
- }
-
- return 0;
-}
-
-#endif /* __FreeBSD__ */
-
-
-#ifdef HAVE_DARWIN_LIBPROC
-
-int
-proc_darwin_pid_for_addr(pid_t *result, struct sockaddr *src_addr,
- UNUSED socklen_t src_addrlen)
-{
- pid_t *pids = NULL;
- struct proc_fdinfo *fds = NULL;
- int ret = -1;
-
- /* default result if no pid matches */
- *result = -1;
-
- /* iterate over all pids to find a matching socket */
- int pid_count = proc_listallpids(NULL, 0);
- if (pid_count <= 0)
- goto errout1;
- pids = malloc(sizeof(pid_t) * pid_count);
- if (!pids) {
- goto errout1;
- }
-
- pid_count = proc_listallpids(pids, sizeof(pid_t) * pid_count);
- if (pid_count <= 0)
- goto errout2;
-
- for (int i = 0; i < pid_count; i++) {
- pid_t pid = pids[i];
-
- /* fetch fd info for this pid */
- int fd_count = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
- if (fd_count <= 0) {
- /* failed to fetch pidinfo; process may have exited */
- continue;
- }
-
- if (fds) {
- free(fds);
- }
- fds = malloc(PROC_PIDLISTFD_SIZE * fd_count);
- if (!fds) {
- goto errout2;
- }
- fd_count = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds,
- sizeof(fds[0]) * fd_count);
-
- /* look for a matching socket file descriptor */
- for (int j = 0; j < fd_count; j++) {
- struct proc_fdinfo *fd = &fds[j];
- struct socket_fdinfo sinfo;
-
- if (fd->proc_fdtype != PROX_FDTYPE_SOCKET) {
- continue;
- }
-
- if (proc_pidfdinfo(pid, fd->proc_fd,
- PROC_PIDFDSOCKETINFO,
- &sinfo,
- sizeof(struct socket_fdinfo)) <= 0) {
- /* process may have exited or socket may have
- * been released. */
- continue;
- }
-
- if (sinfo.psi.soi_kind != SOCKINFO_TCP) {
- continue;
- }
-
- uint16_t sock_lport = sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport;
- if (sinfo.psi.soi_family == AF_INET &&
- src_addr->sa_family == AF_INET) {
- struct sockaddr_in *src_sai = (struct sockaddr_in *)src_addr;
-
- if (src_sai->sin_addr.s_addr != sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4.s_addr) {
- continue;
- }
-
- if (src_sai->sin_port != sock_lport) {
- continue;
- }
- } else if (sinfo.psi.soi_family == AF_INET6 &&
- src_addr->sa_family == AF_INET6) {
- struct sockaddr_in6 *src_sai = (struct sockaddr_in6 *)src_addr;
-
- if (memcmp(src_sai->sin6_addr.s6_addr, sinfo.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6.s6_addr, 16) != 0) {
- continue;
- }
-
- if (src_sai->sin6_port != sock_lport) {
- continue;
- }
- } else {
- /* other address family */
- continue;
- }
-
- /* valid match */
- *result = pid;
- goto success;
- }
- }
-
-success:
- ret = 0;
- free(fds);
-errout2:
- free(pids);
-errout1:
- return ret;
-}
-
-/*
- * Fetch process info for the given pid.
- * On success, returns 0 and fills in path, uid, and gid.
- * Caller must free returned path string.
- * Returns -1 on failure, or if unsupported on this platform.
- */
-int
-proc_darwin_get_info(pid_t pid, char **path, uid_t *uid, gid_t *gid) {
- /* fetch process structure */
- struct proc_bsdinfo bsd_info;
- if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &bsd_info,
- sizeof(bsd_info)) <= 0) {
- return -1;
- }
-
- *uid = bsd_info.pbi_uid;
- *gid = bsd_info.pbi_gid;
-
- /* fetch process path */
- *path = malloc(PROC_PIDPATHINFO_MAXSIZE);
- if (!*path) {
- return -1;
- }
- int path_len = proc_pidpath(pid, *path, PROC_PIDPATHINFO_MAXSIZE);
- if (path_len <= 0) {
- free(*path);
- *path = NULL;
- return -1;
- }
-
- return 0;
-}
-
-#endif /* HAVE_DARWIN_LIBPROC */
-
-/* vim: set noet ft=c: */
-
-
-
diff --git a/proc.h b/proc.h
deleted file mode 100644
index 232a416..0000000
--- a/proc.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * SSLsplit - transparent SSL/TLS interception
- * https://www.roe.ch/SSLsplit
- *
- * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PROC_H
-#define PROC_H
-
-#include "attrib.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <event2/util.h>
-
-#if defined(HAVE_DARWIN_LIBPROC) || defined(__FreeBSD__)
-#define HAVE_LOCAL_PROCINFO
-#endif
-
-#ifdef HAVE_DARWIN_LIBPROC
-#ifndef LOCAL_PROCINFO_STR
-#define LOCAL_PROCINFO_STR "Darwin libproc"
-#define proc_pid_for_addr(a,b,c) proc_darwin_pid_for_addr(a,b,c)
-#define proc_get_info(a,b,c,d) proc_darwin_get_info(a,b,c,d)
-#endif /* LOCAL_PROCINFO_STR */
-int proc_darwin_pid_for_addr(pid_t *, struct sockaddr *, socklen_t) WUNRES NONNULL(1,2);
-int proc_darwin_get_info(pid_t, char **, uid_t *, gid_t *) WUNRES NONNULL(2,3,4);
-#endif /* HAVE_DARWIN_LIBPROC */
-
-#ifdef __FreeBSD__
-#ifndef LOCAL_PROCINFO_STR
-#define LOCAL_PROCINFO_STR "FreeBSD sysctl"
-#define proc_pid_for_addr(a,b,c) proc_freebsd_pid_for_addr(a,b,c)
-#define proc_get_info(a,b,c,d) proc_freebsd_get_info(a,b,c,d)
-#endif /* LOCAL_PROCINFO_STR */
-int proc_freebsd_pid_for_addr(pid_t *, struct sockaddr *, socklen_t) WUNRES NONNULL(1,2);
-int proc_freebsd_get_info(pid_t, char **, uid_t *, gid_t *) WUNRES NONNULL(2,3,4);
-#endif /* __FreeBSD__ */
-
-#endif /* !PROC_H */
-
-/* vim: set noet ft=c: */
diff --git a/pxyconn.h b/pxyconn.h
deleted file mode 100644
index b02907e..0000000
--- a/pxyconn.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * SSLsplit - transparent SSL/TLS interception
- * https://www.roe.ch/SSLsplit
- *
- * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PXYCONN_H
-#define PXYCONN_H
-
-#include "opts.h"
-#include "attrib.h"
-#include "pxythrmgr.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <event2/event.h>
-#include <event2/util.h>
-
-void pxy_conn_setup(evutil_socket_t, struct sockaddr *, int,
- pxy_thrmgr_ctx_t *, proxyspec_t *, opts_t *)
- NONNULL(2,4,5,6);
-
-#endif /* !PXYCONN_H */
-
-/* vim: set noet ft=c: */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..7772e1c
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,15 @@
+find_package(OpenSSL REQUIRED)
+
+add_library(tfe-library base64.cc build.cc cache.cc cachemgr.cc cachessess.cc
+ cachedsess.cc cachetgcrt.cc cachefkcrt.cc cert.cc
+ dynbuf.cc logbuf.cc log.cc logger.cc nat.cc opts.cc
+ privsep.cc proxy.cc pxyconn.cc pxythrmgr.cc pxysslshut.cc
+ pxyhttp.cc ssl.cc sys.cc thrqueue.cc url.cc util.cc)
+
+target_include_directories(tfe-library PRIVATE ${OPENSSL_INCLUDE_DIR})
+target_link_libraries(tfe-library ${OPENSSL_LIBRARIES})
+target_link_libraries(tfe-library pthread libevent-static libevent-static-openssl
+ libevent-static-pthreads http-parser-static MESA_prof_load-static)
+
+add_executable(tfe main.cc)
+target_link_libraries(tfe tfe-library) \ No newline at end of file
diff --git a/attrib.h b/src/attrib.h
index 9b502bf..9b502bf 100644
--- a/attrib.h
+++ b/src/attrib.h
diff --git a/base64.c b/src/base64.cc
index 1069cc1..9496f08 100644
--- a/base64.c
+++ b/src/base64.cc
@@ -95,7 +95,7 @@ base64_dec(const char *in, size_t insz, size_t *outsz)
*outsz = ((insz / 4) * 3) - 1;
else
*outsz = (insz / 4) * 3;
- if (!(out = malloc((*outsz) + 1))) {
+ if (!(out = (unsigned char *)malloc((*outsz) + 1))) {
*outsz = 0;
return NULL;
}
@@ -161,7 +161,7 @@ base64_enc(const unsigned char *in, size_t insz, size_t *outsz)
}
*outsz = ((insz + 2) / 3) * 4;
- if (!(out = malloc((*outsz) + 1))) {
+ if (!(out = (char *)malloc((*outsz) + 1))) {
*outsz = 0;
return NULL;
}
diff --git a/base64.h b/src/base64.h
index 841f2d5..841f2d5 100644
--- a/base64.h
+++ b/src/base64.h
diff --git a/build.c b/src/build.cc
index eae3713..eae3713 100644
--- a/build.c
+++ b/src/build.cc
diff --git a/build.h b/src/build.h
index 18d41f8..18d41f8 100644
--- a/build.h
+++ b/src/build.h
diff --git a/cache.c b/src/cache.cc
index 624d523..c47ec0b 100644
--- a/cache.c
+++ b/src/cache.cc
@@ -45,7 +45,7 @@ cache_new(cache_init_cb_t init_cb)
{
cache_t *cache;
- if (!(cache = malloc(sizeof(cache_t))))
+ if (!(cache = (cache_t *)malloc(sizeof(cache_t))))
return NULL;
if (pthread_mutex_init(&cache->mutex, NULL)) {
diff --git a/cache.h b/src/cache.h
index 5f066e1..5f066e1 100644
--- a/cache.h
+++ b/src/cache.h
diff --git a/cachedsess.c b/src/cachedsess.cc
index 12ea476..5bd70d8 100644
--- a/cachedsess.c
+++ b/src/cachedsess.cc
@@ -95,25 +95,25 @@ cachedsess_del_cb(cache_iter_t it)
static cache_iter_t
cachedsess_get_cb(cache_key_t key)
{
- return kh_get(dynbufmap_t, dstsessmap, key);
+ return kh_get(dynbufmap_t, dstsessmap, (dynbuf_t *)key);
}
static cache_iter_t
cachedsess_put_cb(cache_key_t key, int *ret)
{
- return kh_put(dynbufmap_t, dstsessmap, key, ret);
+ return kh_put(dynbufmap_t, dstsessmap, (dynbuf_t *)key, ret);
}
static void
cachedsess_free_key_cb(cache_key_t key)
{
- dynbuf_free(key);
+ dynbuf_free((dynbuf_t *)key);
}
static void
cachedsess_free_val_cb(cache_val_t val)
{
- dynbuf_free(val);
+ dynbuf_free((dynbuf_t *)val);
}
static cache_key_t
@@ -131,13 +131,13 @@ cachedsess_get_val_cb(cache_iter_t it)
static void
cachedsess_set_val_cb(cache_iter_t it, cache_val_t val)
{
- kh_val(dstsessmap, it) = val;
+ kh_val(dstsessmap, it) = (dynbuf_t *)val;
}
static cache_val_t
cachedsess_unpackverify_val_cb(cache_val_t val, int copy)
{
- dynbuf_t *valbuf = val;
+ dynbuf_t *valbuf = (dynbuf_t *)val;
SSL_SESSION *sess;
const unsigned char *p;
diff --git a/cachedsess.h b/src/cachedsess.h
index c97fafe..c97fafe 100644
--- a/cachedsess.h
+++ b/src/cachedsess.h
diff --git a/cachefkcrt.c b/src/cachefkcrt.cc
index 7bf30da..e6cd216 100644
--- a/cachefkcrt.c
+++ b/src/cachefkcrt.cc
@@ -103,7 +103,7 @@ cachefkcrt_free_key_cb(cache_key_t key)
static void
cachefkcrt_free_val_cb(cache_val_t val)
{
- X509_free(val);
+ X509_free((x509_st *)val);
}
static cache_key_t
@@ -127,10 +127,10 @@ cachefkcrt_set_val_cb(cache_iter_t it, cache_val_t val)
static cache_val_t
cachefkcrt_unpackverify_val_cb(cache_val_t val, int copy)
{
- if (!ssl_x509_is_valid(val))
+ if (!ssl_x509_is_valid((x509_st *)val))
return NULL;
if (copy) {
- ssl_x509_refcount_inc(val);
+ ssl_x509_refcount_inc((X509 *)val);
return val;
}
return ((void*)-1);
@@ -167,7 +167,7 @@ cachefkcrt_mkkey(X509 *keycrt)
{
unsigned char *fpr;
- if (!(fpr = malloc(SSL_X509_FPRSZ)))
+ if (!(fpr = (unsigned char *)malloc(SSL_X509_FPRSZ)))
return NULL;
ssl_x509_fingerprint_sha1(keycrt, fpr);
return fpr;
diff --git a/cachefkcrt.h b/src/cachefkcrt.h
index 47adab1..47adab1 100644
--- a/cachefkcrt.h
+++ b/src/cachefkcrt.h
diff --git a/cachemgr.c b/src/cachemgr.cc
index ad00e0b..bdd3c00 100644
--- a/cachemgr.c
+++ b/src/cachemgr.cc
@@ -52,7 +52,7 @@ cache_t *cachemgr_dsess;
static void *
cachemgr_gc_thread(UNUSED void * arg)
{
- cache_gc(arg);
+ cache_gc((cache_t *)arg);
return NULL;
}
diff --git a/cachemgr.h b/src/cachemgr.h
index d66398c..d66398c 100644
--- a/cachemgr.h
+++ b/src/cachemgr.h
diff --git a/cachessess.c b/src/cachessess.cc
index ae54ff4..9bff1c9 100644
--- a/cachessess.c
+++ b/src/cachessess.cc
@@ -93,25 +93,25 @@ cachessess_del_cb(cache_iter_t it)
static cache_iter_t
cachessess_get_cb(cache_key_t key)
{
- return kh_get(dynbufmap_t, srcsessmap, key);
+ return kh_get(dynbufmap_t, srcsessmap, (dynbuf_t *)key);
}
static cache_iter_t
cachessess_put_cb(cache_key_t key, int *ret)
{
- return kh_put(dynbufmap_t, srcsessmap, key, ret);
+ return kh_put(dynbufmap_t, srcsessmap, (dynbuf_t *)key, ret);
}
static void
cachessess_free_key_cb(cache_key_t key)
{
- dynbuf_free(key);
+ dynbuf_free((dynbuf_t *)key);
}
static void
cachessess_free_val_cb(cache_val_t val)
{
- dynbuf_free(val);
+ dynbuf_free((dynbuf_t *)val);
}
static cache_key_t
@@ -129,13 +129,13 @@ cachessess_get_val_cb(cache_iter_t it)
static void
cachessess_set_val_cb(cache_iter_t it, cache_val_t val)
{
- kh_val(srcsessmap, it) = val;
+ kh_val(srcsessmap, it) = (dynbuf_t *)val;
}
static cache_val_t
cachessess_unpackverify_val_cb(cache_val_t val, int copy)
{
- dynbuf_t *valbuf = val;
+ dynbuf_t *valbuf = (dynbuf_t *)val;
SSL_SESSION *sess;
const unsigned char *p;
diff --git a/cachessess.h b/src/cachessess.h
index aacfd50..aacfd50 100644
--- a/cachessess.h
+++ b/src/cachessess.h
diff --git a/cachetgcrt.c b/src/cachetgcrt.cc
index 6da107d..5244f0c 100644
--- a/cachetgcrt.c
+++ b/src/cachetgcrt.cc
@@ -70,13 +70,13 @@ cachetgcrt_del_cb(cache_iter_t it)
static cache_iter_t
cachetgcrt_get_cb(cache_key_t key)
{
- return kh_get(cstrmap_t, certmap, key);
+ return kh_get(cstrmap_t, certmap, (char *)key);
}
static cache_iter_t
cachetgcrt_put_cb(cache_key_t key, int *ret)
{
- return kh_put(cstrmap_t, certmap, key, ret);
+ return kh_put(cstrmap_t, certmap, (char *)key, ret);
}
static void
@@ -88,7 +88,7 @@ cachetgcrt_free_key_cb(cache_key_t key)
static void
cachetgcrt_free_val_cb(cache_val_t val)
{
- cert_free(val);
+ cert_free((cert_t *)val);
}
static cache_key_t
@@ -113,7 +113,7 @@ static cache_val_t
cachetgcrt_unpackverify_val_cb(cache_val_t val, int copy)
{
if (copy) {
- cert_refcount_inc(val);
+ cert_refcount_inc((cert_t *)val);
return val;
}
return ((void*)-1);
diff --git a/cachetgcrt.h b/src/cachetgcrt.h
index b570b55..b570b55 100644
--- a/cachetgcrt.h
+++ b/src/cachetgcrt.h
diff --git a/cert.c b/src/cert.cc
index e6e4da2..8a5ba5f 100644
--- a/cert.c
+++ b/src/cert.cc
@@ -41,7 +41,7 @@ cert_new(void)
{
cert_t *c;
- if (!(c = malloc(sizeof(cert_t))))
+ if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
memset(c, 0, sizeof(cert_t));
if (pthread_mutex_init(&c->mutex, NULL)) {
@@ -61,7 +61,7 @@ cert_new3(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
{
cert_t *c;
- if (!(c = malloc(sizeof(cert_t))))
+ if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
if (pthread_mutex_init(&c->mutex, NULL)) {
free(c);
@@ -83,7 +83,7 @@ cert_new3_copy(EVP_PKEY *key, X509 *crt, STACK_OF(X509) *chain)
{
cert_t *c;
- if (!(c = malloc(sizeof(cert_t))))
+ if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
if (pthread_mutex_init(&c->mutex, NULL)) {
free(c);
@@ -109,7 +109,7 @@ cert_new_load(const char *filename)
{
cert_t *c;
- if (!(c = malloc(sizeof(cert_t))))
+ if (!(c = (cert_t *)malloc(sizeof(cert_t))))
return NULL;
memset(c, 0, sizeof(cert_t));
if (pthread_mutex_init(&c->mutex, NULL)) {
diff --git a/cert.h b/src/cert.h
index 841a11c..841a11c 100644
--- a/cert.h
+++ b/src/cert.h
diff --git a/src/cfgparser.h b/src/cfgparser.h
new file mode 100644
index 0000000..c7f0063
--- /dev/null
+++ b/src/cfgparser.h
@@ -0,0 +1,123 @@
+//
+// Created by luqiu on 2018-4-26.
+//
+
+#ifndef TFE_CFGPARSER_H
+#define TFE_CFGPARSER_H
+
+#ifndef TFE_STRING_MAX
+#define TFE_STRING_MAX 2048
+#endif
+
+#include <stdexcept>
+#include <string>
+#include <cstring>
+
+extern "C"
+{
+#include <MESA_prof_load.h>
+}
+
+class TfeConfigParser
+{
+public:
+ TfeConfigParser(std::string cfgfile) : str_cfgfile_(std::move(cfgfile))
+ {}
+ ~TfeConfigParser() = default;
+
+ /* 读入函数 */
+ template<typename T>
+ T GetValue(const std::string &str_section, const std::string &str_entry);
+ template<typename T>
+ T GetValueWithDefault(const std::string &str_section, const std::string &str_entry, const T &default_value);
+
+private:
+ std::string str_cfgfile_;
+};
+
+struct tfe_expection_cfg_invalid_format : std::runtime_error
+{
+ explicit tfe_expection_cfg_invalid_format(
+ const std::string &file,
+ const std::string &section,
+ const std::string &item,
+ const std::string &what) : file(file), section(section), item(item), runtime_error(what)
+ {}
+
+ std::string file;
+ std::string section;
+ std::string item;
+};
+
+struct tfe_expection_cfg_lost_entry : std::runtime_error
+{
+ explicit tfe_expection_cfg_lost_entry(
+ const std::string &file,
+ const std::string &section,
+ const std::string &item,
+ const std::string &what) : file(file), section(section), item(item), runtime_error(what)
+ {}
+
+ std::string file;
+ std::string section;
+ std::string item;
+};
+
+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 tfe_expection_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 tfe_expection_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,
+ const std::string &str_entry,
+ const T &default_value)
+{
+ T __value;
+
+ try
+ {
+ __value = GetValue<T>(str_section, str_entry);
+ }
+ catch (...)
+ {
+ return default_value;
+ }
+
+ return std::move(__value);
+}
+
+#endif //TFE_CFGPARSER_H
diff --git a/defaults.h b/src/defaults.h
index baf28bd..baf28bd 100644
--- a/defaults.h
+++ b/src/defaults.h
diff --git a/dynbuf.c b/src/dynbuf.cc
index 52ad014..9ddaecb 100644
--- a/dynbuf.c
+++ b/src/dynbuf.cc
@@ -44,9 +44,9 @@ dynbuf_new_alloc(size_t sz)
{
dynbuf_t *db;
- if (!(db = malloc(sizeof(dynbuf_t))))
+ if (!(db = (dynbuf_t *)malloc(sizeof(dynbuf_t))))
return NULL;
- if (!(db->buf = malloc(sz))) {
+ if (!(db->buf = (unsigned char *)malloc(sz))) {
free(db);
return NULL;
}
@@ -62,9 +62,9 @@ dynbuf_new_copy(const unsigned char *buf, const size_t sz)
{
dynbuf_t *db;
- if (!(db = malloc(sizeof(dynbuf_t))))
+ if (!(db = (dynbuf_t *)malloc(sizeof(dynbuf_t))))
return NULL;
- if (!(db->buf = malloc(sz))) {
+ if (!(db->buf = (unsigned char *)malloc(sz))) {
free(db);
return NULL;
}
@@ -83,7 +83,7 @@ dynbuf_new_file(const char *filename)
dynbuf_t *db;
FILE *f;
- if (!(db = malloc(sizeof(dynbuf_t))))
+ if (!(db = (dynbuf_t *)malloc(sizeof(dynbuf_t))))
return NULL;
f = fopen(filename, "rb");
@@ -94,7 +94,7 @@ dynbuf_new_file(const char *filename)
fseek(f, 0, SEEK_END);
db->sz = ftell(f);
fseek(f, 0, SEEK_SET);
- if (!(db->buf = malloc(db->sz))) {
+ if (!(db->buf = (unsigned char *)malloc(db->sz))) {
free(db);
fclose(f);
return NULL;
@@ -118,7 +118,7 @@ dynbuf_new(unsigned char *buf, size_t sz)
{
dynbuf_t *db;
- if (!(db = malloc(sizeof(dynbuf_t))))
+ if (!(db = (dynbuf_t *)malloc(sizeof(dynbuf_t))))
return NULL;
db->buf = buf;
db->sz = sz;
diff --git a/dynbuf.h b/src/dynbuf.h
index 7e89c63..7e89c63 100644
--- a/dynbuf.h
+++ b/src/dynbuf.h
diff --git a/khash.h b/src/khash.h
index e44f328..e44f328 100644
--- a/khash.h
+++ b/src/khash.h
diff --git a/log.c b/src/log.cc
index d231e8e..2a5c856 100644
--- a/log.c
+++ b/src/log.cc
@@ -397,7 +397,7 @@ log_content_split_pathspec(const char *path, char **lhs, char **rhs)
/* at last / terminating the static part of path */
p++; /* skip / */
- *lhs = malloc(p - path + 1 /* for terminating null */);
+ *lhs = (char *)malloc(p - path + 1 /* for terminating null */);
if (!*lhs)
return -1;
memcpy(*lhs, path, p - path);
@@ -424,7 +424,7 @@ log_content_format_pathspec(const char *logspec,
{
/* set up buffer to hold our generated file path */
size_t path_buflen = PATH_BUF_INC;
- char *path_buf = malloc(path_buflen);
+ char *path_buf = (char *)malloc(path_buflen);
if (path_buf == NULL) {
log_err_printf("failed to allocate path buffer\n");
return NULL;
@@ -543,7 +543,7 @@ log_content_format_pathspec(const char *logspec,
* Note that the use of `PATH_BUF_INC' provides
* our guaranteed space for a trailing '\0' */
path_buflen += elem_len + PATH_BUF_INC;
- char *newbuf = realloc(path_buf, path_buflen);
+ char *newbuf = (char *)realloc(path_buf, path_buflen);
if (newbuf == NULL) {
log_err_printf("failed to reallocate"
" path buffer\n");
@@ -566,7 +566,7 @@ log_content_format_pathspec(const char *logspec,
#undef PATH_BUF_INC
int
-log_content_open(log_content_ctx_t **pctx, opts_t *opts,
+log_content_open(log_content_ctx_t **pctx, struct tfe_config *opts,
char *srchost, char *srcport,
char *dsthost, char *dstport,
char *exec_path, char *user, char *group)
@@ -575,7 +575,8 @@ log_content_open(log_content_ctx_t **pctx, opts_t *opts,
if (*pctx)
return 0;
- *pctx = malloc(sizeof(log_content_ctx_t));
+
+ *pctx = (log_content_ctx_t *)malloc(sizeof(log_content_ctx_t));
if (!*pctx)
return -1;
ctx = *pctx;
@@ -720,7 +721,7 @@ out:
static int
log_content_dir_opencb(void *fh)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if ((ctx->u.dir.fd = privsep_client_openfile(content_clisock,
ctx->u.dir.filename,
@@ -735,7 +736,7 @@ log_content_dir_opencb(void *fh)
static void
log_content_dir_closecb(void *fh)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (ctx->u.dir.filename)
free(ctx->u.dir.filename);
@@ -747,7 +748,7 @@ log_content_dir_closecb(void *fh)
static ssize_t
log_content_dir_writecb(void *fh, const void *buf, size_t sz)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (write(ctx->u.dir.fd, buf, sz) == -1) {
log_err_printf("Warning: Failed to write to content log: %s\n",
@@ -760,7 +761,7 @@ log_content_dir_writecb(void *fh, const void *buf, size_t sz)
static int
log_content_spec_opencb(void *fh)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if ((ctx->u.spec.fd = privsep_client_openfile(content_clisock,
ctx->u.spec.filename,
@@ -775,7 +776,7 @@ log_content_spec_opencb(void *fh)
static void
log_content_spec_closecb(void *fh)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (ctx->u.spec.filename)
free(ctx->u.spec.filename);
@@ -787,7 +788,7 @@ log_content_spec_closecb(void *fh)
static ssize_t
log_content_spec_writecb(void *fh, const void *buf, size_t sz)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (write(ctx->u.spec.fd, buf, sz) == -1) {
log_err_printf("Warning: Failed to write to content log: %s\n",
@@ -858,7 +859,7 @@ log_content_file_opencb(void *fh)
static void
log_content_file_closecb(void *fh)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (ctx->u.file.header_req) {
free(ctx->u.file.header_req);
@@ -873,7 +874,7 @@ log_content_file_closecb(void *fh)
static ssize_t
log_content_file_writecb(void *fh, const void *buf, size_t sz)
{
- UNUSED log_content_ctx_t *ctx = fh;
+ UNUSED log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
if (write(content_file_fd, buf, sz) == -1) {
log_err_printf("Warning: Failed to write to content log: %s\n",
@@ -886,7 +887,7 @@ log_content_file_writecb(void *fh, const void *buf, size_t sz)
static logbuf_t *
log_content_file_prepcb(void *fh, unsigned long prepflags, logbuf_t *lb)
{
- log_content_ctx_t *ctx = fh;
+ log_content_ctx_t *ctx = (log_content_ctx_t *)fh;
int is_request = !!(prepflags & PREPFLAG_REQUEST);
logbuf_t *head;
time_t epoch;
@@ -969,7 +970,7 @@ errout1:
static ssize_t
log_cert_writecb(void *fh, const void *buf, size_t sz)
{
- char *fn = fh;
+ char *fn = (char *)fh;
int fd;
if ((fd = privsep_client_certfile(cert_clisock, fn)) == -1) {
@@ -1001,7 +1002,7 @@ log_cert_writecb(void *fh, const void *buf, size_t sz)
* Return -1 on errors, 0 otherwise.
*/
int
-log_preinit(opts_t *opts)
+log_preinit(struct tfe_config *opts)
{
logger_reopen_func_t reopencb;
logger_open_func_t opencb;
@@ -1116,7 +1117,7 @@ log_preinit_undo(void)
* Return -1 on errors, 0 otherwise.
*/
int
-log_init(opts_t *opts, proxy_ctx_t *ctx, int clisock1, int clisock2)
+log_init(struct tfe_config *opts, proxy_ctx_t *ctx, int clisock1, int clisock2)
{
proxy_ctx = ctx;
if (err_log)
diff --git a/log.h b/src/log.h
index 591c898..f6db99e 100644
--- a/log.h
+++ b/src/log.h
@@ -71,8 +71,9 @@ extern logger_t *connect_log;
logger_write_freebuf(connect_log, NULL, 0, (buf), (sz))
typedef struct log_content_ctx log_content_ctx_t;
-int log_content_open(log_content_ctx_t **, opts_t *, char *, char *, char *,
+int log_content_open(log_content_ctx_t **, struct tfe_config *, char *, char *, char *,
char *, char *, char *, char *) NONNULL(1,2,3) WUNRES;
+
int log_content_submit(log_content_ctx_t *, logbuf_t *, int)
NONNULL(1,2) WUNRES;
int log_content_close(log_content_ctx_t **, int) NONNULL(1) WUNRES;
@@ -81,9 +82,9 @@ int log_content_split_pathspec(const char *, char **,
int log_cert_submit(const char *, X509 *) NONNULL(1,2) WUNRES;
-int log_preinit(opts_t *) NONNULL(1) WUNRES;
+int log_preinit(struct tfe_config *) NONNULL(1) WUNRES;
void log_preinit_undo(void);
-int log_init(opts_t *, proxy_ctx_t *, int, int) NONNULL(1,2) WUNRES;
+int log_init(struct tfe_config *, proxy_ctx_t *, int, int) NONNULL(1,2) WUNRES;
void log_fini(void);
int log_reopen(void) WUNRES;
void log_exceptcb(void);
diff --git a/logbuf.c b/src/logbuf.cc
index 8c5f5b5..215b65a 100644
--- a/logbuf.c
+++ b/src/logbuf.cc
@@ -49,12 +49,12 @@ logbuf_new(void *buf, size_t sz, void *fh, logbuf_t *next)
{
logbuf_t *lb;
- if (!(lb = malloc(sizeof(logbuf_t)))) {
+ if (!(lb = (logbuf_t *)malloc(sizeof(logbuf_t)))) {
if (buf)
free(buf);
return NULL;
}
- lb->buf = buf;
+ lb->buf = (unsigned char *)buf;
lb->sz = sz;
lb->fh = fh;
lb->ctl = 0;
@@ -70,9 +70,9 @@ logbuf_new_alloc(size_t sz, void *fh, logbuf_t *next)
{
logbuf_t *lb;
- if (!(lb = malloc(sizeof(logbuf_t))))
+ if (!(lb = (logbuf_t *)malloc(sizeof(logbuf_t))))
return NULL;
- if (!(lb->buf = malloc(sz))) {
+ if (!(lb->buf = (unsigned char *)malloc(sz))) {
free(lb);
return NULL;
}
@@ -91,9 +91,9 @@ logbuf_new_copy(const void *buf, size_t sz, void *fh, logbuf_t *next)
{
logbuf_t *lb;
- if (!(lb = malloc(sizeof(logbuf_t))))
+ if (!(lb = (logbuf_t *)malloc(sizeof(logbuf_t))))
return NULL;
- if (!(lb->buf = malloc(sz))) {
+ if (!(lb->buf = (unsigned char *)malloc(sz))) {
free(lb);
return NULL;
}
@@ -114,7 +114,7 @@ logbuf_new_printf(void *fh, logbuf_t *next, const char *fmt, ...)
va_list ap;
logbuf_t *lb;
- if (!(lb = malloc(sizeof(logbuf_t))))
+ if (!(lb = (logbuf_t *)malloc(sizeof(logbuf_t))))
return NULL;
va_start(ap, fmt);
lb->sz = vasprintf((char**)&lb->buf, fmt, ap);
diff --git a/logbuf.h b/src/logbuf.h
index c371f90..c371f90 100644
--- a/logbuf.h
+++ b/src/logbuf.h
diff --git a/logger.c b/src/logger.cc
index c66d21d..3211744 100644
--- a/logger.c
+++ b/src/logger.cc
@@ -76,7 +76,7 @@ logger_new(logger_reopen_func_t reopenfunc, logger_open_func_t openfunc,
{
logger_t *logger;
- logger = malloc(sizeof(logger_t));
+ logger = (logger_t *)malloc(sizeof(logger_t));
if (!logger)
return NULL;
logger_clear(logger);
@@ -188,11 +188,11 @@ logger_close(logger_t *logger, void *fh)
static void *
logger_thread(void *arg)
{
- logger_t *logger = arg;
+ logger_t *logger = (logger_t *)arg;
logbuf_t *lb;
int e = 0;
- while ((lb = thrqueue_dequeue(logger->queue))) {
+ while ((lb = (logbuf_t *)thrqueue_dequeue(logger->queue))) {
if (logbuf_ctl_isset(lb, LBFLAG_REOPEN)) {
if (logger->reopen() != 0)
e = 1;
diff --git a/logger.h b/src/logger.h
index 6549cd0..6549cd0 100644
--- a/logger.h
+++ b/src/logger.h
diff --git a/main.c b/src/main.cc
index fd4d8f5..f1c1c54 100644
--- a/main.c
+++ b/src/main.cc
@@ -36,7 +36,6 @@
#include "privsep.h"
#include "ssl.h"
#include "nat.h"
-#include "proc.h"
#include "cachemgr.h"
#include "sys.h"
#include "log.h"
@@ -225,7 +224,7 @@ main_usage(void)
static int
main_loadtgcrt(const char *filename, void *arg)
{
- opts_t *opts = arg;
+ tfe_config *opts = arg;
cert_t *cert;
char **names;
@@ -292,13 +291,15 @@ main(int argc, char *argv[])
{
const char *argv0;
int ch;
- opts_t *opts;
+ tfe_config *opts;
+ proxy_ctx_t *proxy;
+
char *natengine;
int pidfd = -1;
int rv = EXIT_FAILURE;
argv0 = argv[0];
- opts = opts_new();
+ opts = tfe_config_new();
if (nat_getdefaultname()) {
natengine = strdup(nat_getdefaultname());
if (!natengine)
@@ -479,11 +480,9 @@ main(int argc, char *argv[])
if (!opts->ciphers)
oom_die(argv0);
break;
- case 'r':
- opts_proto_force(opts, optarg, argv0);
+ case 'r': tfe_config_proto_force(opts, optarg, argv0);
break;
- case 'R':
- opts_proto_disable(opts, optarg, argv0);
+ case 'R': tfe_config_proto_disable(opts, optarg, argv0);
break;
case 'e':
free(natengine);
@@ -705,7 +704,8 @@ main(int argc, char *argv[])
}
argc -= optind;
argv += optind;
- opts->spec = proxyspec_parse(&argc, &argv, natengine);
+
+ tfe_config_load_from_file(opts, "./config.ini");
/* usage checks before defaults */
if (opts->detach && OPTS_DEBUG(opts)) {
@@ -717,7 +717,7 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: no proxyspec specified.\n", argv0);
exit(EXIT_FAILURE);
}
- for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
+ for (proxyspec *spec = opts->spec; spec; spec = spec->next) {
if (spec->connect_addrlen || spec->sni_port)
continue;
if (!spec->natengine) {
@@ -736,7 +736,7 @@ main(int argc, char *argv[])
spec->natlookup = nat_getlookupcb(spec->natengine);
spec->natsocket = nat_getsocketcb(spec->natengine);
}
- if (opts_has_ssl_spec(opts)) {
+ if (tfe_config_has_ssl_spec(opts)) {
if (ssl_init() == -1) {
fprintf(stderr, "%s: failed to initialize OpenSSL.\n",
argv0);
@@ -801,7 +801,7 @@ main(int argc, char *argv[])
}
#endif /* __APPLE__ */
}
- if (opts_has_ssl_spec(opts) && opts->cakey && !opts->key) {
+ if (tfe_config_has_ssl_spec(opts) && opts->cakey && !opts->key) {
/*
* While browsers still generally accept it, use a leaf key
* size of 1024 bit for leaf keys. When browsers start to
@@ -865,9 +865,9 @@ main(int argc, char *argv[])
/* debugging */
if (OPTS_DEBUG(opts)) {
main_version();
- opts_proto_dbg_dump(opts);
+ tfe_config_proto_dbg_dump(opts);
log_dbg_printf("proxyspecs:\n");
- for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
+ for (proxyspec *spec = opts->spec; spec; spec = spec->next) {
char *specstr = proxyspec_str(spec);
if (!specstr) {
fprintf(stderr, "%s: out of memory\n", argv0);
@@ -957,7 +957,7 @@ main(int argc, char *argv[])
close(pidfd);
/* Initialize proxy before dropping privs */
- proxy_ctx_t *proxy = proxy_new(opts, clisock[0]);
+ proxy = proxy_new(opts, clisock[0]);
if (!proxy) {
log_err_printf("Failed to initialize proxy.\n");
exit(EXIT_FAILURE);
@@ -1001,7 +1001,7 @@ out_cachemgr_failed:
out_sslreinit_failed:
out_log_failed:
out_parent:
- opts_free(opts);
+ tfe_config_free(opts);
ssl_fini();
return rv;
}
diff --git a/nat.c b/src/nat.cc
index 2bd07f7..59fe153 100644
--- a/nat.c
+++ b/src/nat.cc
@@ -64,11 +64,14 @@
#endif /* HAVE_IPFILTER */
#ifdef HAVE_NETFILTER
+extern "C"
+{
#include <limits.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/if.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
+}
#endif /* HAVE_NETFILTER */
@@ -405,7 +408,7 @@ nat_getsockname_lookup_cb(struct sockaddr *dst_addr, socklen_t *dst_addrlen,
strerror(errno));
return -1;
}
- return 0;
+// return 0;
}
#endif
diff --git a/nat.h b/src/nat.h
index d126cbe..d126cbe 100644
--- a/nat.h
+++ b/src/nat.h
diff --git a/src/opts.cc b/src/opts.cc
new file mode 100644
index 0000000..067b40c
--- /dev/null
+++ b/src/opts.cc
@@ -0,0 +1,550 @@
+/*-
+ * SSLsplit - transparent SSL/TLS interception
+ * https://www.roe.ch/SSLsplit
+ *
+ * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opts.h"
+
+#include "sys.h"
+#include "log.h"
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <openssl/dh.h>
+#include <openssl/x509.h>
+#include <MESA_prof_load.h>
+#include <assert.h>
+
+#include "cfgparser.h"
+
+struct tfe_config *tfe_config_new()
+{
+ tfe_config *__config;
+
+ __config = (tfe_config *) malloc(sizeof(tfe_config));
+ memset(__config, 0, sizeof(tfe_config));
+
+ __config->sslcomp = 1;
+ __config->chain = sk_X509_new_null();
+ __config->sslmethod = SSLv23_method;
+
+ return __config;
+}
+
+#define TFE_STRING_MAX 4096
+
+static int __proxyspec_parse_each_entry(
+ tfe_config *cfg,
+ TfeConfigParser &ini_config_object,
+ const std::string &str_proxyspec)
+{
+ const std::string str_section = "proxyspec:" + str_proxyspec;
+ const char *cstr_str_section = str_section.c_str();
+
+ std::string str_listen_addr;
+ std::string str_listen_port;
+ std::string str_natengine;
+ std::string str_protocol;
+
+ str_listen_addr = ini_config_object.GetValue<std::string>(str_section, "listen_addr");
+ str_listen_port = ini_config_object.GetValue<std::string>(str_section, "listen_port");
+ str_natengine = ini_config_object.GetValue<std::string>(str_section, "natengine");
+ str_protocol = ini_config_object.GetValue<std::string>(str_section, "protocol");
+
+ struct proxyspec *__spec = (proxyspec *) malloc(sizeof(proxyspec));
+ memset(__spec, 0, sizeof(proxyspec));
+
+ if (str_protocol == "http")
+ {
+ __spec->ssl = 0;
+ __spec->http = 1;
+ __spec->upgrade = 0;
+ } else if (str_protocol == "https")
+ {
+ __spec->ssl = 1;
+ __spec->http = 1;
+ __spec->upgrade = 0;
+ } else if (str_protocol == "ssl")
+ {
+ __spec->ssl = 1;
+ __spec->http = 0;
+ __spec->upgrade = 0;
+ } else if (str_protocol == "autossl")
+ {
+ __spec->ssl = 0;
+ __spec->http = 0;
+ __spec->upgrade = 1;
+ }
+
+ __spec->natengine = strdup(str_natengine.c_str());
+ assert(__spec->natengine != nullptr);
+
+ int ret = sys_sockaddr_parse(&__spec->listen_addr, &__spec->listen_addrlen, str_listen_addr.c_str(),
+ str_listen_port.c_str(), AF_INET, EVUTIL_AI_PASSIVE);
+ if (ret < 0)
+ {
+ throw tfe_expection_cfg_invalid_format("", "", "", "");
+ }
+
+ log_dbg_printf("Proxyspec %s: Listen Address %s, Port %s, Protocol %s\n", str_proxyspec.c_str(),
+ str_listen_addr.c_str(), str_listen_port.c_str(), str_protocol.c_str());
+
+
+ /* 插入到Spec链表头部 */
+ __spec->next = cfg->spec;
+ cfg->spec = __spec;
+
+ return 0;
+}
+
+static int __ssl_protocol_load_from_file(tfe_config *cfg, TfeConfigParser &cfg_parser)
+{
+ bool __en_tls_1_0 = true;
+ bool __en_tls_1_1 = true;
+ bool __en_tls_1_2 = true;
+ bool __en_ssl_v2 = true;
+ bool __en_ssl_v3 = true;
+
+ __en_tls_1_0 = cfg_parser.GetValueWithDefault("ssl_protocol", "tls_v1_0", __en_tls_1_0);
+ __en_tls_1_1 = cfg_parser.GetValueWithDefault("ssl_protocol", "tls_v1_1", __en_tls_1_1);
+ __en_tls_1_2 = cfg_parser.GetValueWithDefault("ssl_protocol", "tls_v1_2", __en_tls_1_2);
+ __en_ssl_v2 = cfg_parser.GetValueWithDefault("ssl_protocol", "ssl_v2", __en_ssl_v2);
+ __en_ssl_v3 = cfg_parser.GetValueWithDefault("ssl_protocol", "ssl_v3", __en_ssl_v3);
+
+ if (!__en_tls_1_0) cfg->no_tls10 = 1;
+ if (!__en_tls_1_1) cfg->no_tls11 = 1;
+ if (!__en_tls_1_2) cfg->no_tls12 = 1;
+ if (!__en_ssl_v2) cfg->no_ssl2 = 1;
+ if (!__en_ssl_v3) cfg->no_ssl3 = 1;
+
+ return 0;
+}
+
+void tfe_config_load_from_file(tfe_config *cfg, const char *c_str_file)
+{
+ TfeConfigParser __config_parser(c_str_file);
+
+ try
+ {
+ /* 读取ProxySpec列表 */
+ std::string str_proxyspec_symbol = __config_parser.GetValue<std::string>("proxyspec", "symbol");
+ char *__buffer_proxyspec = strdup(str_proxyspec_symbol.c_str());
+
+ /* 拆分列表,根据列表读取详细配置 */
+ for (const char *__str_token = strtok(__buffer_proxyspec, ",");
+ __str_token != nullptr; __str_token = strtok(nullptr, ","))
+ {
+ __proxyspec_parse_each_entry(cfg, __config_parser, std::string(__str_token));
+ }
+
+ /* 解析SSL/TLS版本功能开关 */
+ __ssl_protocol_load_from_file(cfg, __config_parser);
+ }
+ catch (tfe_expection_cfg_invalid_format &e)
+ {
+ log_err_printf("Invalid format config entries in file %s, section %s, entry %s.",
+ e.file.c_str(), e.section.c_str(), e.item.c_str());
+ goto __errout;
+ }
+
+ catch (tfe_expection_cfg_lost_entry &e)
+ {
+ log_err_printf("Required config entries is not existed in file %s, section %s, entry %s.",
+ e.file.c_str(), e.section.c_str(), e.item.c_str());
+ goto __errout;
+ }
+
+ return;
+
+__errout:
+ exit(EXIT_FAILURE);
+}
+
+void tfe_config_parse_args(tfe_config *tfe, int argc, char **argv)
+{
+ return;
+}
+
+void tfe_config_free(tfe_config *opts)
+{
+ sk_X509_pop_free(opts->chain, X509_free);
+
+ if (opts->cacrt)
+ X509_free(opts->cacrt);
+
+ if (opts->cakey)
+ EVP_PKEY_free(opts->cakey);
+
+ if (opts->key)
+ EVP_PKEY_free(opts->key);
+
+ if (opts->dh)
+ DH_free(opts->dh);
+
+ if (opts->ecdhcurve)
+ free(opts->ecdhcurve);
+
+ if (opts->spec)
+ proxyspec_free(opts->spec);
+
+ if (opts->ciphers)
+ free(opts->ciphers);
+
+ if (opts->tgcrtdir)
+ free(opts->tgcrtdir);
+
+ if (opts->crlurl)
+ free(opts->crlurl);
+
+ if (opts->dropuser)
+ free(opts->dropuser);
+
+ if (opts->dropgroup)
+ free(opts->dropgroup);
+
+ if (opts->jaildir)
+ free(opts->jaildir);
+
+ if (opts->pidfile)
+ free(opts->pidfile);
+
+ if (opts->connectlog)
+ free(opts->connectlog);
+
+ if (opts->contentlog)
+ free(opts->contentlog);
+
+ if (opts->certgendir)
+ free(opts->certgendir);
+
+ if (opts->contentlog_basedir)
+ free(opts->contentlog_basedir);
+
+ if (opts->masterkeylog)
+ free(opts->masterkeylog);
+
+ memset(opts, 0, sizeof(tfe_config));
+ free(opts);
+}
+
+/*
+ * Return 1 if opts_t contains a proxyspec that (eventually) uses SSL/TLS,
+ * 0 otherwise. When 0, it is safe to assume that no SSL/TLS operations
+ * will take place with this configuration.
+ */
+int
+tfe_config_has_ssl_spec(tfe_config *opts)
+{
+ proxyspec *p = opts->spec;
+
+ while (p)
+ {
+ if (p->ssl || p->upgrade)
+ return 1;
+ p = p->next;
+ }
+
+ return 0;
+}
+
+/*
+ * Return 1 if opts_t contains a proxyspec with dns, 0 otherwise.
+ */
+int
+tfe_config_has_dns_spec(tfe_config *opts)
+{
+ proxyspec *p = opts->spec;
+
+ while (p)
+ {
+ if (p->dns)
+ return 1;
+ p = p->next;
+ }
+
+ return 0;
+}
+
+/*
+ * Parse SSL proto string in optarg and look up the corresponding SSL method.
+ * Calls exit() on failure.
+ */
+void
+tfe_config_proto_force(tfe_config *opts, const char *optarg, const char *argv0)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ if (opts->sslmethod != SSLv23_method)
+ {
+#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ if (opts->sslversion) {
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ fprintf(stderr, "%s: cannot use -r multiple times\n", argv0);
+ exit(EXIT_FAILURE);
+ }
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#ifdef HAVE_SSLV2
+ if (!strcmp(optarg, "ssl2")) {
+ opts->sslmethod = SSLv2_method;
+ } else
+#endif /* HAVE_SSLV2 */
+#ifdef HAVE_SSLV3
+ if (!strcmp(optarg, "ssl3"))
+ {
+ opts->sslmethod = SSLv3_method;
+ } else
+#endif /* HAVE_SSLV3 */
+#ifdef HAVE_TLSV10
+ if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1"))
+ {
+ opts->sslmethod = TLSv1_method;
+ } else
+#endif /* HAVE_TLSV10 */
+#ifdef HAVE_TLSV11
+ if (!strcmp(optarg, "tls11"))
+ {
+ opts->sslmethod = TLSv1_1_method;
+ } else
+#endif /* HAVE_TLSV11 */
+#ifdef HAVE_TLSV12
+ if (!strcmp(optarg, "tls12"))
+ {
+ opts->sslmethod = TLSv1_2_method;
+ } else
+#endif /* HAVE_TLSV12 */
+#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ /*
+ * Support for SSLv2 and the corresponding SSLv2_method(),
+ * SSLv2_server_method() and SSLv2_client_method() functions were
+ * removed in OpenSSL 1.1.0.
+ */
+#ifdef HAVE_SSLV3
+ if (!strcmp(optarg, "ssl3")) {
+ opts->sslversion = SSL3_VERSION;
+ } else
+#endif /* HAVE_SSLV3 */
+#ifdef HAVE_TLSV10
+ if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
+ opts->sslversion = TLS1_VERSION;
+ } else
+#endif /* HAVE_TLSV10 */
+#ifdef HAVE_TLSV11
+ if (!strcmp(optarg, "tls11")) {
+ opts->sslversion = TLS1_1_VERSION;
+ } else
+#endif /* HAVE_TLSV11 */
+#ifdef HAVE_TLSV12
+ if (!strcmp(optarg, "tls12")) {
+ opts->sslversion = TLS1_2_VERSION;
+ } else
+#endif /* HAVE_TLSV12 */
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ {
+ fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
+ argv0, optarg);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*
+ * Parse SSL proto string in optarg and set the corresponding no_foo bit.
+ * Calls exit() on failure.
+ */
+void
+tfe_config_proto_disable(tfe_config *opts, const char *optarg, const char *argv0)
+{
+#ifdef HAVE_SSLV2
+ if (!strcmp(optarg, "ssl2")) {
+ opts->no_ssl2 = 1;
+ } else
+#endif /* HAVE_SSLV2 */
+#ifdef HAVE_SSLV3
+ if (!strcmp(optarg, "ssl3"))
+ {
+ opts->no_ssl3 = 1;
+ } else
+#endif /* HAVE_SSLV3 */
+#ifdef HAVE_TLSV10
+ if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1"))
+ {
+ opts->no_tls10 = 1;
+ } else
+#endif /* HAVE_TLSV10 */
+#ifdef HAVE_TLSV11
+ if (!strcmp(optarg, "tls11"))
+ {
+ opts->no_tls11 = 1;
+ } else
+#endif /* HAVE_TLSV11 */
+#ifdef HAVE_TLSV12
+ if (!strcmp(optarg, "tls12"))
+ {
+ opts->no_tls12 = 1;
+ } else
+#endif /* HAVE_TLSV12 */
+ {
+ fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
+ argv0, optarg);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*
+ * Dump the SSL/TLS protocol related configuration to the debug log.
+ */
+void
+tfe_config_proto_dbg_dump(tfe_config *opts)
+{
+ log_dbg_printf("SSL/TLS protocol: %s%s%s%s%s%s\n",
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#ifdef HAVE_SSLV2
+ (opts->sslmethod == SSLv2_method) ? "ssl2" :
+#endif /* HAVE_SSLV2 */
+#ifdef HAVE_SSLV3
+ (opts->sslmethod == SSLv3_method) ? "ssl3" :
+ #endif /* HAVE_SSLV3 */
+ #ifdef HAVE_TLSV10
+ (opts->sslmethod == TLSv1_method) ? "tls10" :
+ #endif /* HAVE_TLSV10 */
+ #ifdef HAVE_TLSV11
+ (opts->sslmethod == TLSv1_1_method) ? "tls11" :
+ #endif /* HAVE_TLSV11 */
+ #ifdef HAVE_TLSV12
+ (opts->sslmethod == TLSv1_2_method) ? "tls12" :
+ #endif /* HAVE_TLSV12 */
+ #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ #ifdef HAVE_SSLV3
+ (opts->sslversion == SSL3_VERSION) ? "ssl3" :
+#endif /* HAVE_SSLV3 */
+#ifdef HAVE_TLSV10
+ (opts->sslversion == TLS1_VERSION) ? "tls10" :
+#endif /* HAVE_TLSV10 */
+#ifdef HAVE_TLSV11
+ (opts->sslversion == TLS1_1_VERSION) ? "tls11" :
+#endif /* HAVE_TLSV11 */
+#ifdef HAVE_TLSV12
+ (opts->sslversion == TLS1_2_VERSION) ? "tls12" :
+#endif /* HAVE_TLSV12 */
+ #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ "negotiate",
+#ifdef HAVE_SSLV2
+ opts->no_ssl2 ? " -ssl2" :
+#endif /* HAVE_SSLV2 */
+ "",
+#ifdef HAVE_SSLV3
+ opts->no_ssl3 ? " -ssl3" :
+ #endif /* HAVE_SSLV3 */
+ "",
+#ifdef HAVE_TLSV10
+ opts->no_tls10 ? " -tls10" :
+ #endif /* HAVE_TLSV10 */
+ "",
+#ifdef HAVE_TLSV11
+ opts->no_tls11 ? " -tls11" :
+ #endif /* HAVE_TLSV11 */
+ "",
+#ifdef HAVE_TLSV12
+ opts->no_tls12 ? " -tls12" :
+ #endif /* HAVE_TLSV12 */
+ "");
+}
+
+/*
+ * Clear and free a proxy spec.
+ */
+void
+proxyspec_free(proxyspec *spec)
+{
+ do
+ {
+ proxyspec *next = spec->next;
+ if (spec->natengine)
+ free(spec->natengine);
+ memset(spec, 0, sizeof(proxyspec));
+ free(spec);
+ spec = next;
+ } while (spec);
+}
+
+/*
+ * Return text representation of proxy spec for display to the user.
+ * Returned string must be freed by caller.
+ */
+char *proxyspec_str(proxyspec *spec)
+{
+ char *s;
+ char *lhbuf, *lpbuf;
+ char *cbuf = NULL;
+ if (sys_sockaddr_str((struct sockaddr *) &spec->listen_addr,
+ spec->listen_addrlen, &lhbuf, &lpbuf) != 0)
+ {
+ return NULL;
+ }
+ if (spec->connect_addrlen)
+ {
+ char *chbuf, *cpbuf;
+ if (sys_sockaddr_str((struct sockaddr *) &spec->connect_addr,
+ spec->connect_addrlen,
+ &chbuf, &cpbuf) != 0)
+ {
+ return NULL;
+ }
+ if (asprintf(&cbuf, "[%s]:%s", chbuf, cpbuf) < 0)
+ {
+ return NULL;
+ }
+ free(chbuf);
+ free(cpbuf);
+ }
+ if (spec->sni_port)
+ {
+ if (asprintf(&cbuf, "sni %i", spec->sni_port) < 0)
+ {
+ return NULL;
+ }
+ }
+ if (asprintf(&s, "[%s]:%s %s%s%s %s", lhbuf, lpbuf,
+ (spec->ssl ? "ssl" : "tcp"),
+ (spec->upgrade ? "|upgrade" : ""),
+ (spec->http ? "|http" : ""),
+ (spec->natengine ? spec->natengine : cbuf)) < 0)
+ {
+ s = NULL;
+ }
+ free(lhbuf);
+ free(lpbuf);
+ if (cbuf)
+ free(cbuf);
+ return s;
+}
+
+/* vim: set noet ft=c: */
diff --git a/opts.h b/src/opts.h
index f5e9f27..72d81a7 100644
--- a/opts.h
+++ b/src/opts.h
@@ -29,7 +29,6 @@
#ifndef OPTS_H
#define OPTS_H
-#include "proc.h"
#include "nat.h"
#include "ssl.h"
#include "attrib.h"
@@ -37,7 +36,8 @@
#include <sys/types.h>
#include <sys/socket.h>
-typedef struct proxyspec {
+struct proxyspec
+{
unsigned int ssl : 1;
unsigned int http : 1;
unsigned int upgrade: 1;
@@ -54,35 +54,28 @@ typedef struct proxyspec {
nat_lookup_cb_t natlookup;
nat_socket_cb_t natsocket;
struct proxyspec *next;
-} proxyspec_t;
+};
-typedef struct opts {
+struct tfe_config
+{
+ /* Configure Files */
+ char * cfgfile;
+
+ /* Options */
unsigned int debug : 1;
unsigned int detach : 1;
unsigned int sslcomp : 1;
-#ifdef HAVE_SSLV2
unsigned int no_ssl2 : 1;
-#endif /* HAVE_SSLV2 */
-#ifdef HAVE_SSLV3
unsigned int no_ssl3 : 1;
-#endif /* HAVE_SSLV3 */
-#ifdef HAVE_TLSV10
unsigned int no_tls10 : 1;
-#endif /* HAVE_TLSV10 */
-#ifdef HAVE_TLSV11
unsigned int no_tls11 : 1;
-#endif /* HAVE_TLSV11 */
-#ifdef HAVE_TLSV12
unsigned int no_tls12 : 1;
-#endif /* HAVE_TLSV12 */
unsigned int passthrough : 1;
unsigned int deny_ocsp : 1;
unsigned int contentlog_isdir : 1;
unsigned int contentlog_isspec : 1;
-#ifdef HAVE_LOCAL_PROCINFO
- unsigned int lprocinfo : 1;
-#endif /* HAVE_LOCAL_PROCINFO */
unsigned int certgen_writeall: 1;
+
char *ciphers;
char *certgendir;
char *tgcrtdir;
@@ -95,35 +88,31 @@ typedef struct opts {
char *contentlog_basedir; /* static part of logspec, for privsep srv */
char *masterkeylog;
CONST_SSL_METHOD *(*sslmethod)(void);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
int sslversion;
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
X509 *cacrt;
EVP_PKEY *cakey;
EVP_PKEY *key;
STACK_OF(X509) *chain;
-#ifndef OPENSSL_NO_DH
DH *dh;
-#endif /* !OPENSSL_NO_DH */
-#ifndef OPENSSL_NO_ECDH
char *ecdhcurve;
-#endif /* !OPENSSL_NO_ECDH */
- proxyspec_t *spec;
+
+ struct proxyspec * spec;
char *crlurl;
-} opts_t;
+};
+
+struct tfe_config *tfe_config_new(void) MALLOC;
+void tfe_config_free(struct tfe_config *) NONNULL(1);
+int tfe_config_has_ssl_spec(struct tfe_config *) NONNULL(1) WUNRES;
+int tfe_config_has_dns_spec(struct tfe_config *) NONNULL(1) WUNRES;
+void tfe_config_proto_force(struct tfe_config *, const char *, const char *) NONNULL(1,2,3);
+void tfe_config_proto_disable(struct tfe_config *, const char *, const char *) NONNULL(1,2,3);
+void tfe_config_proto_dbg_dump(struct tfe_config *) NONNULL(1);
+void tfe_config_load_from_file(tfe_config *cfg, const char *c_str_file);
-opts_t *opts_new(void) MALLOC;
-void opts_free(opts_t *) NONNULL(1);
-int opts_has_ssl_spec(opts_t *) NONNULL(1) WUNRES;
-int opts_has_dns_spec(opts_t *) NONNULL(1) WUNRES;
-void opts_proto_force(opts_t *, const char *, const char *) NONNULL(1,2,3);
-void opts_proto_disable(opts_t *, const char *, const char *) NONNULL(1,2,3);
-void opts_proto_dbg_dump(opts_t *) NONNULL(1);
#define OPTS_DEBUG(opts) unlikely((opts)->debug)
-proxyspec_t * proxyspec_parse(int *, char **[], const char *) MALLOC;
-void proxyspec_free(proxyspec_t *) NONNULL(1);
-char * proxyspec_str(proxyspec_t *) NONNULL(1) MALLOC;
+void proxyspec_free(struct proxyspec *) NONNULL(1);
+char * proxyspec_str(struct proxyspec *) NONNULL(1) MALLOC;
#endif /* !OPTS_H */
diff --git a/privsep.c b/src/privsep.cc
index 61d425f..794e2e2 100644
--- a/privsep.c
+++ b/src/privsep.cc
@@ -135,7 +135,7 @@ privsep_server_signal_handler(int sig)
}
static int WUNRES
-privsep_server_openfile_verify(opts_t *opts, char *fn, int mkpath)
+privsep_server_openfile_verify(tfe_config *opts, char *fn, int mkpath)
{
if (mkpath && !opts->contentlog_isspec)
return -1;
@@ -188,9 +188,9 @@ privsep_server_openfile(char *fn, int mkpath)
}
static int WUNRES
-privsep_server_opensock_verify(opts_t *opts, void *arg)
+privsep_server_opensock_verify(tfe_config *opts, void *arg)
{
- for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
+ for (proxyspec *spec = opts->spec; spec; spec = spec->next) {
if (spec == arg)
return 0;
}
@@ -198,7 +198,7 @@ privsep_server_opensock_verify(opts_t *opts, void *arg)
}
static int WUNRES
-privsep_server_opensock(proxyspec_t *spec)
+privsep_server_opensock(proxyspec *spec)
{
evutil_socket_t fd;
int on = 1;
@@ -254,7 +254,7 @@ privsep_server_opensock(proxyspec_t *spec)
}
static int WUNRES
-privsep_server_certfile_verify(opts_t *opts, char *fn)
+privsep_server_certfile_verify(tfe_config *opts, char *fn)
{
if (!opts->certgendir)
return -1;
@@ -282,7 +282,7 @@ privsep_server_certfile(char *fn)
* Returns 0 on success, 1 on EOF and -1 on error.
*/
static int WUNRES
-privsep_server_handle_req(opts_t *opts, int srvsock)
+privsep_server_handle_req(tfe_config *opts, int srvsock)
{
char req[PRIVSEP_MAX_REQ_SIZE];
char ans[PRIVSEP_MAX_ANS_SIZE];
@@ -374,7 +374,7 @@ privsep_server_handle_req(opts_t *opts, int srvsock)
break;
}
case PRIVSEP_REQ_OPENSOCK: {
- proxyspec_t *arg;
+ proxyspec *arg;
int s;
if (n != sizeof(char) + sizeof(arg)) {
@@ -386,7 +386,7 @@ privsep_server_handle_req(opts_t *opts, int srvsock)
}
return 0;
}
- arg = *(proxyspec_t**)(&req[1]);
+ arg = *(proxyspec**)(&req[1]);
if (privsep_server_opensock_verify(opts, arg) == -1) {
ans[0] = PRIVSEP_ANS_DENIED;
if (sys_sendmsgfd(srvsock, ans, 1, -1) == -1) {
@@ -504,7 +504,7 @@ privsep_server_handle_req(opts_t *opts, int srvsock)
* Returns 0 on a successful clean exit and -1 on errors.
*/
static int
-privsep_server(opts_t *opts, int sigpipe, int srvsock[], size_t nsrvsock,
+privsep_server(tfe_config *opts, int sigpipe, int srvsock[], size_t nsrvsock,
pid_t childpid)
{
int srveof[nsrvsock];
@@ -697,7 +697,7 @@ privsep_client_openfile(int clisock, const char *fn, int mkpath)
}
int
-privsep_client_opensock(int clisock, const proxyspec_t *spec)
+privsep_client_opensock(int clisock, const proxyspec *spec)
{
char ans[PRIVSEP_MAX_ANS_SIZE];
char req[1 + sizeof(spec)];
@@ -705,7 +705,7 @@ privsep_client_opensock(int clisock, const proxyspec_t *spec)
ssize_t n;
req[0] = PRIVSEP_REQ_OPENSOCK;
- *((const proxyspec_t **)&req[1]) = spec;
+ *((const proxyspec **)&req[1]) = spec;
if (sys_sendmsgfd(clisock, req, sizeof(req), -1) == -1) {
return -1;
@@ -814,7 +814,7 @@ privsep_client_close(int clisock)
* will not be touched.
*/
int
-privsep_fork(opts_t *opts, int clisock[], size_t nclisock)
+privsep_fork(tfe_config *opts, int clisock[], size_t nclisock)
{
int selfpipev[2]; /* self-pipe trick: signal handler -> select */
int chldpipev[2]; /* el cheapo interprocess sync early after fork */
diff --git a/privsep.h b/src/privsep.h
index b59dab4..d12f8d8 100644
--- a/privsep.h
+++ b/src/privsep.h
@@ -32,10 +32,10 @@
#include "attrib.h"
#include "opts.h"
-int privsep_fork(opts_t *, int[], size_t);
+int privsep_fork(struct tfe_config *, int[], size_t);
int privsep_client_openfile(int, const char *, int);
-int privsep_client_opensock(int, const proxyspec_t *spec);
+int privsep_client_opensock(int, const proxyspec *spec);
int privsep_client_certfile(int, const char *);
int privsep_client_close(int);
diff --git a/proxy.c b/src/proxy.cc
index 9e9d6e2..78f788a 100644
--- a/proxy.c
+++ b/src/proxy.cc
@@ -59,35 +59,38 @@
static int signals[] = { SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1 };
-struct proxy_ctx {
+struct proxy_ctx
+{
pxy_thrmgr_ctx_t *thrmgr;
struct event_base *evbase;
struct event *sev[sizeof(signals)/sizeof(int)];
struct event *gcev;
struct proxy_listener_ctx *lctx;
- opts_t *opts;
+ struct tfe_config *opts;
};
/*
* Listener context.
*/
-typedef struct proxy_listener_ctx {
+typedef struct proxy_listener_ctx
+{
pxy_thrmgr_ctx_t *thrmgr;
- proxyspec_t *spec;
- opts_t *opts;
+ 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(pxy_thrmgr_ctx_t *thrmgr, proxyspec_t *spec,
- opts_t *opts) MALLOC;
+proxy_listener_ctx_new(pxy_thrmgr_ctx_t *thrmgr, proxyspec *spec,
+ tfe_config *opts) MALLOC;
static proxy_listener_ctx_t *
-proxy_listener_ctx_new(pxy_thrmgr_ctx_t *thrmgr, proxyspec_t *spec,
- opts_t *opts)
+proxy_listener_ctx_new(pxy_thrmgr_ctx_t *thrmgr, proxyspec *spec,
+ tfe_config *opts)
{
- proxy_listener_ctx_t *ctx = malloc(sizeof(proxy_listener_ctx_t));
+ 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));
@@ -162,7 +165,7 @@ proxy_debug_base(const struct event_base *ev_base)
*/
static proxy_listener_ctx_t *
proxy_listener_setup(struct event_base *evbase, pxy_thrmgr_ctx_t *thrmgr,
- proxyspec_t *spec, opts_t *opts, int clisock)
+ proxyspec *spec, tfe_config *opts, int clisock)
{
proxy_listener_ctx_t *plc;
int fd;
@@ -251,13 +254,15 @@ proxy_gc_cb(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
* Returns ctx on success, or NULL on error.
*/
proxy_ctx_t *
-proxy_new(opts_t *opts, int clisock)
+proxy_new(tfe_config *opts, int clisock)
{
proxy_listener_ctx_t *head;
proxy_ctx_t *ctx;
struct evdns_base *dnsbase;
int rc;
+ struct timeval gc_delay = {60, 0};
+
/* adds locking, only required if accessed from separate threads */
evthread_use_pthreads();
@@ -281,7 +286,7 @@ proxy_new(opts_t *opts, int clisock)
goto leave1;
}
- if (opts_has_dns_spec(opts)) {
+ 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);
@@ -317,7 +322,7 @@ proxy_new(opts_t *opts, int clisock)
}
head = ctx->lctx = NULL;
- for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
+ for (proxyspec *spec = opts->spec; spec; spec = spec->next) {
head = proxy_listener_setup(ctx->evbase, ctx->thrmgr,
spec, opts, clisock);
if (!head)
@@ -334,7 +339,6 @@ proxy_new(opts_t *opts, int clisock)
evsignal_add(ctx->sev[i], NULL);
}
- struct timeval gc_delay = {60, 0};
ctx->gcev = event_new(ctx->evbase, -1, EV_PERSIST, proxy_gc_cb, ctx);
if (!ctx->gcev)
goto leave4;
diff --git a/proxy.h b/src/proxy.h
index 98f348f..db6deda 100644
--- a/proxy.h
+++ b/src/proxy.h
@@ -34,7 +34,7 @@
typedef struct proxy_ctx proxy_ctx_t;
-proxy_ctx_t * proxy_new(opts_t *, int) NONNULL(1) MALLOC;
+proxy_ctx_t * proxy_new(struct tfe_config *, int) NONNULL(1) MALLOC;
void proxy_run(proxy_ctx_t *) NONNULL(1);
void proxy_loopbreak(proxy_ctx_t *) NONNULL(1);
void proxy_free(proxy_ctx_t *) NONNULL(1);
diff --git a/pxyconn.c b/src/pxyconn.cc
index c9540a2..f6b0d93 100644
--- a/pxyconn.c
+++ b/src/pxyconn.cc
@@ -38,7 +38,6 @@
#include "url.h"
#include "log.h"
#include "attrib.h"
-#include "proc.h"
#include <netinet/in.h>
#include <stdlib.h>
@@ -79,21 +78,6 @@
static unsigned long ssl_session_context = 0x31415926;
#endif /* USE_SSL_SESSION_ID_CONTEXT */
-
-/*
- * Proxy connection context state, describes a proxy connection
- * with source and destination socket bufferevents, SSL context and
- * other session state. One of these exists per handled proxy
- * connection.
- */
-
-/* single dst or src socket bufferevent descriptor */
-typedef struct pxy_conn_desc {
- struct bufferevent *bev;
- SSL *ssl;
- unsigned int closed : 1;
-} pxy_conn_desc_t;
-
#ifdef HAVE_LOCAL_PROCINFO
/* local process data - filled in iff pid != -1 */
typedef struct pxy_conn_lproc_desc {
@@ -111,91 +95,15 @@ typedef struct pxy_conn_lproc_desc {
} pxy_conn_lproc_desc_t;
#endif /* HAVE_LOCAL_PROCINFO */
-/* actual proxy connection state consisting of two connection descriptors,
- * connection-wide state and the specs and options */
-typedef struct pxy_conn_ctx {
- /* per-connection state */
- struct pxy_conn_desc src;
- struct pxy_conn_desc dst;
-
- /* status flags */
- unsigned int connected : 1; /* 0 until both ends are connected */
- unsigned int enomem : 1; /* 1 if out of memory */
- /* ssl */
- unsigned int sni_peek_retries : 6; /* max 64 SNI parse retries */
- unsigned int immutable_cert : 1; /* 1 if the cert cannot be changed */
- unsigned int generated_cert : 1; /* 1 if we generated a new cert */
- unsigned int passthrough : 1; /* 1 if SSL passthrough is active */
- /* http */
- unsigned int seen_req_header : 1; /* 0 until request header complete */
- unsigned int seen_resp_header : 1; /* 0 until response hdr complete */
- unsigned int sent_http_conn_close : 1; /* 0 until Conn: close sent */
- unsigned int ocsp_denied : 1; /* 1 if OCSP was denied */
- /* autossl */
- unsigned int clienthello_search : 1; /* 1 if waiting for hello */
- unsigned int clienthello_found : 1; /* 1 if conn upgrade to SSL */
-
- /* server name indicated by client in SNI TLS extension */
- char *sni;
-
- /* log strings from socket */
- char *srchost_str;
- char *srcport_str;
- char *dsthost_str;
- char *dstport_str;
-
- /* log strings from HTTP request */
- char *http_method;
- char *http_uri;
- char *http_host;
- char *http_content_type;
-
- /* log strings from HTTP response */
- char *http_status_code;
- char *http_status_text;
- char *http_content_length;
-
- /* log strings related to SSL */
- char *ssl_names;
- char *origcrtfpr;
- char *usedcrtfpr;
-
-#ifdef HAVE_LOCAL_PROCINFO
- /* local process information */
- pxy_conn_lproc_desc_t lproc;
-#endif /* HAVE_LOCAL_PROCINFO */
-
- /* content log context */
- log_content_ctx_t *logctx;
-
- /* store fd and fd event while connected is 0 */
- evutil_socket_t fd;
- struct event *ev;
-
- /* original destination address, family and certificate */
- struct sockaddr_storage addr;
- socklen_t addrlen;
- int af;
- X509 *origcrt;
-
- /* references to event base and configuration */
- struct event_base *evbase;
- struct evdns_base *dnsbase;
- int thridx;
- pxy_thrmgr_ctx_t *thrmgr;
- proxyspec_t *spec;
- opts_t *opts;
-} pxy_conn_ctx_t;
-
#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_t *spec, opts_t *opts,
+pxy_conn_ctx_new(proxyspec *spec, tfe_config *opts,
pxy_thrmgr_ctx_t *thrmgr, evutil_socket_t fd)
MALLOC NONNULL(1,2,3);
static pxy_conn_ctx_t *
-pxy_conn_ctx_new(proxyspec_t *spec, opts_t *opts,
+pxy_conn_ctx_new(proxyspec *spec, tfe_config *opts,
pxy_thrmgr_ctx_t *thrmgr, evutil_socket_t fd)
{
pxy_conn_ctx_t *ctx = malloc(sizeof(pxy_conn_ctx_t));
@@ -1155,7 +1063,7 @@ pxy_dstssl_create(pxy_conn_ctx_t *ctx)
#endif /* SSL_MODE_RELEASE_BUFFERS */
/* session resuming based on remote endpoint address and port */
- sess = cachemgr_dsess_get((struct sockaddr *)&ctx->addr,
+ sess = (SSL_SESSION *)cachemgr_dsess_get((struct sockaddr *)&ctx->addr,
ctx->addrlen, ctx->sni); /* new sess inst */
if (sess) {
if (OPTS_DEBUG(ctx->opts)) {
@@ -1625,12 +1533,13 @@ pxy_conn_terminate_free(pxy_conn_ctx_t *ctx, int is_requestor)
pxy_conn_ctx_free(ctx, is_requestor);
}
+extern int pxy_http_read_cb(pxy_conn_ctx_t *ctx, struct bufferevent *bev);
+
/*
* Callback for read events on the up- and downstream connection bufferevents.
* Called when there is data ready in the input evbuffer.
*/
-static void
-pxy_bev_readcb(struct bufferevent *bev, void *arg)
+static void pxy_bev_readcb(struct bufferevent *bev, void *arg)
{
pxy_conn_ctx_t *ctx = arg;
pxy_conn_desc_t *other = (bev==ctx->src.bev) ? &ctx->dst : &ctx->src;
@@ -1642,122 +1551,40 @@ pxy_bev_readcb(struct bufferevent *bev, void *arg)
}
#endif /* DEBUG_PROXY */
- if (!ctx->connected) {
+ if (!ctx->connected)
+ {
log_err_printf("readcb called when other end not connected - "
"aborting.\n");
log_exceptcb();
return;
}
- if (ctx->clienthello_search) {
- if (pxy_conn_autossl_peek_and_upgrade(ctx)) {
- return;
- }
+ if (ctx->clienthello_search && pxy_conn_autossl_peek_and_upgrade(ctx))
+ {
+ return;
}
struct evbuffer *inbuf = bufferevent_get_input(bev);
- if (other->closed) {
- log_dbg_printf("Warning: Drained %zu bytes (conn closed)\n",
- evbuffer_get_length(inbuf));
- evbuffer_drain(inbuf, evbuffer_get_length(inbuf));
- return;
- }
-
struct evbuffer *outbuf = bufferevent_get_output(other->bev);
- /* request header munging */
- if (ctx->spec->http && !ctx->seen_req_header && (bev == ctx->src.bev)
- && !ctx->passthrough) {
- logbuf_t *lb = NULL, *tail = NULL;
- char *line;
- while ((line = evbuffer_readln(inbuf, NULL,
- EVBUFFER_EOL_CRLF))) {
- char *replace;
- if (WANT_CONTENT_LOG(ctx)) {
- logbuf_t *tmp;
- tmp = logbuf_new_printf(NULL, NULL,
- "%s\r\n", line);
- if (tail) {
- if (tmp) {
- tail->next = tmp;
- tail = tail->next;
- }
- } else {
- lb = tail = tmp;
- }
- }
- replace = pxy_http_reqhdr_filter_line(line, ctx);
- if (replace == line) {
- evbuffer_add_printf(outbuf, "%s\r\n", line);
- } else if (replace) {
- evbuffer_add_printf(outbuf, "%s\r\n", replace);
- free(replace);
- }
- free(line);
- if (ctx->seen_req_header) {
- /* request header complete */
- if (ctx->opts->deny_ocsp) {
- pxy_ocsp_deny(ctx);
- }
- break;
- }
- }
- if (lb && WANT_CONTENT_LOG(ctx)) {
- if (log_content_submit(ctx->logctx, lb,
- 1/*req*/) == -1) {
- logbuf_free(lb);
- log_err_printf("Warning: Content log "
- "submission failed\n");
- }
- }
+ if (other->closed)
+ {
+ log_dbg_printf("Warning: Drained %zu bytes (conn closed)\n", evbuffer_get_length(inbuf));
+ evbuffer_drain(inbuf, evbuffer_get_length(inbuf));
+ return;
+ }
+
+ if (ctx->spec->http && !ctx->seen_req_header
+ && (bev == ctx->src.bev) && !ctx->passthrough)
+ {
+ pxy_http_read_cb(ctx, bev);
if (!ctx->seen_req_header)
return;
- } else
- /* response header munging */
- if (ctx->spec->http && !ctx->seen_resp_header && (bev == ctx->dst.bev)
- && !ctx->passthrough) {
- logbuf_t *lb = NULL, *tail = NULL;
- char *line;
- while ((line = evbuffer_readln(inbuf, NULL,
- EVBUFFER_EOL_CRLF))) {
- char *replace;
- if (WANT_CONTENT_LOG(ctx)) {
- logbuf_t *tmp;
- tmp = logbuf_new_printf(NULL, NULL,
- "%s\r\n", line);
- if (tail) {
- if (tmp) {
- tail->next = tmp;
- tail = tail->next;
- }
- } else {
- lb = tail = tmp;
- }
- }
- replace = pxy_http_resphdr_filter_line(line, ctx);
- if (replace == line) {
- evbuffer_add_printf(outbuf, "%s\r\n", line);
- } else if (replace) {
- evbuffer_add_printf(outbuf, "%s\r\n", replace);
- free(replace);
- }
- free(line);
- if (ctx->seen_resp_header) {
- /* response header complete: log connection */
- if (WANT_CONNECT_LOG(ctx)) {
- pxy_log_connect_http(ctx);
- }
- break;
- }
- }
- if (lb && WANT_CONTENT_LOG(ctx)) {
- if (log_content_submit(ctx->logctx, lb,
- 0/*resp*/) == -1) {
- logbuf_free(lb);
- log_err_printf("Warning: Content log "
- "submission failed\n");
- }
- }
+ }
+ else if (ctx->spec->http && !ctx->seen_resp_header
+ && (bev == ctx->dst.bev) && !ctx->passthrough)
+ {
+ pxy_http_read_cb(ctx, bev);
if (!ctx->seen_resp_header)
return;
}
@@ -1839,7 +1666,7 @@ static void
pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg)
{
pxy_conn_ctx_t *ctx = arg;
- pxy_conn_desc_t *this = (bev==ctx->src.bev) ? &ctx->src : &ctx->dst;
+ pxy_conn_desc_t *__this = (bev==ctx->src.bev) ? &ctx->src : &ctx->dst;
pxy_conn_desc_t *other = (bev==ctx->src.bev) ? &ctx->dst : &ctx->src;
int is_requestor = (bev == ctx->src.bev);
@@ -1871,7 +1698,7 @@ pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg)
/* wrap client-side socket in an eventbuffer */
if ((ctx->spec->ssl || ctx->clienthello_found) &&
!ctx->passthrough) {
- ctx->src.ssl = pxy_srcssl_create(ctx, this->ssl);
+ ctx->src.ssl = pxy_srcssl_create(ctx, __this->ssl);
if (!ctx->src.ssl) {
bufferevent_free_and_close_fd(bev, ctx);
ctx->dst.bev = NULL;
@@ -1980,13 +1807,13 @@ pxy_bev_eventcb(struct bufferevent *bev, short events, void *arg)
connected:
/* log connection if we don't analyze any headers */
- if ((!this->ssl || (bev == ctx->src.bev)) &&
+ if ((!__this->ssl || (bev == ctx->src.bev)) &&
(!ctx->spec->http || ctx->passthrough) &&
WANT_CONNECT_LOG(ctx)) {
pxy_log_connect_nonhttp(ctx);
}
- if (this->ssl) {
+ if (__this->ssl) {
/* write SSL certificates to gendir */
if ((bev == ctx->src.bev) && ctx->opts->certgendir) {
pxy_srccert_write(ctx);
@@ -1995,7 +1822,7 @@ connected:
/* log master key */
if (ctx->opts->masterkeylog) {
char *keystr;
- keystr = ssl_ssl_masterkey_to_str(this->ssl);
+ keystr = ssl_ssl_masterkey_to_str(__this->ssl);
if ((keystr == NULL) ||
(log_masterkey_print_free(keystr) == -1)) {
if (errno == ENOMEM)
@@ -2007,7 +1834,7 @@ connected:
}
if (OPTS_DEBUG(ctx->opts)) {
- if (this->ssl) {
+ if (__this->ssl) {
char *keystr;
/* for SSL, we get two connect events */
log_dbg_printf("SSL connected %s [%s]:%s"
@@ -2020,9 +1847,10 @@ connected:
bev == ctx->dst.bev ?
ctx->dstport_str :
ctx->srcport_str,
- SSL_get_version(this->ssl),
- SSL_get_cipher(this->ssl));
- keystr = ssl_ssl_masterkey_to_str(this->ssl);
+ SSL_get_version(__this->ssl),
+ SSL_get_cipher(__this->ssl), __this);
+
+ keystr = ssl_ssl_masterkey_to_str(__this->ssl);
if (keystr) {
log_dbg_print_free(keystr);
}
@@ -2209,16 +2037,16 @@ leave:
/* we only get a single disconnect event here for both connections */
if (OPTS_DEBUG(ctx->opts)) {
log_dbg_printf("%s disconnected to [%s]:%s\n",
- this->ssl ? "SSL" : "TCP",
+ __this->ssl ? "SSL" : "TCP",
ctx->dsthost_str, ctx->dstport_str);
log_dbg_printf("%s disconnected from [%s]:%s\n",
- this->ssl ? "SSL" : "TCP",
+ __this->ssl ? "SSL" : "TCP",
ctx->srchost_str, ctx->srcport_str);
}
- this->closed = 1;
+ __this->closed = 1;
bufferevent_free_and_close_fd(bev, ctx);
- this->bev = NULL;
+ __this->bev = NULL;
if (other->closed) {
pxy_conn_ctx_free(ctx, is_requestor);
}
@@ -2421,7 +2249,7 @@ void
pxy_conn_setup(evutil_socket_t fd,
struct sockaddr *peeraddr, int peeraddrlen,
pxy_thrmgr_ctx_t *thrmgr,
- proxyspec_t *spec, opts_t *opts)
+ proxyspec *spec, tfe_config *opts)
{
pxy_conn_ctx_t *ctx;
diff --git a/src/pxyconn.h b/src/pxyconn.h
new file mode 100644
index 0000000..13c0583
--- /dev/null
+++ b/src/pxyconn.h
@@ -0,0 +1,145 @@
+/*-
+ * SSLsplit - transparent SSL/TLS interception
+ * https://www.roe.ch/SSLsplit
+ *
+ * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PXYCONN_H
+#define PXYCONN_H
+
+#include "log.h"
+#include "opts.h"
+#include "attrib.h"
+#include "pxythrmgr.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <event2/event.h>
+#include <event2/util.h>
+
+/*
+ * Proxy connection context state, describes a proxy connection
+ * with source and destination socket bufferevents, SSL context and
+ * other session state. One of these exists per handled proxy
+ * connection.
+ */
+
+/* single dst or src socket bufferevent descriptor */
+typedef struct pxy_conn_desc {
+ struct bufferevent *bev;
+ SSL *ssl;
+ unsigned int closed : 1;
+} pxy_conn_desc_t;
+
+/* actual proxy connection state consisting of two connection descriptors,
+ * connection-wide state and the specs and options */
+
+typedef struct pxy_conn_ctx {
+ /* per-connection state */
+ struct pxy_conn_desc src;
+ struct pxy_conn_desc dst;
+
+ /* status flags */
+ unsigned int connected : 1; /* 0 until both ends are connected */
+ unsigned int enomem : 1; /* 1 if out of memory */
+ /* ssl */
+ unsigned int sni_peek_retries : 6; /* max 64 SNI parse retries */
+ unsigned int immutable_cert : 1; /* 1 if the cert cannot be changed */
+ unsigned int generated_cert : 1; /* 1 if we generated a new cert */
+ unsigned int passthrough : 1; /* 1 if SSL passthrough is active */
+ /* http */
+ unsigned int seen_req_header : 1; /* 0 until request header complete */
+ unsigned int seen_resp_header : 1; /* 0 until response hdr complete */
+ unsigned int sent_http_conn_close : 1; /* 0 until Conn: close sent */
+ unsigned int ocsp_denied : 1; /* 1 if OCSP was denied */
+ /* autossl */
+ unsigned int clienthello_search : 1; /* 1 if waiting for hello */
+ unsigned int clienthello_found : 1; /* 1 if conn upgrade to SSL */
+
+ /* http request parser ctx */
+ void * http_request_parser_ctx;
+ /* http response parser ctx */
+ void * http_response_parser_ctx;
+
+ /* server name indicated by client in SNI TLS extension */
+ char *sni;
+
+ /* log strings from socket */
+ char *srchost_str;
+ char *srcport_str;
+ char *dsthost_str;
+ char *dstport_str;
+
+ /* log strings from HTTP request */
+ char *http_method;
+ char *http_uri;
+ char *http_host;
+ char *http_content_type;
+
+ /* log strings from HTTP response */
+ char *http_status_code;
+ char *http_status_text;
+ char *http_content_length;
+
+ /* log strings related to SSL */
+ char *ssl_names;
+ char *origcrtfpr;
+ char *usedcrtfpr;
+
+#ifdef HAVE_LOCAL_PROCINFO
+ /* local process information */
+ pxy_conn_lproc_desc_t lproc;
+#endif /* HAVE_LOCAL_PROCINFO */
+
+ /* content log context */
+ log_content_ctx_t *logctx;
+
+ /* store fd and fd event while connected is 0 */
+ evutil_socket_t fd;
+ struct event *ev;
+
+ /* original destination address, family and certificate */
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int af;
+ X509 *origcrt;
+
+ /* references to event base and configuration */
+ struct event_base *evbase;
+ struct evdns_base *dnsbase;
+ int thridx;
+ pxy_thrmgr_ctx_t *thrmgr;
+ proxyspec *spec;
+ tfe_config *opts;
+} pxy_conn_ctx_t;
+
+void pxy_conn_setup(evutil_socket_t, struct sockaddr *, int,
+ pxy_thrmgr_ctx_t *, proxyspec *, tfe_config *)
+ NONNULL(2,4,5,6);
+
+#endif /* !PXYCONN_H */
+
+/* vim: set noet ft=c: */
diff --git a/src/pxyhttp.cc b/src/pxyhttp.cc
new file mode 100644
index 0000000..1424fb4
--- /dev/null
+++ b/src/pxyhttp.cc
@@ -0,0 +1,182 @@
+/* HTTP/HTTP2 Protocol Handler
+ *
+ * Author: Lu Qiuwen<[email protected]>
+ * Date: 2018-04-08
+ *
+ */
+
+#include <assert.h>
+#include <http_parser.h>
+#include <event2/bufferevent.h>
+#include <evdns.h>
+
+#include "pxyhttp.h"
+#include "pxyconn.h"
+
+static int __http_request_cb_on_url(http_parser *parser, const char *at, size_t length)
+{
+ pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
+
+ /* 复制URI,注意补齐String的\0结尾 */
+ ctx->http_uri = (char *) malloc(length + 1);
+ strncpy(ctx->http_uri, at, length);
+ ctx->http_uri[length] = '\0';
+
+ return 0;
+}
+
+static int __http_request_cb_on_header_field(http_parser *parser, const char *at, size_t length)
+{
+ pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
+ assert(ctx != NULL && at != NULL);
+
+ /* 处理Host字段,置Host为0xffffffff,在value回调函数中处理的value即为host字段 */
+ if (strncasecmp(at, "Host", length) == 0)
+ {
+ ctx->http_host = (char *) 0xffffffff;
+ goto __leave;
+ }
+
+__leave:
+ return 0;
+}
+
+static int __http_request_cb_on_header_value(http_parser *parser, const char *at, size_t length)
+{
+ pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
+ assert(ctx != NULL && at != NULL);
+
+ /* 处理Host字段的值 */
+ if (ctx->http_host == (void *) 0xffffffff)
+ {
+ ctx->http_host = (char *) malloc(length + 1);
+ strncpy(ctx->http_host, at, length);
+ ctx->http_host[length] = '\0';
+ }
+
+ return 0;
+}
+
+static int __http_request_cb_on_headers_complete(http_parser *parser)
+{
+ pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
+ ctx->seen_req_header = 1;
+ return 0;
+}
+
+static int __http_resp_cb_on_status(http_parser *parser, const char *at, size_t length)
+{
+ return 0;
+}
+
+static int __http_resp_cb_on_headers_complete(http_parser *parser)
+{
+ pxy_conn_ctx_t *ctx = (pxy_conn_ctx_t *) parser->data;
+
+ /* HTTP状态码 */
+ asprintf(&ctx->http_status_code, "%d", parser->status_code);
+ ctx->seen_resp_header = 1;
+ return 0;
+}
+
+/* HTTP Request Handlers */
+const static struct http_parser_settings __setting_http_parser_request =
+{
+ nullptr, /* on_message_begin */
+ __http_request_cb_on_url, /* on_url */
+ nullptr, /* on_status */
+ __http_request_cb_on_header_field, /* on_header_field */
+ __http_request_cb_on_header_value, /* on_header_value */
+ __http_request_cb_on_headers_complete, /* on_headers_complete */
+ nullptr, /* on_body */
+ nullptr /* on_message_complete */
+};
+
+/* HTTP Response Handlers */
+const static struct http_parser_settings __setting_http_parser_resp =
+{
+ nullptr, /* on_message_begin */
+ nullptr, /* on_url */
+ __http_resp_cb_on_status, /* on_status */
+ nullptr, /* on_header_field */
+ nullptr, /* on_header_value */
+ __http_resp_cb_on_headers_complete, /* on_headers_complete */
+ nullptr, /* on_body */
+ nullptr /* on_message_complete */
+};
+
+int pxy_http_read_cb(pxy_conn_ctx_t *ctx, struct bufferevent *bev)
+{
+ pxy_conn_desc_t *other = (bev == ctx->src.bev) ? &ctx->dst : &ctx->src;
+ int is_http_request = (bev == ctx->src.bev);
+
+ /* HTTP Parser Handler */
+ http_parser *http_parser_ctx = is_http_request ?
+ (http_parser *)ctx->http_request_parser_ctx :
+ (http_parser *)ctx->http_response_parser_ctx;
+
+ void **http_parser_ctx_ref = is_http_request ?
+ &ctx->http_request_parser_ctx :
+ &ctx->http_response_parser_ctx;
+
+ /* HTTP Passer Type */
+ enum http_parser_type http_parser_work_mode = is_http_request ?
+ HTTP_REQUEST :
+ HTTP_RESPONSE;
+
+ const struct http_parser_settings *http_parser_cb = is_http_request ?
+ &__setting_http_parser_request :
+ &__setting_http_parser_resp;
+
+ /* 第一次请求,解析器句柄为空,创建新的解析器上下文 */
+ if (http_parser_ctx == NULL)
+ {
+ http_parser_ctx = (http_parser *)malloc(sizeof(http_parser));
+ *http_parser_ctx_ref = http_parser_ctx;
+
+ http_parser_ctx->data = ctx;
+ http_parser_init(http_parser_ctx, http_parser_work_mode);
+ }
+
+ /* 已经处理了HTTP Header,转发其他数据 */
+ if (is_http_request && ctx->seen_req_header)
+ return 0;
+ if (!is_http_request && ctx->seen_resp_header)
+ return 0;
+
+ struct evbuffer *input_buffer = bufferevent_get_input(bev);
+ size_t input_buffer_len = evbuffer_get_length(input_buffer);
+
+ if (input_buffer_len == 0)
+ return 0;
+
+ /* 连续的副本,供http_parser扫描使用 */
+ char *__buffer_copy = (char *)malloc(input_buffer_len);
+ assert(__buffer_copy != NULL);
+
+ /* 从buffer中拷贝出来一个副本 */
+ ssize_t __buffer_len = evbuffer_copyout(input_buffer, __buffer_copy, input_buffer_len);
+ if (__buffer_len < 0) goto __error;
+
+ /* 送入HTTP解析器处理 */
+ if (http_parser_execute(http_parser_ctx, http_parser_cb, __buffer_copy, __buffer_len)
+ != __buffer_len)
+ {
+ goto __error;
+ }
+
+ /* 判断此时HTTP头部是否完整,若完整,即可调用业务层处理,
+ * 每个HTTP事务仅在此调用一次业务层处理逻辑,调用结束后即可进入转发流程 */
+ if(is_http_request && ctx->seen_req_header)
+ {
+ //TODO: Call Biz
+ }
+ if(!is_http_request && ctx->seen_resp_header)
+ {
+ //TODO: Call Biz
+ }
+
+__error:
+ free(__buffer_copy);
+ return -1;
+} \ No newline at end of file
diff --git a/src/pxyhttp.h b/src/pxyhttp.h
new file mode 100644
index 0000000..2ad3c13
--- /dev/null
+++ b/src/pxyhttp.h
@@ -0,0 +1,4 @@
+#ifndef TFE_PXYHTTP_H
+#define TFE_PXYHTTP_H
+
+#endif //TFE_PXYHTTP_H
diff --git a/pxysslshut.c b/src/pxysslshut.cc
index 8db900f..c48767f 100644
--- a/pxysslshut.c
+++ b/src/pxysslshut.cc
@@ -51,7 +51,7 @@
*/
typedef struct pxy_ssl_shutdown_ctx {
- opts_t *opts;
+ tfe_config *opts;
struct event_base *evbase;
struct event *ev;
SSL *ssl;
@@ -59,7 +59,7 @@ typedef struct pxy_ssl_shutdown_ctx {
} pxy_ssl_shutdown_ctx_t;
static pxy_ssl_shutdown_ctx_t *
-pxy_ssl_shutdown_ctx_new(opts_t *opts, struct event_base *evbase, SSL *ssl)
+pxy_ssl_shutdown_ctx_new(tfe_config *opts, struct event_base *evbase, SSL *ssl)
{
pxy_ssl_shutdown_ctx_t *ctx;
@@ -165,7 +165,7 @@ complete:
* socket is closed, eventually, or in the case of fatal errors, immediately.
*/
void
-pxy_ssl_shutdown(opts_t *opts, struct event_base *evbase, SSL *ssl,
+pxy_ssl_shutdown(tfe_config *opts, struct event_base *evbase, SSL *ssl,
evutil_socket_t fd)
{
pxy_ssl_shutdown_ctx_t *sslshutctx;
diff --git a/pxysslshut.h b/src/pxysslshut.h
index a76d60c..9e3975b 100644
--- a/pxysslshut.h
+++ b/src/pxysslshut.h
@@ -36,7 +36,7 @@
#include <event2/event.h>
#include <event2/util.h>
-void pxy_ssl_shutdown(opts_t *, struct event_base *, SSL *, evutil_socket_t)
+void pxy_ssl_shutdown(tfe_config *, struct event_base *, SSL *, evutil_socket_t)
NONNULL(1,2,3);
#endif /* !PXYSSLSHUT_H */
diff --git a/pxythrmgr.c b/src/pxythrmgr.cc
index 5f867c7..a670732 100644
--- a/pxythrmgr.c
+++ b/src/pxythrmgr.cc
@@ -53,7 +53,7 @@ typedef struct pxy_thr_ctx {
struct pxy_thrmgr_ctx {
int num_thr;
- opts_t *opts;
+ tfe_config *opts;
pxy_thr_ctx_t **thr;
pthread_mutex_t mutex;
};
@@ -96,7 +96,7 @@ pxy_thrmgr_thr(void *arg)
* This gets called before forking to background.
*/
pxy_thrmgr_ctx_t *
-pxy_thrmgr_new(opts_t *opts)
+pxy_thrmgr_new(tfe_config *opts)
{
pxy_thrmgr_ctx_t *ctx;
@@ -120,7 +120,7 @@ pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx)
{
int idx = -1, dns = 0;
- dns = opts_has_dns_spec(ctx->opts);
+ dns = tfe_config_has_dns_spec(ctx->opts);
if (pthread_mutex_init(&ctx->mutex, NULL)) {
log_dbg_printf("Failed to initialize mutex\n");
diff --git a/pxythrmgr.h b/src/pxythrmgr.h
index 8cd2f7c..88f142d 100644
--- a/pxythrmgr.h
+++ b/src/pxythrmgr.h
@@ -40,7 +40,7 @@
typedef struct pxy_thrmgr_ctx pxy_thrmgr_ctx_t;
-pxy_thrmgr_ctx_t * pxy_thrmgr_new(opts_t *) MALLOC;
+pxy_thrmgr_ctx_t * pxy_thrmgr_new(tfe_config *) MALLOC;
int pxy_thrmgr_run(pxy_thrmgr_ctx_t *) NONNULL(1) WUNRES;
void pxy_thrmgr_free(pxy_thrmgr_ctx_t *) NONNULL(1);
diff --git a/ssl.c b/src/ssl.cc
index 1f5e306..4ef9ee7 100644
--- a/ssl.c
+++ b/src/ssl.cc
@@ -1958,6 +1958,15 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
ssize_t n = sz;
char *sn = NULL;
+ ssize_t tlsextslen;
+ ssize_t sidlen;
+ ssize_t suiteslen;
+ ssize_t compslen;
+ ssize_t msglen;
+ ssize_t recordlen;
+
+ //=====
+
*clienthello = NULL;
DBG_printf("parsing buffer of sz %zd\n", sz);
@@ -2084,7 +2093,8 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
return 1;
}
DBG_printf("length: %02x %02x\n", p[0], p[1]);
- ssize_t recordlen = p[1] + (p[0] << 8);
+
+ recordlen = p[1] + (p[0] << 8);
DBG_printf("recordlen=%zd\n", recordlen);
p += 2; n -= 2;
if (recordlen < 36) /* arbitrary size too small for a c-h */
@@ -2109,7 +2119,7 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
if (n < 3)
continue;
DBG_printf("message len: %02x %02x %02x\n", p[0], p[1], p[2]);
- ssize_t msglen = p[2] + (p[1] << 8) + (p[0] << 16);
+ msglen = p[2] + (p[1] << 8) + (p[0] << 16);
DBG_printf("msglen=%zd\n", msglen);
p += 3; n -= 3;
if (msglen < 32) /* arbitrary size too small for a c-h */
@@ -2141,7 +2151,7 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
if (n < 1)
continue;
DBG_printf("clienthello sidlen %02x\n", *p);
- ssize_t sidlen = *p; /* session id length, 0..32 */
+ sidlen = *p; /* session id length, 0..32 */
p += 1; n -= 1;
if (n < sidlen)
continue;
@@ -2151,7 +2161,8 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
continue;
DBG_printf("clienthello cipher suites length %02x %02x\n",
p[0], p[1]);
- ssize_t suiteslen = p[1] + (p[0] << 8);
+
+ suiteslen = p[1] + (p[0] << 8);
p += 2; n -= 2;
if (n < suiteslen)
continue;
@@ -2161,7 +2172,8 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
if (n < 1)
continue;
DBG_printf("clienthello compress methods length %02x\n", *p);
- ssize_t compslen = *p;
+
+ compslen = *p;
p++; n--;
if (n < compslen)
continue;
@@ -2180,7 +2192,7 @@ ssl_tls_clienthello_parse(const unsigned char *buf, ssize_t sz, int search,
if (n < 2)
continue;
DBG_printf("tlsexts length %02x %02x\n", p[0], p[1]);
- ssize_t tlsextslen = p[1] + (p[0] << 8);
+ tlsextslen = p[1] + (p[0] << 8);
DBG_printf("tlsextslen %zd\n", tlsextslen);
p += 2; n -= 2;
if (n < tlsextslen)
diff --git a/ssl.h b/src/ssl.h
index a3290a5..a3290a5 100644
--- a/ssl.h
+++ b/src/ssl.h
diff --git a/sys.c b/src/sys.cc
index 2db0a93..dee9549 100644
--- a/sys.c
+++ b/src/sys.cc
@@ -357,9 +357,8 @@ sys_group_str(gid_t gid)
* On success, returns address family and fills in addr, addrlen.
* Returns -1 on error.
*/
-int
-sys_sockaddr_parse(struct sockaddr_storage *addr, socklen_t *addrlen,
- char *naddr, char *nport, int af, int flags)
+int sys_sockaddr_parse(struct sockaddr_storage *addr, socklen_t *addrlen,
+ const char *naddr, const char *nport, int af, int flags)
{
struct evutil_addrinfo hints;
struct evutil_addrinfo *ai;
diff --git a/sys.h b/src/sys.h
index 6c1382a..65ab559 100644
--- a/sys.h
+++ b/src/sys.h
@@ -46,8 +46,9 @@ int sys_isgroup(const char *) NONNULL(1) WUNRES;
char * sys_user_str(uid_t) MALLOC;
char * sys_group_str(gid_t) MALLOC;
-int sys_sockaddr_parse(struct sockaddr_storage *, socklen_t *,
- char *, char *, int, int) NONNULL(1,2,3,4) WUNRES;
+int sys_sockaddr_parse(
+ struct sockaddr_storage *, socklen_t *,
+ const char *, const char *, int, int) NONNULL(1, 2, 3, 4) WUNRES;
int sys_sockaddr_str(struct sockaddr *, socklen_t,
char **, char **) NONNULL(1,3,4);
char * sys_ip46str_sanitize(const char *) NONNULL(1) MALLOC;
diff --git a/thrqueue.c b/src/thrqueue.cc
index 1807bd7..1807bd7 100644
--- a/thrqueue.c
+++ b/src/thrqueue.cc
diff --git a/thrqueue.h b/src/thrqueue.h
index 4bc6e8c..4bc6e8c 100644
--- a/thrqueue.h
+++ b/src/thrqueue.h
diff --git a/url.c b/src/url.cc
index e2ab2b5..e2ab2b5 100644
--- a/url.c
+++ b/src/url.cc
diff --git a/url.h b/src/url.h
index 4c447ce..4c447ce 100644
--- a/url.h
+++ b/src/url.h
diff --git a/util.c b/src/util.cc
index d16036c..d16036c 100644
--- a/util.c
+++ b/src/util.cc
diff --git a/util.h b/src/util.h
index 91be6b2..91be6b2 100644
--- a/util.h
+++ b/src/util.h
diff --git a/base64.t.c b/test/base64.t.c
index f95f020..f95f020 100644
--- a/base64.t.c
+++ b/test/base64.t.c
diff --git a/cachedsess.t.c b/test/cachedsess.t.c
index af031f2..af031f2 100644
--- a/cachedsess.t.c
+++ b/test/cachedsess.t.c
diff --git a/cachefkcrt.t.c b/test/cachefkcrt.t.c
index 2930f59..2930f59 100644
--- a/cachefkcrt.t.c
+++ b/test/cachefkcrt.t.c
diff --git a/cachemgr.t.c b/test/cachemgr.t.c
index 1229c88..1229c88 100644
--- a/cachemgr.t.c
+++ b/test/cachemgr.t.c
diff --git a/cachessess.t.c b/test/cachessess.t.c
index a50b467..a50b467 100644
--- a/cachessess.t.c
+++ b/test/cachessess.t.c
diff --git a/cachetgcrt.t.c b/test/cachetgcrt.t.c
index f4c4ad6..f4c4ad6 100644
--- a/cachetgcrt.t.c
+++ b/test/cachetgcrt.t.c
diff --git a/cert.t.c b/test/cert.t.c
index d21a6bd..d21a6bd 100644
--- a/cert.t.c
+++ b/test/cert.t.c
diff --git a/dynbuf.t.c b/test/dynbuf.t.c
index db275c5..db275c5 100644
--- a/dynbuf.t.c
+++ b/test/dynbuf.t.c
diff --git a/main.t.c b/test/main.t.c
index 48d6700..48d6700 100644
--- a/main.t.c
+++ b/test/main.t.c
diff --git a/opts.t.c b/test/opts.t.c
index c85294b..a9af9df 100644
--- a/opts.t.c
+++ b/test/opts.t.c
@@ -86,7 +86,7 @@ static char *argv14[] = {
START_TEST(proxyspec_parse_01)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv01;
@@ -110,7 +110,7 @@ END_TEST
START_TEST(proxyspec_parse_02)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv02;
@@ -134,7 +134,7 @@ END_TEST
START_TEST(proxyspec_parse_03)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 2;
char **argv = argv01;
@@ -147,7 +147,7 @@ END_TEST
START_TEST(proxyspec_parse_04)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 4;
char **argv = argv01;
@@ -160,7 +160,7 @@ END_TEST
START_TEST(proxyspec_parse_05)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv03;
@@ -184,7 +184,7 @@ END_TEST
START_TEST(proxyspec_parse_06)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv04;
@@ -208,7 +208,7 @@ END_TEST
START_TEST(proxyspec_parse_07)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv05;
@@ -232,7 +232,7 @@ END_TEST
START_TEST(proxyspec_parse_08)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv06;
@@ -255,7 +255,7 @@ END_TEST
START_TEST(proxyspec_parse_09)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv07;
@@ -268,7 +268,7 @@ END_TEST
START_TEST(proxyspec_parse_10)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 4;
char **argv = argv06;
@@ -281,7 +281,7 @@ END_TEST
START_TEST(proxyspec_parse_11)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 3;
char **argv = argv08;
@@ -305,7 +305,7 @@ END_TEST
START_TEST(proxyspec_parse_12)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 4;
char **argv = argv08;
@@ -318,7 +318,7 @@ END_TEST
START_TEST(proxyspec_parse_13)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 10;
char **argv = argv09;
@@ -353,7 +353,7 @@ END_TEST
START_TEST(proxyspec_parse_14)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 6;
char **argv = argv10;
@@ -389,7 +389,7 @@ END_TEST
START_TEST(proxyspec_parse_15)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 3;
char **argv = argv11;
@@ -412,7 +412,7 @@ END_TEST
START_TEST(proxyspec_parse_16)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 10;
char **argv = argv12;
@@ -447,7 +447,7 @@ END_TEST
START_TEST(proxyspec_parse_17)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 5;
char **argv = argv13;
@@ -460,7 +460,7 @@ END_TEST
START_TEST(proxyspec_parse_18)
{
- proxyspec_t *spec;
+ proxyspec *spec;
int argc = 8;
char **argv = argv14;
diff --git a/pxythrmgr.t.c b/test/pxythrmgr.t.c
index 529b8b8..529b8b8 100644
--- a/pxythrmgr.t.c
+++ b/test/pxythrmgr.t.c
diff --git a/ssl.t.c b/test/ssl.t.c
index 52bef29..52bef29 100644
--- a/ssl.t.c
+++ b/test/ssl.t.c
diff --git a/sys.t.c b/test/sys.t.c
index cdb7883..cdb7883 100644
--- a/sys.t.c
+++ b/test/sys.t.c
diff --git a/url.t.c b/test/url.t.c
index 74f897b..74f897b 100644
--- a/url.t.c
+++ b/test/url.t.c
diff --git a/util.t.c b/test/util.t.c
index 2e63634..2e63634 100644
--- a/util.t.c
+++ b/test/util.t.c
diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt
new file mode 100644
index 0000000..8042f02
--- /dev/null
+++ b/vendor/CMakeLists.txt
@@ -0,0 +1,103 @@
+# CMakeFiles for 3rd vendor library
+
+include(ExternalProject)
+
+### Libevent 2.1.8
+ExternalProject_Add(libevent
+ PREFIX libevent
+ URL ${CMAKE_CURRENT_SOURCE_DIR}/libevent-2.1.8-stable.tar.gz
+ URL_MD5 f3eeaed018542963b7d2416ef1135ecc
+ CONFIGURE_COMMAND ./configure --prefix=<INSTALL_DIR> --disable-shared
+ BUILD_IN_SOURCE 1)
+
+ExternalProject_Get_Property(libevent INSTALL_DIR)
+set(LIBEVENT_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+file(MAKE_DIRECTORY ${LIBEVENT_INCLUDE_DIRECTORIES})
+
+add_library(libevent-static STATIC IMPORTED GLOBAL)
+set_property(TARGET libevent-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libevent.a)
+set_property(TARGET libevent-static PROPERTY IMPORTED_INTERFACE_LINK_LIBRARIES pthread crypto)
+set_property(TARGET libevent-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+
+add_library(libevent-static-openssl STATIC IMPORTED GLOBAL)
+set_property(TARGET libevent-static-openssl PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libevent_openssl.a)
+set_property(TARGET libevent-static-openssl PROPERTY IMPORTED_INTERFACE_LINK_LIBRARIES pthread crypto)
+set_property(TARGET libevent-static-openssl PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+
+add_library(libevent-static-pthreads STATIC IMPORTED GLOBAL)
+set_property(TARGET libevent-static-pthreads PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libevent_pthreads.a)
+set_property(TARGET libevent-static-pthreads PROPERTY IMPORTED_INTERFACE_LINK_LIBRARIES pthread crypto)
+set_property(TARGET libevent-static-pthreads PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+
+### http parser
+ExternalProject_Add(http-parser
+ PREFIX http-parser
+ URL ${CMAKE_CURRENT_SOURCE_DIR}/http-parser-2.8.1.tar.gz
+ URL_MD5 cb8cbe17d68c4101eebe80229e32efdb
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND make package
+ INSTALL_COMMAND ""
+ BUILD_IN_SOURCE 1)
+
+ExternalProject_Get_Property(http-parser SOURCE_DIR)
+set(HTTP_PARSER_INCLUDE_DIRECTORIES ${SOURCE_DIR})
+file(MAKE_DIRECTORY ${HTTP_PARSER_INCLUDE_DIRECTORIES})
+
+add_library(http-parser-static STATIC IMPORTED GLOBAL)
+set_property(TARGET http-parser-static PROPERTY IMPORTED_LOCATION ${SOURCE_DIR}/libhttp_parser.a)
+set_property(TARGET http-parser-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SOURCE_DIR})
+
+### libcheck
+ExternalProject_Add(libcheck
+ PREFIX libcheck
+ URL ${CMAKE_CURRENT_SOURCE_DIR}/check-0.12.0.tar.gz
+ URL_MD5 31b17c6075820a434119592941186f70
+ CONFIGURE_COMMAND ./configure --prefix=<INSTALL_DIR> --disable-shared
+ BUILD_IN_SOURCE 1)
+
+ExternalProject_Get_Property(libcheck INSTALL_DIR)
+set(LIBCHECK_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+file(MAKE_DIRECTORY ${LIBCHECK_INCLUDE_DIRECTORIES})
+
+add_library(libcheck-static STATIC IMPORTED GLOBAL)
+set_property(TARGET libcheck-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libcheck.a)
+set_property(TARGET libcheck-static PROPERTY IMPORTED_INTERFACE_LINK_LIBRARIES pthread rt m)
+set_property(TARGET libcheck-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+
+### MESA Prof Load
+ExternalProject_Add(MESA_prof_load
+ PREFIX MESA_prof_load
+ URL ${CMAKE_CURRENT_SOURCE_DIR}/MESA_prof_load-3b2bfd.tar.gz
+ URL_MD5 411eedec773e6265bf9185846cab0f15
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND make
+ INSTALL_COMMAND ""
+ BUILD_IN_SOURCE 1)
+
+ExternalProject_Get_Property(MESA_prof_load SOURCE_DIR)
+set(MESA_PROF_LOAD_INCLUDE_DIRECTORIES ${SOURCE_DIR}/include)
+file(MAKE_DIRECTORY ${MESA_PROF_LOAD_INCLUDE_DIRECTORIES})
+
+add_library(MESA_prof_load-static STATIC IMPORTED GLOBAL)
+set_property(TARGET MESA_prof_load-static PROPERTY IMPORTED_LOCATION ${SOURCE_DIR}/lib/libMESA_prof_load.a)
+set_property(TARGET MESA_prof_load-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SOURCE_DIR}/inc)
+
+#### GoogleTest
+#ExternalProject_Add(googletest
+# PREFIX googletest
+# URL ${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.8.0.tar.gz
+# URL_MD5 16877098823401d1bf2ed7891d7dce36
+# CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
+#
+#ExternalProject_Get_Property(googletest INSTALL_DIR)
+#set(GTEST_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+#file(MAKE_DIRECTORY ${GTEST_INCLUDE_DIRECTORIES})
+#
+#add_library(gtest STATIC IMPORTED GLOBAL)
+#set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgtest.a)
+#set_property(TARGET gtest PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+#
+#add_library(gmock STATIC IMPORTED GLOBAL)
+#set_property(TARGET gmock PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgtest.a)
+#set_property(TARGET gmock PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
+
diff --git a/vendor/MESA_prof_load-3b2bfd.tar.gz b/vendor/MESA_prof_load-3b2bfd.tar.gz
new file mode 100644
index 0000000..8004fa3
--- /dev/null
+++ b/vendor/MESA_prof_load-3b2bfd.tar.gz
Binary files differ
diff --git a/vendor/check-0.12.0.tar.gz b/vendor/check-0.12.0.tar.gz
new file mode 100644
index 0000000..375dbce
--- /dev/null
+++ b/vendor/check-0.12.0.tar.gz
Binary files differ
diff --git a/vendor/googletest-release-1.8.0.tar.gz b/vendor/googletest-release-1.8.0.tar.gz
new file mode 100644
index 0000000..a40df33
--- /dev/null
+++ b/vendor/googletest-release-1.8.0.tar.gz
Binary files differ
diff --git a/vendor/http-parser-2.8.1.tar.gz b/vendor/http-parser-2.8.1.tar.gz
new file mode 100644
index 0000000..85d2b5a
--- /dev/null
+++ b/vendor/http-parser-2.8.1.tar.gz
Binary files differ
diff --git a/vendor/libevent-2.1.8-stable.tar.gz b/vendor/libevent-2.1.8-stable.tar.gz
new file mode 100644
index 0000000..2004f84
--- /dev/null
+++ b/vendor/libevent-2.1.8-stable.tar.gz
Binary files differ