From 4b50e0784f11f34b4424a91c04ffc2adff812616 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Feb 2019 17:53:08 -0500 Subject: [PATCH 1/3] eternal storage permission --- android/browser/src/main/AndroidManifest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/browser/src/main/AndroidManifest.xml b/android/browser/src/main/AndroidManifest.xml index 1869033a9..65149bfd9 100644 --- a/android/browser/src/main/AndroidManifest.xml +++ b/android/browser/src/main/AndroidManifest.xml @@ -26,4 +26,6 @@ + + From 2fde6a74c376b82263e31299c25f42a9ced6abf7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Feb 2019 21:32:15 -0500 Subject: [PATCH 2/3] pass -DANDROID to i2pd --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c12231944..868b4670d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Android") # CMAKE_ANDROID_STANDALONE_TOOLCHAIN (and likely other cross compilation # android variables) was only introduced in v3.7 cmake_minimum_required (VERSION 3.7) + add_definitions(-DANDROID) # for i2pd else() cmake_minimum_required (VERSION 3.5) endif() From a1a2cbf6d575e91ec7920a54aebc2410a1c15360 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Feb 2019 08:48:17 -0500 Subject: [PATCH 3/3] Revert "sync with upstream" --- CMakeLists.txt | 21 -- android/ouinet/build.gradle | 2 - android/ouinet/src/main/cpp/native-lib.cpp | 48 +-- .../main/java/ie/equalit/ouinet/Ouinet.java | 67 ++-- modules/asio-ipfs | 2 +- modules/obfs4proxy/CMakeLists.txt | 62 ---- scripts/build-android.sh | 38 +-- src/client.cpp | 68 +--- src/client_front_end.h | 1 + src/endpoint.cpp | 70 ++-- src/endpoint.h | 61 +++- src/injector.cpp | 42 --- src/injector_config.h | 27 -- .../pluggable-transports/client-process.cpp | 86 ----- .../pluggable-transports/client-process.h | 52 --- .../dispatcher-process.cpp | 303 ----------------- .../pluggable-transports/dispatcher-process.h | 59 ---- .../pluggable-transports/pt-ouiservice.cpp | 185 ----------- .../pluggable-transports/pt-ouiservice.h | 84 ----- .../pluggable-transports/server-process.cpp | 110 ------- .../pluggable-transports/server-process.h | 52 --- .../pluggable-transports/socks5-client.cpp | 305 ------------------ .../pluggable-transports/socks5-client.h | 32 -- src/ouiservice/pluggable-transports/util.h | 77 ----- src/ouiservice/pt-obfs2.cpp | 135 -------- src/ouiservice/pt-obfs2.h | 67 ---- src/ouiservice/pt-obfs3.cpp | 135 -------- src/ouiservice/pt-obfs3.h | 67 ---- src/ouiservice/pt-obfs4.cpp | 160 --------- src/ouiservice/pt-obfs4.h | 69 ---- src/ouiservice/tcp.cpp | 33 +- src/ouiservice/tcp.h | 7 +- test/CMakeLists.txt | 20 -- test/ouiservice-client.cpp | 74 ----- test/ouiservice-server.cpp | 70 ---- 35 files changed, 131 insertions(+), 2560 deletions(-) delete mode 100644 modules/obfs4proxy/CMakeLists.txt delete mode 100644 src/ouiservice/pluggable-transports/client-process.cpp delete mode 100644 src/ouiservice/pluggable-transports/client-process.h delete mode 100644 src/ouiservice/pluggable-transports/dispatcher-process.cpp delete mode 100644 src/ouiservice/pluggable-transports/dispatcher-process.h delete mode 100644 src/ouiservice/pluggable-transports/pt-ouiservice.cpp delete mode 100644 src/ouiservice/pluggable-transports/pt-ouiservice.h delete mode 100644 src/ouiservice/pluggable-transports/server-process.cpp delete mode 100644 src/ouiservice/pluggable-transports/server-process.h delete mode 100644 src/ouiservice/pluggable-transports/socks5-client.cpp delete mode 100644 src/ouiservice/pluggable-transports/socks5-client.h delete mode 100644 src/ouiservice/pluggable-transports/util.h delete mode 100644 src/ouiservice/pt-obfs2.cpp delete mode 100644 src/ouiservice/pt-obfs2.h delete mode 100644 src/ouiservice/pt-obfs3.cpp delete mode 100644 src/ouiservice/pt-obfs3.h delete mode 100644 src/ouiservice/pt-obfs4.cpp delete mode 100644 src/ouiservice/pt-obfs4.h delete mode 100644 test/ouiservice-client.cpp delete mode 100644 test/ouiservice-server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0aad4cae..868b4670d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,23 +40,10 @@ add_definitions(-DBOOST_COROUTINE_NO_DEPRECATION_WARNING) # https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio/using.html#boost_asio.using.optional_separate_compilation add_definitions(-DBOOST_ASIO_SEPARATE_COMPILATION) -################################################################################ - -set(GOROOT "${CMAKE_BINARY_DIR}/golang") -externalproject_add(golang - URL https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz - URL_MD5 5630231012b6d02b821af51f04c2776c - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - SOURCE_DIR ${GOROOT} -) - ################################################################################ option(ASIO_IPFS_WITH_EXAMPLE_BINARIES "" OFF) add_subdirectory(./modules/asio-ipfs) -add_subdirectory(./modules/obfs4proxy) add_subdirectory(./src/ouiservice/i2p) ################################################################################ @@ -163,12 +150,8 @@ file(GLOB client_sources "./src/ouiservice.cpp" "./src/ssl/ca_certificate.cpp" "./src/ssl/dummy_certificate.cpp" - "./src/ouiservice/pt-obfs2.cpp" - "./src/ouiservice/pt-obfs3.cpp" - "./src/ouiservice/pt-obfs4.cpp" "./src/ouiservice/tcp.cpp" "./src/ouiservice/tls.cpp" - "./src/ouiservice/pluggable-transports/*.cpp" "./src/logger.cpp" "./src/cache/*.cpp" "./src/bittorrent/*.cpp" @@ -215,12 +198,8 @@ if (WITH_INJECTOR) "./src/connect_to_host.cpp" "./src/cache_control.cpp" "./src/ouiservice.cpp" - "./src/ouiservice/pt-obfs2.cpp" - "./src/ouiservice/pt-obfs3.cpp" - "./src/ouiservice/pt-obfs4.cpp" "./src/ouiservice/tcp.cpp" "./src/ouiservice/tls.cpp" - "./src/ouiservice/pluggable-transports/*.cpp" "./src/ssl/ca_certificate.cpp" "./src/logger.cpp" "./src/cache/*.cpp" diff --git a/android/ouinet/build.gradle b/android/ouinet/build.gradle index 53cd54d0c..dc914a118 100644 --- a/android/ouinet/build.gradle +++ b/android/ouinet/build.gradle @@ -23,9 +23,7 @@ android { sourceSets { main { jniLibs.srcDirs = ["$libdir"] - assets.srcDirs = ["$assetsdir"] } - } buildTypes { release { diff --git a/android/ouinet/src/main/cpp/native-lib.cpp b/android/ouinet/src/main/cpp/native-lib.cpp index ac6867feb..587d20c86 100644 --- a/android/ouinet/src/main/cpp/native-lib.cpp +++ b/android/ouinet/src/main/cpp/native-lib.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include "debug.h" @@ -36,40 +35,13 @@ ouinet::asio::io_service g_ios; thread g_client_thread; bool g_crypto_initialized = false; -void start_client_thread(const vector& args, const vector& extra_path) +void start_client_thread(const vector& args) { if (g_crypto_initialized) { ouinet::util::crypto_init(); g_crypto_initialized = true; } - char* old_path_c = getenv("PATH"); - if (old_path_c) { - std::string old_path(old_path_c); - std::set old_path_entries; - size_t index = 0; - while (true) { - size_t pos = old_path.find(':', index); - if (pos == std::string::npos) { - old_path_entries.insert(old_path.substr(index)); - break; - } else { - old_path_entries.insert(old_path.substr(index, pos - index)); - index = pos; - } - } - - std::string new_path; - for (size_t i = 0; i < extra_path.size(); i++) { - if (!old_path_entries.count(extra_path[i])) { - new_path += extra_path[i]; - new_path += ":"; - } - } - new_path += old_path; - setenv("PATH", new_path.c_str(), 1); - } - if (g_client_thread.get_id() != thread::id()) return; g_client_thread = thread([=] { @@ -112,10 +84,10 @@ JNIEXPORT void JNICALL Java_ie_equalit_ouinet_Ouinet_nStartClient( JNIEnv* env, jobject /* this */, - jobjectArray jargs, - jobjectArray jpath) + jobjectArray jargs) { size_t argn = env->GetArrayLength(jargs); + vector args; args.reserve(argn); @@ -126,19 +98,7 @@ Java_ie_equalit_ouinet_Ouinet_nStartClient( env->ReleaseStringUTFChars(jstr, arg); } - - size_t pathn = env->GetArrayLength(jpath); - vector path; - path.reserve(pathn); - - for (size_t i = 0; i < pathn; ++i) { - jstring jstr = (jstring) env->GetObjectArrayElement(jpath, i); - const char* dir = env->GetStringUTFChars(jstr, 0); - path.push_back(dir); - env->ReleaseStringUTFChars(jstr, dir); - } - - start_client_thread(args, path); + start_client_thread(args); } extern "C" diff --git a/android/ouinet/src/main/java/ie/equalit/ouinet/Ouinet.java b/android/ouinet/src/main/java/ie/equalit/ouinet/Ouinet.java index f46f1e3e5..ad1c4047c 100644 --- a/android/ouinet/src/main/java/ie/equalit/ouinet/Ouinet.java +++ b/android/ouinet/src/main/java/ie/equalit/ouinet/Ouinet.java @@ -23,7 +23,7 @@ public class Ouinet { System.setProperty("https.proxyHost", "127.0.0.1"); System.setProperty("https.proxyPort", "8080"); } - private static final String TAG = "Ouinet"; + private Context _ctx; private WifiManager.MulticastLock _lock = null; @@ -41,9 +41,7 @@ public static class Config { public Ouinet(Context ctx, Config conf) { _ctx = ctx; - List args = new ArrayList(); - List path = new ArrayList(); - + Vector args = new Vector(); new File(dir()).mkdirs(); @@ -52,13 +50,14 @@ public Ouinet(Context ctx, Config conf) { // repository and fails if this conf file isn't there. new File(dir() + "/ouinet-client.conf").createNewFile(); } catch (IOException e) { - Log.d(TAG, "Exception thrown while creating ouinet config file: ", e); + Log.d("Ouinet", + "Exception thrown while creating ouinet config file: " + e); } - args.add("ouinet-client"); // App name - args.add("--repo=" + dir()); - args.add("--listen-on-tcp=127.0.0.1:8080"); - args.add("--front-end-ep=0.0.0.0:8081"); + args.addElement("ouinet-client"); // App name + args.addElement("--repo=" + dir()); + args.addElement("--listen-on-tcp=127.0.0.1:8080"); + args.addElement("--front-end-ep=0.0.0.0:8081"); maybeAdd(args, "--injector-ep", conf.injector_endpoint); maybeAdd(args, "--injector-credentials", conf.injector_credentials); @@ -77,7 +76,7 @@ public Ouinet(Context ctx, Config conf) { String asset = conf.tls_ca_cert_store_path.substring(assetPrefix.length()); ca_cert_path = dir() + "/assets/" + asset; - if (copyAssetToFile(asset, ca_cert_path)) { + if (copyAssetToFile(ctx, asset, ca_cert_path)) { maybeAdd(args, "--tls-ca-cert-store-path", ca_cert_path); } } @@ -90,21 +89,15 @@ public Ouinet(Context ctx, Config conf) { if (conf.injector_tls_cert != null) { String cert_path = dir() + "/injector-tls-cert.pem"; writeToFile(cert_path, conf.injector_tls_cert.getBytes()); - args.add("--injector-tls-cert-file=" + cert_path); + args.addElement("--injector-tls-cert-file=" + cert_path); } } catch (IOException e) { - Log.d(TAG, "Exception thrown while creating injector's cert file: ", e); - } - - String objfs4proxy_path = dir() + "/objfs4proxy"; - if (copyExecutableToFile("obfs4proxy", objfs4proxy_path)) { - Log.d(TAG, "objfs4proxy copied to " + objfs4proxy_path); - path.add(dir()); - } else { - Log.d(TAG, "objfs4proxy not copied"); + Log.d("Ouinet", + "Exception thrown while creating injector's cert file: " + e); + e.printStackTrace(); } - nStartClient(args.toArray(new String[0]), path.toArray(new String[0])); + nStartClient(listToArray(args)); } public String pathToCARootCert() @@ -112,35 +105,24 @@ public String pathToCARootCert() return nPathToCARootCert(); } - public boolean copyAssetToFile(String asset, String path) + public boolean copyAssetToFile(Context ctx, String asset, String path) { try { - java.io.InputStream stream = _ctx.getAssets().open(asset); + java.io.InputStream stream = ctx.getAssets().open(asset); int size = stream.available(); byte[] buffer = new byte[size]; stream.read(buffer); stream.close(); writeToFile(path, buffer); } catch (IOException e) { - Log.d(TAG, "Failed to write asset \"" + asset + "\" to file \"" + path + "\"", e); + Log.d("Ouinet", "Failed to write asset \"" + asset + "\" to file \"" + path + "\""); + e.printStackTrace(); return false; } return true; } - public boolean copyExecutableToFile(String asset, String path) { - if (!copyAssetToFile(asset, path)) { - return false; - } - File executable = new File(path); - if (!executable.setExecutable(true)) { - Log.d(TAG, "Failed to set executable for file: " + path); - return false; - } - return true; - } - // If this succeeds, we should be able to do UDP multicasts // from inside ouinet (currently know to be needed by IPFS' mDNS // but that's not essential for WAN). @@ -188,9 +170,16 @@ public void setCredentialsFor(String injector, String credentials) { } //---------------------------------------------------------------- - private void maybeAdd(List args, String key, String value) { + private String[] listToArray(List list) { + String[] ret = new String[list.size()]; + int i = 0; + for (String s : list) { ret[i] = s; i += 1; } + return ret; + } + + private void maybeAdd(Vector args, String key, String value) { if (value == null || value.isEmpty()) return; - args.add(key + "=" + value); + args.addElement(key + "=" + value); } private void writeToFile(String path, byte[] bytes) throws IOException { @@ -217,7 +206,7 @@ private String dir() { * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ - private native void nStartClient(String[] args, String[] path); + private native void nStartClient(String[] args); private native void nStopClient(); private native void nSetInjectorEP(String endpoint); diff --git a/modules/asio-ipfs b/modules/asio-ipfs index cffde1f77..1fcf2855e 160000 --- a/modules/asio-ipfs +++ b/modules/asio-ipfs @@ -1 +1 @@ -Subproject commit cffde1f77da95be90808e6260c34fa400802a8d1 +Subproject commit 1fcf2855ee7ca9e6cb48150d4624c2989b8bb1f1 diff --git a/modules/obfs4proxy/CMakeLists.txt b/modules/obfs4proxy/CMakeLists.txt deleted file mode 100644 index f070b96e5..000000000 --- a/modules/obfs4proxy/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -cmake_minimum_required (VERSION 3.5) - -include(ExternalProject) - -################################################################################ -project(obfs4proxy) - -# Convert system name into GOOS. -if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") - set(GOOS "linux") -elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Android") - set(GOOS "android") -else() - message(FATAL_ERROR "unsupported system name ${CMAKE_SYSTEM_NAME}") -endif() - -# Convert system processor into GOARCH (and maybe GOARM). -if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - set(GOARCH "amd64") -elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") - set(GOARCH "arm64") -elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7-a") - set(GOARCH "arm") - set(GOARM "7") -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^arm.*") - set(GOARCH "arm") - set(GOARM "6") -else() - message(FATAL_ERROR "unsupported system processor ${CMAKE_SYSTEM_PROCESSOR}") -endif() - -# Build target tag with the Android API version if relevant. -if("${CMAKE_SYSTEM_NAME}" STREQUAL "Android") - set(TARGET "${CMAKE_SYSTEM_NAME}${CMAKE_SYSTEM_VERSION}--${CMAKE_SYSTEM_PROCESSOR}") -else() - set(TARGET "${CMAKE_SYSTEM_NAME}--${CMAKE_SYSTEM_PROCESSOR}") -endif() - -set(GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go-workspace") - -# -# Using CGO_ENABLED causes go to use the external linker shipped by the -# android ndk. This is almost certainly the wrong way to do it, but it -# seems to work for now. -# -externalproject_add(obfs4proxy - URL https://github.com/Yawning/obfs4/archive/obfs4proxy-0.0.9.tar.gz - URL_MD5 5ec7e4d96bf57fa0b269083076aacd02 - DEPENDS golang - CONFIGURE_COMMAND "" - BUILD_IN_SOURCE 1 - BUILD_COMMAND mkdir -p ${GOPATH} - && export PATH=${GOROOT}/bin:$ENV{PATH} - && export GOPATH=${GOPATH} - && export GOOS=${GOOS} - && export GOARCH=${GOARCH} - && export GOARM=${GOARM} - && export CC=${CMAKE_C_COMPILER} - && export CGO_ENABLED=1 - && go build -o ${CMAKE_CURRENT_BINARY_DIR}/obfs4proxy ./obfs4proxy - INSTALL_COMMAND "" -) diff --git a/scripts/build-android.sh b/scripts/build-android.sh index e268d3d5c..261f9a98c 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -1,7 +1,6 @@ #!/bin/bash set -e -set -x DIR=`pwd` SCRIPT_DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")") @@ -128,22 +127,6 @@ function add_library { done } -###################################################################### -# This variable shall contain paths to generated binaries which -# must all be included in the final Android package. -OUT_BINARIES=() - -function add_binary { - local binaries=("$@") binaries - for binary in "${binaries[@]}"; do - if [ ! -f "$binary" ]; then - echo "Cannot add binary \"$binary\": File doesn't exist" - exit 1 - fi - OUT_BINARIES+=("$binary") - done -} - ###################################################################### MODES= ALLOWED_MODES="build emu abiclean" @@ -299,9 +282,9 @@ function maybe_install_ndk_toolchain { function maybe_install_gradle { GRADLE_REQUIRED_MAJOR_VERSION=4 GRADLE_REQUIRED_MINOR_VERSION=6 - + NEED_GRADLE=false - + if ! which gradle 1> /dev/null 2>&1; then NEED_GRADLE=true else @@ -421,7 +404,6 @@ add_library $DIR/build-ouinet/libclient.so add_library $DIR/build-ouinet/modules/asio-ipfs/ipfs_bindings/libipfs_bindings.so add_library $DIR/build-ouinet/gcrypt/src/gcrypt/src/.libs/libgcrypt.so add_library $DIR/build-ouinet/gpg_error/out/lib/libgpg-error.so -add_binary $DIR/build-ouinet/modules/obfs4proxy/obfs4proxy } ###################################################################### @@ -436,18 +418,6 @@ for lib in "${OUT_LIBS[@]}"; do done } -###################################################################### -function copy_binaries { -local binary_dst_dir="${DIR}"/build-android/builddir/assets/ -rm -rf "${binary_dst_dir}" -mkdir -p "${binary_dst_dir}" -local binary -for binary in "${OUT_BINARIES[@]}"; do - echo "Copying $binary to $binary_dst_dir" - cp $binary $binary_dst_dir/ -done -} - ###################################################################### # Unpolished code to build the debug APK function build_ouinet_apk { @@ -459,8 +429,7 @@ gradle --no-daemon build \ -Pboost_includedir=${BOOST_INCLUDEDIR} \ -Pandroid_abi=${ABI} \ -Pouinet_clientlib_path="${DIR}"/build-android/builddir/deps/${ABI}/libclient.so \ - -Plibdir="${DIR}"/build-android/builddir/deps \ - -Passetsdir="${DIR}"/build-android/builddir/assets + -Plibdir="${DIR}"/build-android/builddir/deps echo "---------------------------------" echo "Your Android package is ready at:" @@ -538,7 +507,6 @@ if check_mode build; then # TODO: miniupnp build_ouinet_libs copy_jni_libs - copy_binaries build_ouinet_apk fi diff --git a/src/client.cpp b/src/client.cpp index 7aa5e2aca..bf915bdd5 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -45,9 +45,6 @@ #include "ouiservice.h" #include "ouiservice/i2p.h" -#include "ouiservice/pt-obfs2.h" -#include "ouiservice/pt-obfs3.h" -#include "ouiservice/pt-obfs4.h" #include "ouiservice/tcp.h" #include "ouiservice/tls.h" @@ -1402,55 +1399,28 @@ void Client::State::setup_injector(asio::yield_context yield) cout << "Setting up injector: " << *injector_ep << endl; - std::unique_ptr client; - - if (injector_ep->type == Endpoint::I2pEndpoint) { + if (is_i2p_endpoint(*injector_ep)) { + std::string ep = boost::get(*injector_ep).pubkey; auto i2p_service = make_shared((_config.repo_root()/"i2p").string(), _ios); - auto i2p_client = i2p_service->build_client(injector_ep->endpoint_string); - - /* - if (!i2p_client->verify_endpoint()) { - return or_throw(yield, asio::error::invalid_argument); - } - */ - client = std::move(i2p_client); - } else if (injector_ep->type == Endpoint::TcpEndpoint) { - auto tcp_client = make_unique(_ios, injector_ep->endpoint_string); + std::unique_ptr i2p_client = i2p_service->build_client(ep); - if (!tcp_client->verify_endpoint()) { - return or_throw(yield, asio::error::invalid_argument); - } - client = std::move(tcp_client); - } else if (injector_ep->type == Endpoint::Obfs2Endpoint) { - auto obfs2_client = make_unique(_ios, injector_ep->endpoint_string, _config.repo_root()/"obfs2-client"); + _injector->add(std::move(i2p_client)); + } else { + tcp::endpoint tcp_endpoint + = boost::get(*injector_ep); - if (!obfs2_client->verify_endpoint()) { - return or_throw(yield, asio::error::invalid_argument); - } - client = std::move(obfs2_client); - } else if (injector_ep->type == Endpoint::Obfs3Endpoint) { - auto obfs3_client = make_unique(_ios, injector_ep->endpoint_string, _config.repo_root()/"obfs3-client"); + auto tcp_client + = make_unique(_ios, tcp_endpoint); - if (!obfs3_client->verify_endpoint()) { - return or_throw(yield, asio::error::invalid_argument); - } - client = std::move(obfs3_client); - } else if (injector_ep->type == Endpoint::Obfs4Endpoint) { - auto obfs4_client = make_unique(_ios, injector_ep->endpoint_string, _config.repo_root()/"obfs4-client"); + bool enable_injector_tls = !_config.tls_injector_cert_path().empty(); - if (!obfs4_client->verify_endpoint()) { - return or_throw(yield, asio::error::invalid_argument); + if (!enable_injector_tls) { + _injector->add(std::move(tcp_client)); + } else { + auto tls_client + = make_unique(move(tcp_client), inj_ctx); + _injector->add(std::move(tls_client)); } - client = std::move(obfs4_client); - } - - bool enable_injector_tls = !_config.tls_injector_cert_path().empty(); - if (!enable_injector_tls) { - _injector->add(std::move(client)); - } else { - auto tls_client - = make_unique(move(client), inj_ctx); - _injector->add(std::move(tls_client)); } _injector->start(yield); @@ -1478,14 +1448,10 @@ void Client::State::set_injector(string injector_ep_str) _config.set_injector_endpoint(*injector_ep); - asio::spawn(_ios, [self = shared_from_this(), injector_ep_str] (auto yield) { + asio::spawn(_ios, [self = shared_from_this()] (auto yield) { if (self->was_stopped()) return; sys::error_code ec; self->setup_injector(yield[ec]); - - if (ec == asio::error::invalid_argument) { - cerr << "Failed to parse endpoint \"" << injector_ep_str << "\"" << endl; - } }); } diff --git a/src/client_front_end.h b/src/client_front_end.h index 3c6dc04fd..00fc2bbc9 100644 --- a/src/client_front_end.h +++ b/src/client_front_end.h @@ -6,6 +6,7 @@ #include #include #include "namespaces.h" +#include "endpoint.h" #include "ssl/ca_certificate.h" namespace ouinet { class CacheClient; } diff --git a/src/endpoint.cpp b/src/endpoint.cpp index ec826c2ce..db5a9929f 100644 --- a/src/endpoint.cpp +++ b/src/endpoint.cpp @@ -2,58 +2,40 @@ namespace ouinet { -boost::optional parse_endpoint(beast::string_view endpoint) -{ - size_t pos = endpoint.find(':'); - if (pos == std::string::npos) { - return boost::none; - } - beast::string_view type = endpoint.substr(0, pos); - Endpoint output; - output.endpoint_string = endpoint.substr(pos + 1).to_string(); - - if (type == "tcp") { - output.type = Endpoint::TcpEndpoint; - } else if (type == "i2p") { - output.type = Endpoint::I2pEndpoint; #ifdef USE_GNUNET - } else if (type == "gnunet") { - output.type = Endpoint::GnunetEndpoint; +std::ostream& operator<<(std::ostream& os, const GnunetEndpoint& ep) +{ + return os << ep.host << ":" << ep.port; +} #endif - } else if (type == "obfs2") { - output.type = Endpoint::Obfs2Endpoint; - } else if (type == "obfs3") { - output.type = Endpoint::Obfs3Endpoint; - } else if (type == "obfs4") { - output.type = Endpoint::Obfs4Endpoint; - } else { - return boost::none; - } - return output; + +std::ostream& operator<<(std::ostream& os, const I2PEndpoint& ep) +{ + return os << ep.pubkey; } std::ostream& operator<<(std::ostream& os, const Endpoint& ep) { - if (ep.type == Endpoint::TcpEndpoint) { - os << "tcp"; - } else if (ep.type == Endpoint::I2pEndpoint) { - os << "i2p"; + struct Visitor { + std::ostream& os; + + void operator()(const asio::ip::tcp::endpoint& ep) { + os << ep; + } + #ifdef USE_GNUNET - } else if (ep.type == Endpoint::GnunetEndpoint) { - os << "i2p"; + void operator()(const GnunetEndpoint& ep) { + os << ep; + } #endif - } else if (ep.type == Endpoint::Obfs2Endpoint) { - os << "obfs2"; - } else if (ep.type == Endpoint::Obfs3Endpoint) { - os << "obfs3"; - } else if (ep.type == Endpoint::Obfs4Endpoint) { - os << "obfs4"; - } else { - assert(false); - } - - os << ":"; - os << ep.endpoint_string; + + void operator()(const I2PEndpoint& ep) { + os << ep; + } + }; + + Visitor visitor{os}; + boost::apply_visitor(visitor, ep); return os; } diff --git a/src/endpoint.h b/src/endpoint.h index dc0eee57a..a8e1bd999 100644 --- a/src/endpoint.h +++ b/src/endpoint.h @@ -7,28 +7,57 @@ namespace ouinet { -struct Endpoint { - enum Type { - TcpEndpoint, - I2pEndpoint, -#ifdef USE_GNUNET - GnunetEndpoint, -#endif - Obfs2Endpoint, - Obfs3Endpoint, - Obfs4Endpoint +struct I2PEndpoint { + std::string pubkey; + + bool operator==(const I2PEndpoint& other) const { + return pubkey == other.pubkey; + } +}; + +using Endpoint = boost::variant< asio::ip::tcp::endpoint + , I2PEndpoint>; + +inline +boost::optional parse_endpoint(beast::string_view endpoint) +{ + using std::string; + using beast::string_view; + using asio::ip::tcp; + + auto as_tcp_endpoint = []( string_view host + , string_view port + ) -> boost::optional { + sys::error_code ec; + auto ip = asio::ip::address::from_string(host.to_string(), ec); + if (ec) return boost::none; + return tcp::endpoint(ip, strtol(port.data(), 0, 10)); }; - Type type; - std::string endpoint_string; + sys::error_code ec; + + string_view host; + string_view port; - bool operator==(const Endpoint& other) const { - return type == other.type && endpoint_string == other.endpoint_string; + std::tie(host, port) = split_string_pair(endpoint, ':'); + + if (port.empty()) { + return Endpoint{I2PEndpoint{endpoint.to_string()}}; } -}; -boost::optional parse_endpoint(beast::string_view endpoint); + if (auto ep = as_tcp_endpoint(host, port)) { + return Endpoint{*ep}; + } + + return boost::none; +} + +inline +bool is_i2p_endpoint(const Endpoint& ep) { + return boost::get(&ep) ? true : false; +} +std::ostream& operator<<(std::ostream& os, const I2PEndpoint&); std::ostream& operator<<(std::ostream& os, const Endpoint&); } // ouinet namespace diff --git a/src/injector.cpp b/src/injector.cpp index 90745307f..3eebc3587 100644 --- a/src/injector.cpp +++ b/src/injector.cpp @@ -34,9 +34,6 @@ #include "ouiservice.h" #include "ouiservice/i2p.h" -#include "ouiservice/pt-obfs2.h" -#include "ouiservice/pt-obfs3.h" -#include "ouiservice/pt-obfs4.h" #include "ouiservice/tcp.h" #include "ouiservice/tls.h" #include "ssl/ca_certificate.h" @@ -779,45 +776,6 @@ int main(int argc, const char* argv[]) proxy_server.add(make_unique(move(base), ssl_context)); } - if (config.obfs2_endpoint()) { - tcp::endpoint endpoint = *config.obfs2_endpoint(); - cout << "obfs2 Address: " << util::str(endpoint) << endl; - util::create_state_file( config.repo_root()/"endpoint-obfs2" - , util::str(endpoint)); - - proxy_server.add(make_unique(ios, endpoint, config.repo_root()/"obfs2-server")); - } - - if (config.obfs3_endpoint()) { - tcp::endpoint endpoint = *config.obfs3_endpoint(); - cout << "obfs3 Address: " << util::str(endpoint) << endl; - util::create_state_file( config.repo_root()/"endpoint-obfs3" - , util::str(endpoint)); - - proxy_server.add(make_unique(ios, endpoint, config.repo_root()/"obfs3-server")); - } - - if (config.obfs4_endpoint()) { - tcp::endpoint endpoint = *config.obfs4_endpoint(); - - util::create_state_file( config.repo_root()/"endpoint-obfs4" - , util::str(endpoint)); - - unique_ptr server = - make_unique(ios, endpoint, config.repo_root()/"obfs4-server"); - asio::spawn(ios, [ - obfs4 = server.get(), - endpoint - ] (asio::yield_context yield) { - sys::error_code ec; - obfs4->wait_for_running(yield[ec]); - if (!ec) { - cout << "obfs4 Address: " << util::str(endpoint) << "," << obfs4->connection_arguments() << endl; - } - }); - proxy_server.add(std::move(server)); - } - if (config.listen_on_i2p()) { auto i2p_service = make_shared((config.repo_root()/"i2p").string(), ios); std::unique_ptr i2p_server = i2p_service->build_server("i2p-private-key"); diff --git a/src/injector_config.h b/src/injector_config.h index 75cb4fdd9..732f82612 100644 --- a/src/injector_config.h +++ b/src/injector_config.h @@ -34,15 +34,6 @@ class InjectorConfig { boost::optional tls_endpoint() const { return _tls_endpoint; } - boost::optional obfs2_endpoint() const - { return _obfs2_endpoint; } - - boost::optional obfs3_endpoint() const - { return _obfs3_endpoint; } - - boost::optional obfs4_endpoint() const - { return _obfs4_endpoint; } - static boost::program_options::options_description options_description(); @@ -67,9 +58,6 @@ class InjectorConfig { bool _listen_on_i2p = false; boost::optional _tcp_endpoint; boost::optional _tls_endpoint; - boost::optional _obfs2_endpoint; - boost::optional _obfs3_endpoint; - boost::optional _obfs4_endpoint; boost::filesystem::path OUINET_CONF_FILE = "ouinet-injector.conf"; std::string _credentials; util::Ed25519PrivateKey _index_bep44_private_key; @@ -98,9 +86,6 @@ InjectorConfig::options_description() // Transport options ("listen-on-tcp", po::value(), "IP:PORT endpoint on which we'll listen (cleartext)") ("listen-on-tls", po::value(), "IP:PORT endpoint on which we'll listen (encrypted)") - ("listen-on-obfs2", po::value(), "IP:PORT endpoint on which we'll listen using the obfs2 pluggable transport") - ("listen-on-obfs3", po::value(), "IP:PORT endpoint on which we'll listen using the obfs3 pluggable transport") - ("listen-on-obfs4", po::value(), "IP:PORT endpoint on which we'll listen using the obfs4 pluggable transport") ("listen-on-i2p", po::value(), "Whether we should be listening on I2P (true/false)") @@ -199,18 +184,6 @@ InjectorConfig::InjectorConfig(int argc, const char**argv) _tls_endpoint = util::parse_tcp_endpoint(vm["listen-on-tls"].as()); } - if (vm.count("listen-on-obfs2")) { - _obfs2_endpoint = util::parse_tcp_endpoint(vm["listen-on-obfs2"].as()); - } - - if (vm.count("listen-on-obfs3")) { - _obfs3_endpoint = util::parse_tcp_endpoint(vm["listen-on-obfs3"].as()); - } - - if (vm.count("listen-on-obfs4")) { - _obfs4_endpoint = util::parse_tcp_endpoint(vm["listen-on-obfs4"].as()); - } - setup_index_bep44_private_key( vm.count("index-bep44-private-key") ? vm["index-bep44-private-key"].as() : string()); diff --git a/src/ouiservice/pluggable-transports/client-process.cpp b/src/ouiservice/pluggable-transports/client-process.cpp deleted file mode 100644 index 0d9a4e3e9..000000000 --- a/src/ouiservice/pluggable-transports/client-process.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "client-process.h" -#include "util.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -ClientProcess::ClientProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - std::string transport_name, - boost::optional state_directory -): - DispatcherProcess(ios, command, command_line_arguments, state_directory), - _transport_name(transport_name), - _transport_initialized(false) -{ -} - -void ClientProcess::start(asio::yield_context yield, Signal& cancel_signal) -{ - std::map environment; - environment["TOR_PT_CLIENT_TRANSPORTS"] = _transport_name; - - start_process(environment, yield, cancel_signal); -} - -void ClientProcess::stop() -{ - stop_process(); -} - -void ClientProcess::process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized -) { - if (command == "PROXY") { - ec = asio::error::fault; - } else if (command == "PROXY-ERROR") { - ec = asio::error::fault; - } else if (command == "CMETHOD") { - if (args.size() < 3) { - ec = asio::error::fault; - return; - } - if (args[0] != _transport_name) { - return; - } - if (args[1] == "socks5") { - _connection_method = Socks5Connection; - } else if (args[1] == "transparent-TCP") { - _connection_method = TransparentConnection; - } else { - ec = asio::error::fault; - return; - } - boost::optional endpoint = parse_endpoint(args[2]); - if (!endpoint) { - ec = asio::error::fault; - return; - } - _endpoint = *endpoint; - _transport_initialized = true; - } else if (command == "CMETHOD-ERROR") { - ec = asio::error::fault; - } else if (command == "CMETHODS") { - if (args.size() != 1 || args[0] != "DONE") { - ec = asio::error::fault; - return; - } - if (_transport_initialized) { - initialized = true; - } else { - ec = asio::error::operation_not_supported; - } - } else { - DispatcherProcess::process_output_line(command, args, ec, initialized); - } -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/client-process.h b/src/ouiservice/pluggable-transports/client-process.h deleted file mode 100644 index 197cd9f91..000000000 --- a/src/ouiservice/pluggable-transports/client-process.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include - -#include "dispatcher-process.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -class ClientProcess : public DispatcherProcess -{ - public: - enum ConnectionMethod { - Socks5Connection, - TransparentConnection - }; - - public: - ClientProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - std::string transport_name, - boost::optional state_directory - ); - - void start(asio::yield_context yield, Signal& cancel_signal); - void stop(); - - asio::ip::tcp::endpoint endpoint() const { return _endpoint; } - ConnectionMethod connection_method() const { return _connection_method; } - - protected: - void process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized - ) override; - - protected: - std::string _transport_name; - - bool _transport_initialized; - asio::ip::tcp::endpoint _endpoint; - ConnectionMethod _connection_method; -}; - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/dispatcher-process.cpp b/src/ouiservice/pluggable-transports/dispatcher-process.cpp deleted file mode 100644 index 7658d2530..000000000 --- a/src/ouiservice/pluggable-transports/dispatcher-process.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include "dispatcher-process.h" -#include "../../or_throw.h" -#include "../../util/condition_variable.h" - -#include -#include -#include - -namespace ouinet { -namespace ouiservice { -namespace pt { - -static void parse_output_line(std::string line, std::string& command, std::vector& args) -{ - size_t pos = line.find(' '); - if (pos == std::string::npos) { - command = line; - return; - } else { - command = line.substr(0, pos); - line = line.substr(pos + 1); - } - - while (!line.empty()) { - while (line[0] == ' ') { - line.erase(line.begin()); - } - if (line.empty()) { - break; - } - pos = line.find(' '); - if (pos == std::string::npos) { - args.push_back(line); - break; - } else { - args.push_back(line.substr(0, pos)); - line = line.substr(pos + 1); - } - } -} - -DispatcherProcess::DispatcherProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - boost::optional state_directory -): - _ios(ios), - _command(command), - _command_line_arguments(command_line_arguments), - _state_directory(state_directory) -{ -} - -DispatcherProcess::~DispatcherProcess() -{ - stop_process(); -} - -void DispatcherProcess::start_process( - std::map environment, - asio::yield_context yield, - Signal& cancel_signal -) { - assert(!_process); - - boost::process::environment env = boost::this_process::environment(); - std::vector to_remove; - for (auto i : env) { - if (i.get_name().substr(0, 7) == "TOR_PT_") { - to_remove.push_back(i.get_name()); - } - } - for (auto i : to_remove) { - env.erase(i); - } - env["TOR_PT_MANAGED_TRANSPORT_VER"] = "1"; - env["TOR_PT_EXIT_ON_STDIN_CLOSE"] = "1"; - if (_state_directory) { - env["TOR_PT_STATE_LOCATION"] = *_state_directory; - } - for (auto i : environment) { - env[i.first] = i.second; - } - - _standard_input = std::make_unique(_ios); - auto standard_output = std::make_unique(_ios); - _process_exit = std::make_unique>(); - - std::error_code error_code; - _process = std::make_unique( - _command, - boost::process::args(_command_line_arguments), - boost::process::env(env), - boost::process::std_in < *_standard_input, - boost::process::std_out > *standard_output, - boost::process::std_err > boost::process::null, - boost::process::error(error_code), - boost::process::on_exit([ - signal = _process_exit.get() - ] (int exit, const std::error_code& error_code) { - (*signal)(); - }), - _ios - ); - - if (error_code) { - return or_throw(yield, boost::system::errc::make_error_code( - static_cast(error_code.value()) - )); - } - - - - /* - * Start the output processing coroutine, and wait for it to signal - * successful initialization. - * Abort on: - * - cancellation; - * - object destruction; - * - timeout. - */ - - struct InitializationStatus { - ConditionVariable stop_condition; - boost::optional ec; - InitializationStatus(asio::io_service& ios): - stop_condition(ios), - ec(boost::none) - {} - }; - std::shared_ptr initialization = - std::make_shared(_ios); - - asio::steady_timer timeout_timer(_ios); - timeout_timer.expires_from_now(std::chrono::seconds(15)); - timeout_timer.async_wait([initialization] (const sys::error_code&) { - if (!initialization->ec) { - initialization->ec = asio::error::timed_out; - } - initialization->stop_condition.notify(); - }); - - auto cancelled = cancel_signal.connect([&] { - initialization->ec = asio::error::operation_aborted; - timeout_timer.cancel(); - }); - - auto stopped = _stop_signal.connect([&] { - initialization->ec = asio::error::operation_aborted; - timeout_timer.cancel(); - }); - - asio::spawn(_ios, [ - this, - standard_output = std::move(standard_output), - initialization - ] (asio::yield_context yield) { - std::string output_buffer; - /* - * The output processing coroutine can finish initialization in three forms: - * - successful initialization; - * - error reported by process_output_line; - * - EOF. - * - * The output processing coroutine keeps going until it encounters an EOF. - * It is not aborted by the DispatcherProcess under any circumstance; - * rather, the DispatcherProcess kills the process, which will EOF the - * pipe as soon as pending output is processed. After completion, - * either successful or not, further output is ignored. - */ - - /* - * Reading from an async_pipe doesn't work well in boost 1.67. The - * source and sink endpoints are standard boost::asio components, and - * they don't cause problems, so using them works around the issue. - */ - auto standard_output_source = std::move(*standard_output).source(); - - while (true) { - char buffer[4096]; - sys::error_code ec; - - size_t read = standard_output_source.async_read_some( - asio::mutable_buffers_1(buffer, sizeof(buffer)), - yield[ec] - ); - - if (ec || !read) { - break; - } - - if (initialization->ec) { - continue; - } - - output_buffer.append(buffer, buffer + read); - - size_t pos; - while ((pos = output_buffer.find('\n')) != std::string::npos) { - std::string line = output_buffer.substr(0, pos); - output_buffer = output_buffer.substr(pos + 1); - - std::string command; - std::vector args; - parse_output_line(line, command, args); - - bool initialized = false; - process_output_line(command, args, ec, initialized); - if (ec || initialized) { - assert(!initialization->ec); - initialization->ec = ec; - initialization->stop_condition.notify(); - output_buffer.clear(); - break; - } - } - } - - standard_output_source.close(); - - if (!initialization->ec) { - initialization->ec = asio::error::broken_pipe; - initialization->stop_condition.notify(); - } - }); - - initialization->stop_condition.wait(yield); - - assert(initialization->ec); - sys::error_code ec = *initialization->ec; - timeout_timer.cancel(); - - /* - * If stopped() has been called, the process has already been cleaned up, - * and $this may be gone, so we abort before calling stop(). - */ - if (stopped) { - return or_throw(yield, ec); - } - - if (ec) { - stop_process(); - return or_throw(yield, ec); - } -} - -void DispatcherProcess::stop_process() -{ - if (!_process) { - return; - } - - auto process = std::move(_process); - auto standard_input = std::move(_standard_input); - auto process_exit = std::move(_process_exit); - asio::io_service& ios = _ios; - _stop_signal(); - - asio::spawn(_ios, [ - &ios, - process = std::move(process), - standard_input = std::move(standard_input), - process_exit = std::move(process_exit) - ] (asio::yield_context yield) { - standard_input->close(); - - /* - * Closing the standard input triggers the process to quit. - * Wait for process exit or a timeout. - */ - asio::steady_timer timeout_timer(ios); - timeout_timer.expires_from_now(std::chrono::seconds(5)); - - auto exited = process_exit->connect([&] { - timeout_timer.cancel(); - }); - - sys::error_code ec; - timeout_timer.async_wait(yield[ec]); - - if (process->running()) { - process->terminate(); - } - }); -} - -void DispatcherProcess::process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized -) { - if (command == "VERSION-ERROR") { - ec = asio::error::operation_not_supported; - } else if (command == "ENV-ERROR") { - ec = asio::error::operation_not_supported; - } -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/dispatcher-process.h b/src/ouiservice/pluggable-transports/dispatcher-process.h deleted file mode 100644 index 7d7775650..000000000 --- a/src/ouiservice/pluggable-transports/dispatcher-process.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include - -#include "../../namespaces.h" -#include "../../util/signal.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -class DispatcherProcess -{ - public: - DispatcherProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - boost::optional state_directory - ); - ~DispatcherProcess(); - - protected: - void start_process( - std::map environment, - asio::yield_context yield, - Signal& cancel_signal - ); - void stop_process(); - - virtual void process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized - ); - - protected: - asio::io_service& _ios; - std::string _command; - std::vector _command_line_arguments; - boost::optional _state_directory; - - std::unique_ptr _process; - std::unique_ptr _standard_input; - std::unique_ptr> _process_exit; - - Signal _stop_signal; -}; - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/pt-ouiservice.cpp b/src/ouiservice/pluggable-transports/pt-ouiservice.cpp deleted file mode 100644 index bbcda1ceb..000000000 --- a/src/ouiservice/pluggable-transports/pt-ouiservice.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "pt-ouiservice.h" -#include "client-process.h" -#include "server-process.h" -#include "socks5-client.h" -#include "../../or_throw.h" -#include "../../util.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -PtOuiServiceServer::PtOuiServiceServer(asio::io_service& ios): - _ios(ios), - _acceptor(ios), - _start_listen_condition(ios) -{} - -PtOuiServiceServer::~PtOuiServiceServer() -{} - -void PtOuiServiceServer::start_listen(asio::yield_context yield) -{ - sys::error_code ec; - - if (_server_process) { - ec = asio::error::in_progress; - _start_listen_condition.notify(ec); - return or_throw(yield, ec); - } - - asio::ip::tcp::endpoint tcp_endpoint( - asio::ip::address_v4::loopback(), - 0 - ); - - _acceptor.open(tcp_endpoint.protocol(), ec); - if (ec) { - _start_listen_condition.notify(ec); - return or_throw(yield, ec); - } - - _acceptor.set_option(asio::socket_base::reuse_address(true)); - - _acceptor.bind(tcp_endpoint, ec); - if (ec) { - _acceptor.close(); - _start_listen_condition.notify(ec); - return or_throw(yield, ec); - } - - _acceptor.listen(asio::socket_base::max_connections, ec); - if (ec) { - _acceptor.close(); - _start_listen_condition.notify(ec); - return or_throw(yield, ec); - } - - Signal cancel; - _server_process = start_server_process( - _ios, - _acceptor.local_endpoint(), - yield[ec], - cancel - ); - - if (ec) { - _acceptor.cancel(); - _acceptor.close(); - _server_process.reset(); - _start_listen_condition.notify(ec); - return or_throw(yield, ec); - } - - _start_listen_condition.notify(ec); -} - -void PtOuiServiceServer::stop_listen() -{ - if (_server_process) { - _server_process.reset(); - _acceptor.cancel(); - _acceptor.close(); - } -} - -GenericStream PtOuiServiceServer::accept(asio::yield_context yield) -{ - sys::error_code ec; - - asio::ip::tcp::socket socket(_ios); - _acceptor.async_accept(socket, yield[ec]); - - if (ec) { - return or_throw(yield, ec); - } - - static const auto tcp_shutter = [](asio::ip::tcp::socket& s) { - sys::error_code ec; - s.shutdown(asio::ip::tcp::socket::shutdown_both, ec); - s.close(ec); - }; - - return GenericStream(std::move(socket), tcp_shutter); -} - -void PtOuiServiceServer::wait_for_running(asio::yield_context yield) -{ - _start_listen_condition.wait(yield); -} - -std::string PtOuiServiceServer::connection_arguments() const -{ - return _server_process->connection_arguments(); -} - - - -PtOuiServiceClient::PtOuiServiceClient(asio::io_service& ios): - _ios(ios) -{} - -PtOuiServiceClient::~PtOuiServiceClient() -{} - -void PtOuiServiceClient::start(asio::yield_context yield) -{ - if (_client_process) { - return or_throw(yield, asio::error::in_progress); - } - - sys::error_code ec; - Signal cancel; - _client_process = start_client_process( - _ios, - yield[ec], - cancel - ); - if (ec) { - _client_process.reset(); - return or_throw(yield, ec); - } -} - -void PtOuiServiceClient::stop() -{ - _client_process.reset(); -} - -OuiServiceImplementationClient::ConnectInfo PtOuiServiceClient::connect( - asio::yield_context yield, - Signal& cancel -) { - if (!_client_process) { - return or_throw(yield, asio::error::not_connected); - } - - sys::error_code ec; - std::string remote_endpoint_string; - asio::ip::tcp::socket socket = connect_through_transport( - _ios, - _client_process->endpoint(), - remote_endpoint_string, - yield[ec], - cancel - ); - - if (ec) { - return or_throw(yield, ec); - } - - static const auto tcp_shutter = [](asio::ip::tcp::socket& s) { - sys::error_code ec; - s.shutdown(asio::ip::tcp::socket::shutdown_both, ec); - s.close(ec); - }; - - return ConnectInfo{ - GenericStream(std::move(socket), tcp_shutter), - remote_endpoint_string - }; -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/pt-ouiservice.h b/src/ouiservice/pluggable-transports/pt-ouiservice.h deleted file mode 100644 index 3c02fad7c..000000000 --- a/src/ouiservice/pluggable-transports/pt-ouiservice.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include "../../ouiservice.h" -#include "../../util/condition_variable.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -class ClientProcess; -class ServerProcess; - -class PtOuiServiceServer : public OuiServiceImplementationServer -{ - public: - PtOuiServiceServer(asio::io_service& ios); - ~PtOuiServiceServer(); - - void start_listen(asio::yield_context yield) final; - void stop_listen() final; - - GenericStream accept(asio::yield_context yield) final; - - /* - * Wait for the next start_listen() call to complete. - * Reports the same error condition as start_listen() itself. - */ - void wait_for_running(asio::yield_context yield); - std::string connection_arguments() const; - - protected: - virtual std::unique_ptr start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal - ) = 0; - - private: - asio::io_service& _ios; - - asio::ip::tcp::acceptor _acceptor; - std::unique_ptr _server_process; - ConditionVariable _start_listen_condition; -}; - -class PtOuiServiceClient : public OuiServiceImplementationClient -{ - public: - PtOuiServiceClient(asio::io_service& ios); - ~PtOuiServiceClient(); - - void start(asio::yield_context yield) final; - void stop() final; - - OuiServiceImplementationClient::ConnectInfo connect( - asio::yield_context yield, - Signal& cancel - ) final; - - protected: - virtual std::unique_ptr start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal - ) = 0; - virtual asio::ip::tcp::socket connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal - ) = 0; - - private: - asio::io_service& _ios; - - std::unique_ptr _client_process; -}; - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/server-process.cpp b/src/ouiservice/pluggable-transports/server-process.cpp deleted file mode 100644 index 2b741ec24..000000000 --- a/src/ouiservice/pluggable-transports/server-process.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "server-process.h" -#include "util.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -ServerProcess::ServerProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - std::string transport_name, - boost::optional bind_address, - asio::ip::tcp::endpoint destination_address, - std::map transport_options, - boost::optional state_directory -): - DispatcherProcess(ios, command, command_line_arguments, state_directory), - _transport_name(transport_name), - _bind_address(bind_address), - _destination_address(destination_address), - _transport_options(transport_options), - _transport_initialized(false) -{ -} - -void ServerProcess::start(asio::yield_context yield, Signal& cancel_signal) -{ - std::map environment; - environment["TOR_PT_SERVER_TRANSPORTS"] = _transport_name; - if (!_transport_options.empty()) { - std::string transport_options; - for (auto i : _transport_options) { - if (!transport_options.empty()) { - transport_options += ";"; - } - transport_options += _transport_name; - transport_options += ":"; - transport_options += string_escape(i.first, ":;="); - transport_options += "="; - transport_options += string_escape(i.second, ":;="); - } - environment["TOR_PT_SERVER_TRANSPORT_OPTIONS"] = transport_options; - } - if (_bind_address) { - std::string bind_address; - bind_address += _transport_name; - bind_address += "-"; - bind_address += format_endpoint(*_bind_address); - environment["TOR_PT_SERVER_BINDADDR"] = bind_address; - } - environment["TOR_PT_ORPORT"] = format_endpoint(_destination_address); - - start_process(environment, yield, cancel_signal); -} - -void ServerProcess::stop() -{ - stop_process(); -} - -void ServerProcess::process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized -) { - if (command == "SMETHOD") { - if (args.size() < 2) { - ec = asio::error::fault; - return; - } - if (args[0] != _transport_name) { - return; - } - boost::optional endpoint = parse_endpoint(args[1]); - if (!endpoint) { - ec = asio::error::fault; - return; - } - _listening_endpoint = *endpoint; - - for (size_t i = 2; i < args.size(); i++) { - std::string arg = args[i]; - if (arg.substr(0, 5) == "ARGS:") { - _connection_arguments = arg.substr(5); - } - } - - _transport_initialized = true; - } else if (command == "SMETHOD-ERROR") { - ec = asio::error::fault; - } else if (command == "SMETHODS") { - if (args.size() != 1 || args[0] != "DONE") { - ec = asio::error::fault; - return; - } - if (_transport_initialized) { - initialized = true; - } else { - ec = asio::error::operation_not_supported; - } - } else { - DispatcherProcess::process_output_line(command, args, ec, initialized); - } -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/server-process.h b/src/ouiservice/pluggable-transports/server-process.h deleted file mode 100644 index 8535a9b62..000000000 --- a/src/ouiservice/pluggable-transports/server-process.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include - -#include "dispatcher-process.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -class ServerProcess : public DispatcherProcess -{ - public: - ServerProcess( - asio::io_service& ios, - std::string command, - std::vector command_line_arguments, - std::string transport_name, - boost::optional bind_address, - asio::ip::tcp::endpoint destination_address, - std::map transport_options, - boost::optional state_directory - ); - - void start(asio::yield_context yield, Signal& cancel_signal); - void stop(); - - asio::ip::tcp::endpoint listening_endpoint() const { return _listening_endpoint; } - std::string connection_arguments() const { return _connection_arguments; } - - protected: - void process_output_line( - std::string command, - std::vector args, - sys::error_code& ec, - bool& initialized - ) override; - - protected: - std::string _transport_name; - boost::optional _bind_address; - asio::ip::tcp::endpoint _destination_address; - std::map _transport_options; - - bool _transport_initialized; - asio::ip::tcp::endpoint _listening_endpoint; - std::string _connection_arguments; -}; - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/socks5-client.cpp b/src/ouiservice/pluggable-transports/socks5-client.cpp deleted file mode 100644 index 454daa96f..000000000 --- a/src/ouiservice/pluggable-transports/socks5-client.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#include "socks5-client.h" -#include "util.h" -#include "../../or_throw.h" - -#include - -namespace ouinet { -namespace ouiservice { -namespace pt { - -/* - * Communicate connection arguments via Json Parameter Block authentication. - * This method is described in the PT specification; actual implementation - * degree is unclear. - */ -/* -ruud: -I can't find any complete documentation on this, and no code that uses it. -Let's implement this once we find a use case for it. - -void connection_arguments_json( - asio::ip::tcp::socket& socket, - std::map& connection_arguments, - asio::yield_context yield -) { -} -*/ - -/* - * Communicate connection arguments encoded in username/password. - * This encoding is not described in the specification, but widely implemented. - */ -void connection_arguments_username( - asio::ip::tcp::socket& socket, - std::map& connection_arguments, - asio::yield_context yield -) { - sys::error_code ec; - - std::string encoded_arguments; - for (auto i : connection_arguments) { - if (!encoded_arguments.empty()) { - encoded_arguments += ";"; - } - encoded_arguments += string_escape(i.first, ";="); - encoded_arguments += "="; - encoded_arguments += string_escape(i.second, ";="); - } - - std::string packet; - packet += '\x01'; // authentication scheme version - packet += (char)(encoded_arguments.size()); // username size - packet += encoded_arguments; // username - packet += '\x01'; // password size - packet += '\x00'; // password - - socket.async_send( - asio::const_buffers_1(packet.data(), packet.size()), - 0, yield[ec] - ); - if (ec) { - return or_throw(yield, ec); - } - - char reply[2]; - size_t received = socket.async_receive( - asio::mutable_buffers_1(reply, sizeof(reply)), - 0, yield[ec] - ); - if (ec) { - return or_throw(yield, ec); - } - - if (received != 2) { - return or_throw(yield, asio::error::connection_reset); - } - // authentication scheme version - if (reply[0] != '\x01') { - return or_throw(yield, asio::error::access_denied); - } - // error code - if (reply[1] != '\0') { - return or_throw(yield, asio::error::access_denied); - } -} - - -asio::ip::tcp::socket connect_socks5( - asio::ip::tcp::endpoint proxy_endpoint, - asio::ip::tcp::endpoint destination_endpoint, - boost::optional> connection_arguments, - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel -) { - sys::error_code ec; - - asio::ip::tcp::socket socket(ios); - - auto cancel_slot = cancel.connect([&] { - // tcp::socket::cancel() does not work properly on all platforms - sys::error_code ec; - socket.close(ec); - }); - - socket.async_connect(proxy_endpoint, yield[ec]); - if (ec) { - return or_throw(yield, ec, std::move(socket)); - } - - - - std::string negotiation_request; - negotiation_request += '\x05'; // protocol version 5 - if (connection_arguments) { - negotiation_request += '\x01'; // 1 authentication methods supported - //negotiation_request += '\x09'; // Json Parameter Block authentication - negotiation_request += '\x02'; // username/password authentication - } else { - negotiation_request += '\x01'; // 1 authentication methods supported - negotiation_request += '\x00'; // null authentication - } - - socket.async_send( - asio::const_buffers_1(negotiation_request.data(), negotiation_request.size()), - 0, yield[ec] - ); - if (ec) { - socket.close(); - return or_throw(yield, ec, std::move(socket)); - } - - size_t received; - - char negotiation_reply[2]; - received = socket.async_receive( - asio::mutable_buffers_1(negotiation_reply, sizeof(negotiation_reply)), - 0, yield[ec] - ); - if (ec) { - socket.close(); - return or_throw(yield, ec, std::move(socket)); - } - - if (received != sizeof(negotiation_reply)) { - socket.close(); - return or_throw(yield, asio::error::connection_reset, std::move(socket)); - } - // protocol version 5 - if (negotiation_reply[0] != '\x05') { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - - if (connection_arguments) { - if (negotiation_reply[1] == '\x02') { - // username/password authentication - connection_arguments_username(socket, *connection_arguments, yield[ec]); - if (ec) { - socket.close(); - return or_throw(yield, ec, std::move(socket)); - } - } else { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - } else { - if (negotiation_reply[1] != 0) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - } - - - - std::string connect_request; - connect_request += '\x05'; // protocol version 5 - connect_request += '\x01'; // CONNECT - connect_request += '\x00'; // reserved - if (destination_endpoint.address().is_v4()) { - connect_request += '\x01'; // ipv4 address - auto address = destination_endpoint.address().to_v4().to_bytes(); - connect_request.append(address.begin(), address.end()); - } else { - connect_request += '\x04'; // ipv6 address - auto address = destination_endpoint.address().to_v6().to_bytes(); - connect_request.append(address.begin(), address.end()); - } - connect_request += (destination_endpoint.port() >> 8) & 0xff; - connect_request += (destination_endpoint.port() >> 0) & 0xff; - - socket.async_send( - asio::const_buffers_1(connect_request.data(), connect_request.size()), - 0, yield[ec] - ); - if (ec) { - socket.close(); - return or_throw(yield, ec, std::move(socket)); - } - - char connect_reply_start[4]; - received = socket.async_receive( - asio::mutable_buffers_1(connect_reply_start, sizeof(connect_reply_start)), - 0, yield[ec] - ); - if (ec) { - socket.close(); - return or_throw(yield, ec, std::move(socket)); - } - if (received != sizeof(connect_reply_start)) { - socket.close(); - return or_throw(yield, asio::error::connection_reset, std::move(socket)); - } - // protocol version 5 - if (connect_reply_start[0] != '\x05') { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - // error code - if (connect_reply_start[1] != '\x00') { - socket.close(); - if (connect_reply_start[1] == '\x02') { - // connection not allowed by ruleset - std::cout << "operation not permitted? echt?\n"; - ec = asio::error::no_permission; - } else if (connect_reply_start[1] == '\x03') { - // Network unreachable - ec = asio::error::network_unreachable; - } else if (connect_reply_start[1] == '\x04') { - // Host unreachable - ec = asio::error::host_unreachable; - } else { - ec = asio::error::connection_refused; - } - return or_throw(yield, ec, std::move(socket)); - } - // reserved - if (connect_reply_start[2] != '\x00') { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - // address type - if (connect_reply_start[3] == '\x01') { - // ipv4 - char buffer[4]; - received = socket.async_receive( - asio::mutable_buffers_1(buffer, sizeof(buffer)), - 0, yield[ec] - ); - if (ec || received != sizeof(buffer)) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - } else if (connect_reply_start[3] == '\x04') { - // ipv6 - char buffer[16]; - received = socket.async_receive( - asio::mutable_buffers_1(buffer, sizeof(buffer)), - 0, yield[ec] - ); - if (ec || received != sizeof(buffer)) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - } else if (connect_reply_start[3] == '\x03') { - // hostname - char dummy_buffer[256]; - unsigned char size; - received = socket.async_receive( - asio::mutable_buffers_1(&size, 1), - 0, yield[ec] - ); - if (ec || received != 1) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - received = socket.async_receive( - asio::mutable_buffers_1(&dummy_buffer, size), - 0, yield[ec] - ); - if (ec || received != size) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - } else { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - char port_buffer[2]; - received = socket.async_receive( - asio::mutable_buffers_1(port_buffer, sizeof(port_buffer)), - 0, yield[ec] - ); - if (ec || received != sizeof(port_buffer)) { - socket.close(); - return or_throw(yield, asio::error::connection_refused, std::move(socket)); - } - - // Connection accepted. - return std::move(socket); -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/socks5-client.h b/src/ouiservice/pluggable-transports/socks5-client.h deleted file mode 100644 index 18aaa83b3..000000000 --- a/src/ouiservice/pluggable-transports/socks5-client.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "../../namespaces.h" -#include "../../util/signal.h" - -namespace ouinet { -namespace ouiservice { -namespace pt { - -/* - * Connects to $destination_endpoint using a socks5 proxy at $proxy_endpoint. - * Supports optional connection arguments key/value pairs, - * communicated via socks5 authentication. - * On success, returns a TCP socket that is ready for payload data. - */ -asio::ip::tcp::socket connect_socks5( - asio::ip::tcp::endpoint proxy_endpoint, - asio::ip::tcp::endpoint destination_endpoint, - boost::optional> connection_arguments, - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel -); - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pluggable-transports/util.h b/src/ouiservice/pluggable-transports/util.h deleted file mode 100644 index f0e7b9a71..000000000 --- a/src/ouiservice/pluggable-transports/util.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace ouinet { -namespace ouiservice { -namespace pt { - -/* - * Escape a string by prefixing all $characters with backslashes, as well - * as the backslash character. - */ -inline std::string string_escape(std::string payload, std::string characters) -{ - std::string output; - for (auto c : payload) { - if (c == '\\' || characters.find(c) != std::string::npos) { - output += '\\'; - } - output += c; - } - return output; -} - -/* - * Parse a PT-encoded endpoint: - * - 1.2.3.4:567 - * - [1:2:3:4::5]:678 - */ -inline boost::optional parse_endpoint(std::string endpoint) -{ - size_t pos = endpoint.rfind(':'); - if (pos == std::string::npos) { - return boost::none; - } - int port; - try { - port = std::stoi(endpoint.substr(pos + 1)); - } catch(...) { - return boost::none; - } - if (port < 0 || port > 65535) { - return boost::none; - } - - std::string address_string = endpoint.substr(0, pos); - if ( - address_string.size() > 0 - && address_string[0] == '[' - && address_string[address_string.size() - 1] == ']' - ) { - address_string = address_string.substr(1, address_string.size() - 2); - } - sys::error_code ec; - asio::ip::address address = asio::ip::address::from_string(address_string, ec); - if (ec) { - return boost::none; - } - - return asio::ip::tcp::endpoint(address, (short)port); -} - -inline std::string format_endpoint(asio::ip::tcp::endpoint endpoint) -{ - if (endpoint.address().is_v4()) { - return endpoint.address().to_v4().to_string() + ":" + std::to_string(endpoint.port()); - } else { - return "[" + endpoint.address().to_v6().to_string() + "]:" + std::to_string(endpoint.port()); - } -} - -} // pt namespace -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs2.cpp b/src/ouiservice/pt-obfs2.cpp deleted file mode 100644 index e97391d4a..000000000 --- a/src/ouiservice/pt-obfs2.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "pt-obfs2.h" -#include "pluggable-transports/client-process.h" -#include "pluggable-transports/server-process.h" -#include "pluggable-transports/socks5-client.h" -#include "../logger.h" -#include "../or_throw.h" -#include "../util.h" - -#include - -namespace ouinet { -namespace ouiservice { - -Obfs2OuiServiceServer::Obfs2OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory -): - PtOuiServiceServer(ios), - _endpoint(endpoint), - _state_directory(state_directory) -{} - -std::unique_ptr Obfs2OuiServiceServer::start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal -) { - auto server_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs2", - _endpoint, - destination_endpoint, - std::map(), - _state_directory.string() - ); - - sys::error_code ec; - server_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - return std::move(server_process); -} - - - -static boost::optional parse_endpoint(std::string endpoint) -{ - size_t pos = endpoint.rfind(':'); - if (pos == std::string::npos) { - return boost::none; - } - - int port; - try { - port = std::stoi(endpoint.substr(pos + 1)); - } catch(...) { - return boost::none; - } - sys::error_code ec; - asio::ip::address address = asio::ip::address::from_string(endpoint.substr(0, pos), ec); - if (ec) { - return boost::none; - } - return asio::ip::tcp::endpoint(address, port); -} - -Obfs2OuiServiceClient::Obfs2OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory -): - PtOuiServiceClient(ios), - _endpoint(parse_endpoint(endpoint)), - _state_directory(state_directory) -{} - -std::unique_ptr Obfs2OuiServiceClient::start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal -) { - if (!_endpoint) { - return or_throw>(yield, asio::error::invalid_argument); - } - - auto client_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs2", - _state_directory.string() - ); - - sys::error_code ec; - client_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - if (client_process->connection_method() != pt::ClientProcess::Socks5Connection) { - return or_throw>(yield, asio::error::address_family_not_supported); - } - - return std::move(client_process); -} - -asio::ip::tcp::socket Obfs2OuiServiceClient::connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal -) { - remote_endpoint_string = util::str(*_endpoint); - - return pt::connect_socks5( - transport_endpoint, - *_endpoint, - boost::none, - ios, - yield, - cancel_signal - ); -} - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs2.h b/src/ouiservice/pt-obfs2.h deleted file mode 100644 index 05bf0be7d..000000000 --- a/src/ouiservice/pt-obfs2.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../ouiservice.h" - -#include "pluggable-transports/pt-ouiservice.h" - -namespace ouinet { -namespace ouiservice { - -class Obfs2OuiServiceServer : public pt::PtOuiServiceServer -{ - public: - Obfs2OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory - ); - - protected: - std::unique_ptr start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - asio::ip::tcp::endpoint _endpoint; - fs::path _state_directory; -}; - -class Obfs2OuiServiceClient : public pt::PtOuiServiceClient -{ - public: - Obfs2OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory - ); - - bool verify_endpoint() const { return (bool)_endpoint; } - - protected: - std::unique_ptr start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal - ) override; - asio::ip::tcp::socket connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - boost::optional _endpoint; - fs::path _state_directory; -}; - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs3.cpp b/src/ouiservice/pt-obfs3.cpp deleted file mode 100644 index 859b82fab..000000000 --- a/src/ouiservice/pt-obfs3.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "pt-obfs3.h" -#include "pluggable-transports/client-process.h" -#include "pluggable-transports/server-process.h" -#include "pluggable-transports/socks5-client.h" -#include "../logger.h" -#include "../or_throw.h" -#include "../util.h" - -#include - -namespace ouinet { -namespace ouiservice { - -Obfs3OuiServiceServer::Obfs3OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory -): - PtOuiServiceServer(ios), - _endpoint(endpoint), - _state_directory(state_directory) -{} - -std::unique_ptr Obfs3OuiServiceServer::start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal -) { - auto server_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs3", - _endpoint, - destination_endpoint, - std::map(), - _state_directory.string() - ); - - sys::error_code ec; - server_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - return std::move(server_process); -} - - - -static boost::optional parse_endpoint(std::string endpoint) -{ - size_t pos = endpoint.rfind(':'); - if (pos == std::string::npos) { - return boost::none; - } - - int port; - try { - port = std::stoi(endpoint.substr(pos + 1)); - } catch(...) { - return boost::none; - } - sys::error_code ec; - asio::ip::address address = asio::ip::address::from_string(endpoint.substr(0, pos), ec); - if (ec) { - return boost::none; - } - return asio::ip::tcp::endpoint(address, port); -} - -Obfs3OuiServiceClient::Obfs3OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory -): - PtOuiServiceClient(ios), - _endpoint(parse_endpoint(endpoint)), - _state_directory(state_directory) -{} - -std::unique_ptr Obfs3OuiServiceClient::start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal -) { - if (!_endpoint) { - return or_throw>(yield, asio::error::invalid_argument); - } - - auto client_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs3", - _state_directory.string() - ); - - sys::error_code ec; - client_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - if (client_process->connection_method() != pt::ClientProcess::Socks5Connection) { - return or_throw>(yield, asio::error::address_family_not_supported); - } - - return std::move(client_process); -} - -asio::ip::tcp::socket Obfs3OuiServiceClient::connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal -) { - remote_endpoint_string = util::str(*_endpoint); - - return pt::connect_socks5( - transport_endpoint, - *_endpoint, - boost::none, - ios, - yield, - cancel_signal - ); -} - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs3.h b/src/ouiservice/pt-obfs3.h deleted file mode 100644 index f9d05e682..000000000 --- a/src/ouiservice/pt-obfs3.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../ouiservice.h" - -#include "pluggable-transports/pt-ouiservice.h" - -namespace ouinet { -namespace ouiservice { - -class Obfs3OuiServiceServer : public pt::PtOuiServiceServer -{ - public: - Obfs3OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory - ); - - protected: - std::unique_ptr start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - asio::ip::tcp::endpoint _endpoint; - fs::path _state_directory; -}; - -class Obfs3OuiServiceClient : public pt::PtOuiServiceClient -{ - public: - Obfs3OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory - ); - - bool verify_endpoint() const { return (bool)_endpoint; } - - protected: - std::unique_ptr start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal - ) override; - asio::ip::tcp::socket connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - boost::optional _endpoint; - fs::path _state_directory; -}; - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs4.cpp b/src/ouiservice/pt-obfs4.cpp deleted file mode 100644 index 9f1919c3c..000000000 --- a/src/ouiservice/pt-obfs4.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "pt-obfs4.h" -#include "pluggable-transports/client-process.h" -#include "pluggable-transports/server-process.h" -#include "pluggable-transports/socks5-client.h" -#include "../logger.h" -#include "../or_throw.h" -#include "../util.h" - -#include - -namespace ouinet { -namespace ouiservice { - -Obfs4OuiServiceServer::Obfs4OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory -): - PtOuiServiceServer(ios), - _endpoint(endpoint), - _state_directory(state_directory) -{} - -std::unique_ptr Obfs4OuiServiceServer::start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal -) { - auto server_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs4", - _endpoint, - destination_endpoint, - std::map(), - _state_directory.string() - ); - - sys::error_code ec; - server_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - return std::move(server_process); -} - - - -static void parse_endpoint( - std::string endpoint_string, - boost::optional& endpoint, - std::string& certificate, - std::string& iat_mode -) { - endpoint = boost::none; - std::vector parts; - boost::algorithm::split(parts, endpoint_string, [](char c) { return c == ','; }); - if (parts.size() != 3) { - return; - } - if (parts[1].substr(0, 5) != "cert=") { - return; - } - certificate = parts[1].substr(5); - if (parts[2].substr(0, 9) != "iat-mode=") { - return; - } - iat_mode = parts[2].substr(9); - - - size_t pos = parts[0].rfind(':'); - if (pos == std::string::npos) { - return; - } - - int port; - try { - port = std::stoi(parts[0].substr(pos + 1)); - } catch(...) { - return; - } - sys::error_code ec; - asio::ip::address address = asio::ip::address::from_string(parts[0].substr(0, pos), ec); - if (ec) { - return; - } - endpoint = asio::ip::tcp::endpoint(address, port); -} - -Obfs4OuiServiceClient::Obfs4OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory -): - PtOuiServiceClient(ios), - _state_directory(state_directory) -{ - parse_endpoint(endpoint, _endpoint, _certificate, _iat_mode); -} - -std::unique_ptr Obfs4OuiServiceClient::start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal -) { - if (!_endpoint) { - return or_throw>(yield, asio::error::invalid_argument); - } - - auto client_process = std::make_unique( - ios, - "obfs4proxy", - std::vector(), - "obfs4", - _state_directory.string() - ); - - sys::error_code ec; - client_process->start(yield[ec], cancel_signal); - - if (ec) { - return or_throw>(yield, ec); - } - - if (client_process->connection_method() != pt::ClientProcess::Socks5Connection) { - return or_throw>(yield, asio::error::address_family_not_supported); - } - - return std::move(client_process); -} - -asio::ip::tcp::socket Obfs4OuiServiceClient::connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal -) { - std::map connection_arguments; - connection_arguments["cert"] = _certificate; - connection_arguments["iat-mode"] = _iat_mode; - - remote_endpoint_string = util::str(*_endpoint); - - return pt::connect_socks5( - transport_endpoint, - *_endpoint, - connection_arguments, - ios, - yield, - cancel_signal - ); -} - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/pt-obfs4.h b/src/ouiservice/pt-obfs4.h deleted file mode 100644 index a44f13050..000000000 --- a/src/ouiservice/pt-obfs4.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../ouiservice.h" - -#include "pluggable-transports/pt-ouiservice.h" - -namespace ouinet { -namespace ouiservice { - -class Obfs4OuiServiceServer : public pt::PtOuiServiceServer -{ - public: - Obfs4OuiServiceServer( - asio::io_service& ios, - asio::ip::tcp::endpoint endpoint, - fs::path state_directory - ); - - protected: - std::unique_ptr start_server_process( - asio::io_service& ios, - asio::ip::tcp::endpoint destination_endpoint, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - asio::ip::tcp::endpoint _endpoint; - fs::path _state_directory; -}; - -class Obfs4OuiServiceClient : public pt::PtOuiServiceClient -{ - public: - Obfs4OuiServiceClient( - asio::io_service& ios, - std::string endpoint, - fs::path state_directory - ); - - bool verify_endpoint() const { return (bool)_endpoint; } - - protected: - std::unique_ptr start_client_process( - asio::io_service& ios, - asio::yield_context yield, - Signal& cancel_signal - ) override; - asio::ip::tcp::socket connect_through_transport( - asio::io_service& ios, - asio::ip::tcp::endpoint transport_endpoint, - std::string& remote_endpoint_string, - asio::yield_context yield, - Signal& cancel_signal - ) override; - - private: - boost::optional _endpoint; - std::string _certificate; - std::string _iat_mode; - fs::path _state_directory; -}; - -} // ouiservice namespace -} // ouinet namespace diff --git a/src/ouiservice/tcp.cpp b/src/ouiservice/tcp.cpp index 4f3249999..6db3756ba 100644 --- a/src/ouiservice/tcp.cpp +++ b/src/ouiservice/tcp.cpp @@ -67,39 +67,14 @@ GenericStream TcpOuiServiceServer::accept(asio::yield_context yield) return GenericStream(std::move(socket), tcp_shutter); } -static boost::optional parse_endpoint(std::string endpoint) -{ - size_t pos = endpoint.rfind(':'); - if (pos == std::string::npos) { - return boost::none; - } - - int port; - try { - port = std::stoi(endpoint.substr(pos + 1)); - } catch(...) { - return boost::none; - } - sys::error_code ec; - asio::ip::address address = asio::ip::address::from_string(endpoint.substr(0, pos), ec); - if (ec) { - return boost::none; - } - return asio::ip::tcp::endpoint(address, port); -} - -TcpOuiServiceClient::TcpOuiServiceClient(asio::io_service& ios, std::string endpoint): +TcpOuiServiceClient::TcpOuiServiceClient(asio::io_service& ios, asio::ip::tcp::endpoint endpoint): _ios(ios), - _endpoint(parse_endpoint(endpoint)) + _endpoint(endpoint) {} OuiServiceImplementationClient::ConnectInfo TcpOuiServiceClient::connect(asio::yield_context yield, Signal& cancel) { - if (!_endpoint) { - return or_throw(yield, asio::error::invalid_argument); - } - sys::error_code ec; asio::ip::tcp::socket socket(_ios); @@ -110,7 +85,7 @@ TcpOuiServiceClient::connect(asio::yield_context yield, Signal& cancel) socket.close(ec); }); - socket.async_connect(*_endpoint, yield[ec]); + socket.async_connect(_endpoint, yield[ec]); if (ec) { return or_throw(yield, ec); @@ -123,7 +98,7 @@ TcpOuiServiceClient::connect(asio::yield_context yield, Signal& cancel) }; return ConnectInfo{ GenericStream(std::move(socket), tcp_shutter) - , util::str(*_endpoint) }; + , util::str(_endpoint) }; } } // ouiservice namespace diff --git a/src/ouiservice/tcp.h b/src/ouiservice/tcp.h index 9308ede29..c4db6b81d 100644 --- a/src/ouiservice/tcp.h +++ b/src/ouiservice/tcp.h @@ -2,7 +2,6 @@ #include #include -#include #include "../ouiservice.h" @@ -31,7 +30,7 @@ class TcpOuiServiceClient : public OuiServiceImplementationClient using ConnectInfo = OuiServiceImplementationClient::ConnectInfo; public: - TcpOuiServiceClient(asio::io_service& ios, std::string endpoint); + TcpOuiServiceClient(asio::io_service& ios, asio::ip::tcp::endpoint endpoint); // Tcp clients don't have any internal async IO to be started/stopped. void start(asio::yield_context yield) override {} @@ -40,11 +39,9 @@ class TcpOuiServiceClient : public OuiServiceImplementationClient ConnectInfo connect( asio::yield_context yield , Signal& cancel) override; - bool verify_endpoint() const { return (bool)_endpoint; } - private: asio::io_service& _ios; - boost::optional _endpoint; + asio::ip::tcp::endpoint _endpoint; }; } // ouiservice namespace diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 09b6a61da..93266590d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -78,26 +78,6 @@ add_executable(test-logger "test_logger.cpp" target_link_libraries(test-logger ${Boost_LIBRARIES}) -###################################################################### -add_executable(test-oui-server "ouiservice-server.cpp" - "../src/asio.cpp" - "../src/logger.cpp" - "../src/ouiservice.cpp" - "../src/ouiservice/tcp.cpp" -) - -target_link_libraries(test-oui-server ${Boost_LIBRARIES}) - -###################################################################### -add_executable(test-oui-client "ouiservice-client.cpp" - "../src/asio.cpp" - "../src/logger.cpp" - "../src/ouiservice.cpp" - "../src/ouiservice/tcp.cpp" -) - -target_link_libraries(test-oui-client ${Boost_LIBRARIES}) - ###################################################################### add_executable(test-http-util "test_http_util.cpp" "../src/asio.cpp") target_include_directories(test-http-util PUBLIC "${Boost_INCLUDE_DIR}") diff --git a/test/ouiservice-client.cpp b/test/ouiservice-client.cpp deleted file mode 100644 index 9f37db0f6..000000000 --- a/test/ouiservice-client.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -#include "namespaces.h" -#include "ouiservice.h" -#include "ouiservice/tcp.h" - -//#include "util/crypto.h" - -using namespace std; -using namespace ouinet; - -int main(int argc, const char* argv[]) -{ -// util::crypto_init(); - - if (argc < 2) { - std::cerr << "Usage: ouiservice-client \n"; - return 1; - } - std::string message(argv[1]); - message += "\n"; - - asio::io_service ios; - - OuiServiceClient client(ios); - - client.add(make_unique(ios, "127.0.0.1:10203")); - - asio::spawn(ios, [&ios, &client, &message] (asio::yield_context yield) { - sys::error_code ec; - client.start(yield[ec]); - - if (ec) { - std::cerr << "Failed to setup ouiservice client: " << ec.message() << endl; - return; - } - - Signal cancel; - auto out = client.connect(yield[ec], cancel); - if (ec) { - std::cerr << "Failed to connect to server: " << ec.message() << endl; - return; - } - - GenericStream connection = std::move(out.connection); - while (message.size()) { - size_t written = connection.async_write_some(asio::const_buffers_1(message.data(), message.size()), yield[ec]); - if (ec || !written) { - return; - } - message = message.substr(written); - } - - std::string line; - while (true) { - char c; - size_t read = connection.async_read_some(asio::mutable_buffers_1(&c, 1), yield[ec]); - if (ec || !read) { - return; - } - - line += c; - if (c == '\n') { - std::cerr << line; - break; - } - } - }); - - ios.run(); - return 0; -} diff --git a/test/ouiservice-server.cpp b/test/ouiservice-server.cpp deleted file mode 100644 index 10b0c3267..000000000 --- a/test/ouiservice-server.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include - -#include "namespaces.h" -#include "ouiservice.h" -#include "ouiservice/tcp.h" - -//#include "util/crypto.h" - -using namespace std; -using namespace ouinet; - -int main(int argc, const char* argv[]) -{ -// util::crypto_init(); - - asio::io_service ios; - - OuiServiceServer server(ios); - - asio::ip::tcp::endpoint endpoint(asio::ip::address::from_string("127.0.0.1"), 10203); - server.add(make_unique(ios, endpoint)); - - asio::spawn(ios, [&ios, &server] (asio::yield_context yield) { - sys::error_code ec; - server.start_listen(yield[ec]); - - if (ec) { - std::cerr << "Failed to setup ouiservice server: " << ec.message() << endl; - return; - } - - std::cout << "Listening" << endl; - - while (true) { - GenericStream connection = server.accept(yield[ec]); - if (ec) { - break; - } - - asio::spawn(ios, [connection = std::move(connection)] (asio::yield_context yield) mutable { - sys::error_code ec; - std::string line; - while (true) { - char c; - size_t read = connection.async_read_some(asio::mutable_buffers_1(&c, 1), yield[ec]); - if (ec || !read) { - return; - } - - line += c; - if (c == '\n') { - std::cerr << line; - while (line.size()) { - size_t written = connection.async_write_some(asio::const_buffers_1(line.data(), line.size()), yield[ec]); - if (ec || !written) { - return; - } - line = line.substr(written); - } - } - } - }); - } - }); - - ios.run(); - return 0; -}