diff --git a/CMakeLists.txt b/CMakeLists.txt index a3d12afce..f206aee65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -428,24 +428,6 @@ find_package(Threads) if (APPLE AND NOT IOS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default") - if (NOT OpenSSL_DIR) - EXECUTE_PROCESS(COMMAND brew --prefix openssl - OUTPUT_VARIABLE OPENSSL_ROOT_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) - message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}") - endif() -endif() - -if(BUILD_STATIC_DEPS) - # SSL::* targets already set up -else() - find_package(OpenSSL REQUIRED) -endif() -message(STATUS "Using OpenSSL include dir at ${OPENSSL_INCLUDE_DIR}") - -if(MINGW) - # OpenSSL doesn't seem to properly set up its dependencies on Windows, leading to linking errors - target_link_libraries(OpenSSL::Crypto INTERFACE ws2_32) endif() add_definition_if_library_exists(c memset_s "string.h" HAVE_MEMSET_S) @@ -794,7 +776,7 @@ set(Boost_USE_MULTITHREADED TRUE) # Needed for macOS, at least, and won't hurt e if(BUILD_STATIC_DEPS) # StaticBuild.cmake sets Boost targets up for us else() - find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system thread serialization program_options) + find_package(Boost 1.62 QUIET REQUIRED COMPONENTS system thread serialization program_options) endif() set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES}) @@ -802,12 +784,6 @@ if(NOT Boost_FOUND) message(FATAL_ERROR "Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=1.58) or the equivalent") elseif(Boost_FOUND) message(STATUS "Found Boost Version: ${Boost_VERSION}") - if (OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1 AND ( - Boost_VERSION VERSION_LESS 1.62.0 OR (Boost_VERSION VERSION_GREATER 100000 AND Boost_VERSION VERSION_LESS 106200))) - message(FATAL_ERROR "Boost ${Boost_VERSION} (older than 1.62) is too old to link with OpenSSL ${OPENSSL_VERSION} (1.1 or newer) found at ${OPENSSL_INCLUDE_DIR} and ${OPENSSL_LIBRARIES}. " - "Update Boost or install OpenSSL 1.0 and set path to it when running cmake: " - "cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0'") - endif() endif() # Interface target for random extra system libraries that we need to link everything against diff --git a/README.md b/README.md index d55ef3a8e..3a0bf714d 100644 --- a/README.md +++ b/README.md @@ -43,18 +43,14 @@ library archives (`.a`). | CMake | 3.10 | NO | `cmake` | `cmake` | `cmake` | NO | | | pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | | | Boost | 1.65 | NO | `libboost-all-dev`[2] | `boost` | `boost-devel` | NO | C++ libraries | -| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum | | libzmq | 4.3.0 | YES | `libzmq3-dev` | `zeromq` | `zeromq-devel` | NO | ZeroMQ library | | sqlite3 | ? | YES | `libsqlite3-dev` | `sqlite` | `sqlite-devel` | NO | Oxen Name System | -| libunbound | 1.4.16 | NO | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver | | libsodium | 1.0.9 | YES | `libsodium-dev` | `libsodium` | `libsodium-devel` | NO | cryptography | -| libcurl | 4.0 | NO | `libcurl4-openssl-dev` | `curl` | `curl-devel` | NO | HTTP RPC | +| libcurl | 4.0 | NO | `libcurl4-dev` | `curl` | `curl-devel` | NO | HTTP RPC | | libuv (Win) | any | NO | (Windows only) | -- | -- | NO | RPC event loop | | libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces | | liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind | | libreadline | 6.3.0 | NO | `libreadline-dev` | `readline` | `readline-devel` | YES | Input editing | -| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit | -| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing | | Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | | Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | | Qt tools | 5.x | NO | `qttools5-dev` | `qt5-tools` | `qt5-linguist` | YES | Translations | @@ -73,14 +69,14 @@ breakdown of the minimum set of required boost packages. Install all dependencies at once on Debian/Ubuntu: ``` -sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev libsqlite3-dev libcurl4-openssl-dev +sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libzmq3-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev doxygen graphviz libpgm-dev libsqlite3-dev libcurl4-dev ``` Install all dependencies at once on macOS with the provided Brewfile: ``` brew update && brew bundle --file=contrib/brew/Brewfile ``` FreeBSD one liner for required to build dependencies -```pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium sqlite3 openssl unbound``` +```pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium sqlite3``` ### Build instructions @@ -190,13 +186,13 @@ application. To build for 64-bit Windows: ```bash - pacman -S git mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-sqlite3 mingw-w64-x86_64-unbound + pacman -S git mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-sqlite3 ``` To build for 32-bit Windows: ```bash - pacman -S git mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi mingw-w64-i686-sqlite3 mingw-w64-i686-unbound + pacman -S git mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi mingw-w64-i686-sqlite3 ``` * Close and reopen the MSYS MinGW shell via `MSYS2 MinGW 64-bit` shortcut on diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake index 011739c00..07e252764 100644 --- a/cmake/StaticBuild.cmake +++ b/cmake/StaticBuild.cmake @@ -5,26 +5,6 @@ set(LOCAL_MIRROR "" CACHE STRING "local mirror path/URL for lib downloads") -set(OPENSSL_VERSION 3.0.2 CACHE STRING "openssl version") -set(OPENSSL_MIRROR ${LOCAL_MIRROR} https://www.openssl.org/source CACHE STRING "openssl download mirror(s)") -set(OPENSSL_SOURCE openssl-${OPENSSL_VERSION}.tar.gz) -set(OPENSSL_HASH SHA256=98e91ccead4d4756ae3c9cde5e09191a8e586d9f4d50838e7ec09d6411dfdb63 - CACHE STRING "openssl source hash") - -set(EXPAT_VERSION 2.4.4 CACHE STRING "expat version") -string(REPLACE "." "_" EXPAT_TAG "R_${EXPAT_VERSION}") -set(EXPAT_MIRROR ${LOCAL_MIRROR} https://github.com/libexpat/libexpat/releases/download/${EXPAT_TAG} - CACHE STRING "expat download mirror(s)") -set(EXPAT_SOURCE expat-${EXPAT_VERSION}.tar.xz) -set(EXPAT_HASH SHA512=c88a82f4732e27340eb9480c082bcc909b0284e16b368ee9feeb4e2dd058e8f7c42fd48feacd5272cc76cb78bd183df33eb5d0b135fdd1d3c493cb156572ab76 - CACHE STRING "expat source hash") - -set(UNBOUND_VERSION 1.15.0 CACHE STRING "unbound version") -set(UNBOUND_MIRROR ${LOCAL_MIRROR} https://nlnetlabs.nl/downloads/unbound CACHE STRING "unbound download mirror(s)") -set(UNBOUND_SOURCE unbound-${UNBOUND_VERSION}.tar.gz) -set(UNBOUND_HASH SHA256=a480dc6c8937447b98d161fe911ffc76cfaffa2da18788781314e81339f1126f - CACHE STRING "unbound source hash") - set(BOOST_VERSION 1.79.0 CACHE STRING "boost version") set(BOOST_MIRROR ${LOCAL_MIRROR} https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source CACHE STRING "boost download mirror(s)") @@ -141,16 +121,12 @@ if (ANDROID) endif() if(CMAKE_ANDROID_ARCH_ABI MATCHES x86_64) set(android_clang x86_64-linux-android${ANDROID_PLATFORM_LEVEL}-clang) - set(openssl_machine android-x86_64) elseif(CMAKE_ANDROID_ARCH_ABI MATCHES x86) set(android_clang i686-linux-android${ANDROID_PLATFORM_LEVEL}-clang) - set(openssl_machine android-x86) elseif(CMAKE_ANDROID_ARCH_ABI MATCHES armeabi-v7a) set(android_clang armv7a-linux-androideabi${ANDROID_PLATFORM_LEVEL}-clang) - set(openssl_machine android-arm) elseif(CMAKE_ANDROID_ARCH_ABI MATCHES arm64-v8a) set(android_clang aarch64-linux-android${ANDROID_PLATFORM_LEVEL}-clang) - set(openssl_machine android-arm64) else() message(FATAL_ERROR "Don't know how to build for android arch abi ${CMAKE_ANDROID_ARCH_ABI}") endif() @@ -276,81 +252,6 @@ add_static_target(zlib zlib_external libz.a) -set(openssl_configure_extra) -set(openssl_system_env "") -set(openssl_cc "${deps_cc}") -if(CMAKE_CROSSCOMPILING) - if(ARCH_TRIPLET STREQUAL x86_64-w64-mingw32) - set(openssl_configure_extra mingw64) - set(openssl_system_env RC=${CMAKE_RC_COMPILER}) - elseif(ARCH_TRIPLET STREQUAL i686-w64-mingw32) - set(openssl_configure_extra mingw) - set(openssl_system_env RC=${CMAKE_RC_COMPILER}) - elseif(ANDROID) - set(openssl_configure_extra ${openssl_machine} -D__ANDROID_API__=21) - set(openssl_system_env ${cross_extra}) - list(APPEND openssl_system_env "ANDROID_NDK_ROOT=${ANDROID_NDK}") - list(APPEND openssl_system_env "PATH=${ANDROID_TOOLCHAIN_ROOT}/bin:${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/linux-x86_64/bin:$ENV{PATH}") - set(openssl_extra_opts no-asm) - elseif(IOS) - get_filename_component(apple_toolchain "${CMAKE_C_COMPILER}" DIRECTORY) - get_filename_component(apple_sdk "${CMAKE_OSX_SYSROOT}" NAME) - if(NOT ${apple_toolchain} MATCHES Xcode OR NOT ${apple_sdk} MATCHES "iPhone(OS|Simulator)") - message(FATAL_ERROR "didn't find your toolchain and sdk correctly from ${CMAKE_C_COMPILER}/${CMAKE_OSX_SYSROOT}: found toolchain=${apple_toolchain}, sdk=${apple_sdk}") - endif() - set(openssl_system_env CROSS_COMPILE=${apple_toolchain}/ CROSS_TOP=${CMAKE_DEVELOPER_ROOT} CROSS_SDK=${apple_sdk}) - set(openssl_configure ./Configure iphoneos-cross) - set(openssl_cc "clang") - endif() -endif() -build_external(openssl - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${openssl_cc} "CFLAGS=${deps_CFLAGS}" ${openssl_system_env} - ./Configure ${openssl_configure_extra} --prefix=${DEPS_DESTDIR} --libdir=lib ${openssl_extra_opts} - no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost - no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl3 - no-static-engine no-tests no-weak-ssl-ciphers no-zlib-dynamic - BUILD_COMMAND ${CMAKE_COMMAND} -E env CC=${openssl_cc} ${openssl_system_env} make - INSTALL_COMMAND make install_sw - BUILD_BYPRODUCTS - ${DEPS_DESTDIR}/lib/libssl.a ${DEPS_DESTDIR}/lib/libcrypto.a - ${DEPS_DESTDIR}/include/openssl/ssl.h ${DEPS_DESTDIR}/include/openssl/crypto.h -) -add_static_target(OpenSSL::SSL openssl_external libssl.a) -add_static_target(OpenSSL::Crypto openssl_external libcrypto.a) -set(OPENSSL_INCLUDE_DIR ${DEPS_DESTDIR}/include) - - - -build_external(expat - CONFIGURE_COMMAND ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --enable-static - --disable-shared --with-pic --without-examples --without-tests --without-docbook --without-xmlwf - "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" -) -add_static_target(expat expat_external libexpat.a) - - -set(unbound_extra) -if(APPLE AND IOS) - # I have no idea why this is necessary: without this it runs `clang -E` which should work, but - # doesn't because... hurray ios is wonderful? - set(unbound_extra CPP=cpp) -endif() -build_external(unbound - DEPENDS openssl_external expat_external - CONFIGURE_COMMAND ./configure ${cross_host} ${cross_extra} --prefix=${DEPS_DESTDIR} --disable-shared - --enable-static --with-libunbound-only --with-pic --disable-gost - --$,enable,disable>-flto --with-ssl=${DEPS_DESTDIR} - --with-libexpat=${DEPS_DESTDIR} - "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" ${unbound_extra} -) -add_static_target(libunbound unbound_external libunbound.a) -target_link_libraries(libunbound INTERFACE OpenSSL::SSL OpenSSL::Crypto) -if(WIN32) - target_link_libraries(libunbound INTERFACE ws2_32 crypt32 iphlpapi) -endif() - - - set(boost_threadapi "pthread") set(boost_bootstrap_cxx "--cxx=${deps_cxx}") set(boost_toolset "") @@ -631,16 +532,12 @@ set_target_properties(libzmq PROPERTIES set(curl_extra) -if(WIN32) - set(curl_ssl_opts --without-ssl --with-schannel) -elseif(APPLE) - set(curl_ssl_opts --without-ssl --with-secure-transport) +if(APPLE) if(IOS) # This CPP crap shouldn't be necessary but is because Apple's toolchain is trash set(curl_extra "LDFLAGS=-L${DEPS_DESTDIR}/lib -isysroot ${CMAKE_OSX_SYSROOT}" CPP=cpp) endif() else() - set(curl_ssl_opts --with-ssl=${DEPS_DESTDIR}) set(curl_extra "LIBS=-pthread") endif() @@ -672,7 +569,7 @@ foreach(curl_arch ${curl_arches}) build_external(curl TARGET_SUFFIX ${curl_target_suffix} - DEPENDS openssl_external zlib_external + DEPENDS zlib_external CONFIGURE_COMMAND ./configure ${cross_host} ${cross_extra} --prefix=${curl_prefix} --disable-shared --enable-static --disable-ares --disable-ftp --disable-ldap --disable-laps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb @@ -680,7 +577,8 @@ foreach(curl_arch ${curl_arches}) --enable-ipv6 --disable-threaded-resolver --disable-pthreads --disable-verbose --disable-sspi --enable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --enable-http-auth --enable-doh --disable-mime --enable-dateparse --disable-netrc --without-libidn2 - --disable-progress-meter --without-brotli --with-zlib=${DEPS_DESTDIR} ${curl_ssl_opts} + --disable-progress-meter --without-brotli --with-zlib=${DEPS_DESTDIR} + --without-ssl --without-schannel --without-secure-transport --without-librtmp --disable-versioned-symbols --enable-hidden-symbols --without-zsh-functions-dir --without-fish-functions-dir "CC=${deps_cc}" "CFLAGS=${deps_noarch_CFLAGS}${cflags_extra}" ${curl_extra} @@ -710,9 +608,9 @@ endif() add_static_target(CURL::libcurl curl_external libcurl.a) set(libcurl_link_libs zlib) if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw) - list(APPEND libcurl_link_libs crypt32) + list(APPEND libcurl_link_libs ws2_32) elseif(APPLE) - list(APPEND libcurl_link_libs "-framework Security") + list(APPEND libcurl_link_libs "-framework SystemConfiguration") endif() set_target_properties(CURL::libcurl PROPERTIES INTERFACE_LINK_LIBRARIES "${libcurl_link_libs}" diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 247dfd79c..9cf808ab3 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -32,7 +32,6 @@ add_library(common base58.cpp combinator.cpp command_line.cpp - dns_utils.cpp error.cpp expect.cpp file.cpp @@ -68,6 +67,5 @@ target_link_libraries(common filesystem fmt::fmt PRIVATE - libunbound sodium extra) diff --git a/src/common/common_fwd.h b/src/common/common_fwd.h index 7eaa6cdee..5062365da 100644 --- a/src/common/common_fwd.h +++ b/src/common/common_fwd.h @@ -32,7 +32,6 @@ namespace tools { - class DNSResolver; struct login; class password_container; class t_http_connection; diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp deleted file mode 100644 index b73760ebd..000000000 --- a/src/common/dns_utils.cpp +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (c) 2014-2019, The Monero Project -// Copyright (c) 2018, The Loki Project -// -// 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. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 "common/dns_utils.h" -// check local first (in the event of static or in-source compilation of libunbound) -#include "common/string_util.h" -#include "unbound.h" - -#include -#include -#include -#include -#include -#include "epee/misc_log_ex.h" -#include "common/threadpool.h" -#include "crypto/crypto.h" - -#undef OXEN_DEFAULT_LOG_CATEGORY -#define OXEN_DEFAULT_LOG_CATEGORY "net.dns" - -using namespace std::literals; -static constexpr std::array DEFAULT_DNS_PUBLIC_ADDR = -{ - "194.150.168.168"sv, // CCC (Germany) - "80.67.169.40"sv, // FDN (France) - "89.233.43.71"sv, // http://censurfridns.dk (Denmark) - "109.69.8.51"sv, // punCAT (Spain) - "193.58.251.251"sv, // SkyDNS (Russia) -}; - -namespace -{ - -/* - * The following two functions were taken from unbound-anchor.c, from - * the unbound library packaged with this source. The license and source - * can be found in $PROJECT_ROOT/external/unbound - */ - -/* Cert builtin commented out until it's used, as the compiler complains - -// return the built in root update certificate -static const char* -get_builtin_cert(void) -{ - return -// The ICANN CA fetched at 24 Sep 2010. Valid to 2028 -"-----BEGIN CERTIFICATE-----\n" -"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n" -"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n" -"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n" -"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n" -"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n" -"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n" -"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n" -"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n" -"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n" -"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n" -"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n" -"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n" -"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n" -"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n" -"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n" -"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n" -"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n" -"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n" -"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n" -"-----END CERTIFICATE-----\n" - ; -} -*/ - -/** return the built in root DS trust anchor */ -constexpr auto get_builtin_ds() -{ - return std::array{ - ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n", - ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n", - }; -} - -/************************************************************ - ************************************************************ - ***********************************************************/ - -} // anonymous namespace - -namespace tools -{ - -static constexpr const char *get_record_name(int record_type) -{ - switch (record_type) - { - case DNS_TYPE_A: return "A"; - case DNS_TYPE_TXT: return "TXT"; - case DNS_TYPE_AAAA: return "AAAA"; - default: return "unknown"; - } -} - -// fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc -std::optional ipv4_to_string(const char* src, size_t len) -{ - if (len < 4) - { - MERROR("Invalid IPv4 address: " << std::string(src, len)); - return std::nullopt; - } - - std::stringstream ss; - unsigned int bytes[4]; - for (int i = 0; i < 4; i++) - { - unsigned char a = src[i]; - bytes[i] = a; - } - ss << bytes[0] << "." - << bytes[1] << "." - << bytes[2] << "." - << bytes[3]; - return ss.str(); -} - -// this obviously will need to change, but is here to reflect the above -// stop-gap measure and to make the tests pass at least... -std::optional ipv6_to_string(const char* src, size_t len) -{ - if (len < 8) - { - MERROR("Invalid IPv4 address: " << std::string(src, len)); - return std::nullopt; - } - - std::stringstream ss; - unsigned int bytes[8]; - for (int i = 0; i < 8; i++) - { - unsigned char a = src[i]; - bytes[i] = a; - } - ss << bytes[0] << ":" - << bytes[1] << ":" - << bytes[2] << ":" - << bytes[3] << ":" - << bytes[4] << ":" - << bytes[5] << ":" - << bytes[6] << ":" - << bytes[7]; - return ss.str(); -} - -std::optional txt_to_string(const char* src, size_t len) -{ - if (len == 0) - return std::nullopt; - return std::string(src+1, len-1); -} - -void ub_ctx_deleter::operator()(ub_ctx* ctx) { - ub_ctx_delete(ctx); -} - -namespace { - -struct ub_result_deleter { - void operator()(ub_result* result) { - ub_resolve_free(result); - } -}; - -using ub_result_ptr = std::unique_ptr; - -void add_anchors(ub_ctx *ctx) -{ - for (const char* ds : get_builtin_ds()) - { - MINFO("adding trust anchor: " << *ds); - ub_ctx_add_ta(ctx, const_cast(ds)); - } -} - -} // anonymous namespace - -DNSResolver::DNSResolver() -{ - int use_dns_public = 0; - std::vector dns_public_addr; - const char *DNS_PUBLIC = getenv("DNS_PUBLIC"); - if (DNS_PUBLIC) - { - dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC); - if (!dns_public_addr.empty()) - { - MGINFO("Using public DNS server(s): " << tools::join(", ", dns_public_addr) << " (TCP)"); - use_dns_public = 1; - } - else - { - MERROR("Failed to parse DNS_PUBLIC"); - } - } - - // init libunbound context - m_ctx = ub_ctx_create(); - - if (use_dns_public) - { - for (const auto &ip: dns_public_addr) - ub_ctx_set_fwd(m_ctx, ip.c_str()); - ub_ctx_set_option(m_ctx, "do-udp:", "no"); - ub_ctx_set_option(m_ctx, "do-tcp:", "yes"); - } - else { - // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent - ub_ctx_resolvconf(m_ctx, NULL); - ub_ctx_hosts(m_ctx, NULL); - } - - add_anchors(m_ctx); - - if (!DNS_PUBLIC) - { - // TODO(oxen): Don't probe moneropulse for Loki -#if 0 - // if no DNS_PUBLIC specified, we try a lookup to what we know - // should be a valid DNSSEC record, and switch to known good - // DNSSEC resolvers if verification fails - bool available, valid; - static const char *probe_hostname = "updates.moneropulse.org"; - auto records = get_txt_record(probe_hostname, available, valid); - if (!valid) - { - MINFO("Failed to verify DNSSEC record from " << probe_hostname << ", falling back to TCP with well known DNSSEC resolvers"); - ub_ctx_delete(m_ctx); - m_ctx = ub_ctx_create(); - add_anchors(m_ctx); - for (const auto &ip: DEFAULT_DNS_PUBLIC_ADDR) - ub_ctx_set_fwd(m_ctx, string_copy(ip)); - ub_ctx_set_option(m_ctx, string_copy("do-udp:"), string_copy("no")); - ub_ctx_set_option(m_ctx, string_copy("do-tcp:"), string_copy("yes")); - } -#endif - } -} - -std::vector DNSResolver::get_record(const std::string& url, int record_type, std::optional (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid) -{ - std::vector addresses; - dnssec_available = false; - dnssec_valid = false; - - if (url.find('.') == std::string::npos) - { - return addresses; - } - - ub_result* result_raw = nullptr; - // call DNS resolver, blocking. if return value not zero, something went wrong - if (!ub_resolve(m_ctx, url.c_str(), record_type, DNS_CLASS_IN, &result_raw)) - { - // destructor takes care of cleanup - ub_result_ptr result{result_raw}; - - dnssec_available = (result->secure || result->bogus); - dnssec_valid = result->secure && !result->bogus; - if (result->havedata) - { - for (size_t i=0; result->data[i] != NULL; i++) - { - if (auto res = (*reader)(result->data[i], result->len[i])) - { - MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url); - addresses.push_back(*res); - } - } - } - } - - return addresses; -} - -std::vector DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid) -{ - return get_record(url, DNS_TYPE_A, ipv4_to_string, dnssec_available, dnssec_valid); -} - -std::vector DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid) -{ - return get_record(url, DNS_TYPE_AAAA, ipv6_to_string, dnssec_available, dnssec_valid); -} - -std::vector DNSResolver::get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid) -{ - return get_record(url, DNS_TYPE_TXT, txt_to_string, dnssec_available, dnssec_valid); -} - -namespace { - // Data pack that we pass into the unbound callback: - struct dns_results { - int& all_done; - const std::string& hostname; - const char* record_name; - std::vector& results; - std::optional (*reader)(const char*, size_t); - int async_id{0}; - bool done{false}; - bool dnssec; - bool dnssec_required; - - dns_results(int& a, const std::string& h, const char* rn, std::vector& r, std::optional (*rdr)(const char*, size_t), bool dnssec, bool dnssec_req) - : all_done{a}, hostname{h}, record_name{rn}, results{r}, reader{rdr}, dnssec{dnssec}, dnssec_required{dnssec_req} - {} - }; -} - -extern "C" void DNSResolver_async_callback(void* data, int err, ub_result* result_raw) -{ - ub_result_ptr result{result_raw}; - auto &res = *static_cast(data); - res.all_done++; - res.done = true; - if (err) - MWARNING("resolution of " << res.hostname << " failed: " << ub_strerror(err)); - else if ((res.dnssec || res.dnssec_required) && result->bogus) - MWARNING("resolution of " << res.hostname << " failed DNSSEC validation: " << result->why_bogus); - else if (res.dnssec_required && !result->secure) - MWARNING("resolution of " << res.hostname << " failed: DNSSEC validate is required but is not available"); - else if (result->havedata) - { - for (size_t i = 0; result->data[i] != NULL; i++) - { - if (auto r = (*res.reader)(result->data[i], result->len[i])) - { - MINFO("Found \"" << *r << "\" in " << res.record_name << " record for " << res.hostname); - res.results.push_back(*r); - } - } - } -} - -std::vector> DNSResolver::get_many(int type, const std::vector& hostnames, std::chrono::milliseconds timeout, bool dnssec, bool dnssec_required) -{ - auto* reader = type == DNS_TYPE_A ? ipv4_to_string : type == DNS_TYPE_AAAA ? ipv6_to_string : type == DNS_TYPE_TXT ? txt_to_string : nullptr; - if (!reader) - throw std::invalid_argument("Invalid lookup type: " + std::to_string(type)); - - std::vector> results; - if (hostnames.empty()) - return results; - - int num_done = 0; - std::vector result_packs; - results.reserve(hostnames.size()); - result_packs.reserve(hostnames.size()); - ub_ctx_async(m_ctx, true); // Tells libunbound to use a thread instead of a fork - - // Initiate lookups: - for (auto& host : hostnames) - { - auto& pack = result_packs.emplace_back(num_done, host, get_record_name(type), results.emplace_back(), reader, dnssec, dnssec_required); - int err = ub_resolve_async(m_ctx, host.c_str(), type, DNS_CLASS_IN, static_cast(&pack), DNSResolver_async_callback, &pack.async_id); - if (err) - { - MWARNING("unable to initiate lookup for " << host << ": " << ub_strerror(err)); - num_done++; - pack.done = true; - } - } - - // Wait for results - auto expiry = std::chrono::steady_clock::now() + timeout; - while (num_done < (int)results.size() && std::chrono::steady_clock::now() < expiry) - { - std::this_thread::sleep_for(5ms); - int err = ub_process(m_ctx); - if (err) - { - MWARNING("ub_process returned an error while waiting for async results: " << ub_strerror(err)); - break; - } - } - - // Cancel any outstanding requests - for (auto& pack : result_packs) - { - if (!pack.done) - ub_cancel(m_ctx, pack.async_id); - } - - return results; -} - -std::string DNSResolver::get_dns_format_from_oa_address(std::string_view addr_v) -{ - std::string addr{addr_v}; - auto first_at = addr.find("@"); - if (first_at == std::string::npos) - return addr; - - // convert name@domain.tld to name.domain.tld - addr.replace(first_at, 1, "."); - - return addr; -} - -DNSResolver& DNSResolver::instance() -{ - static DNSResolver staticInstance; - return staticInstance; -} - -DNSResolver DNSResolver::create() -{ - return DNSResolver(); -} - -namespace dns_utils -{ - -//----------------------------------------------------------------------- -// TODO: parse the string in a less stupid way, probably with regex -std::string address_from_txt_record(std::string_view s) -{ - // make sure the txt record has the addr_type and find it - constexpr auto addr_type = "oa1:xmr"sv; - if (auto pos = s.find(addr_type); pos != std::string_view::npos) - s.remove_prefix(pos + addr_type.size()); // remove it and everything before it - else - return {}; // not found. - - constexpr auto recipient_address = "recipient_address="sv; - if (auto pos = s.find(recipient_address); pos != std::string_view::npos) - s.remove_prefix(pos + recipient_address.size()); // delete it and everything up to it - else - return {}; // not found - - // find the next semicolon - if (auto pos = s.find(';'); pos != std::string::npos) - { - // length of address == 95, we can at least validate that much here - if (pos == 95) - return std::string{s.substr(0, 95)}; - else if (pos == 106) // length of address == 106 --> integrated address - return std::string{s.substr(0, 106)}; - } - return {}; -} -/** - * @brief gets a oxen address from the TXT record of a DNS entry - * - * gets the oxen address from the TXT record of the DNS entry associated - * with . If this lookup fails, or the TXT record does not contain an - * XMR address in the correct format, returns an empty string. - * will be set true or false according to whether or not the DNS query passes - * DNSSEC validation. - * - * @param url the url to look up - * @param dnssec_valid return-by-reference for DNSSEC status of query - * - * @return a oxen address (as a string) or an empty string - */ -std::vector addresses_from_url(const std::string_view url, bool& dnssec_valid) -{ - std::vector addresses; - // get txt records - bool dnssec_available, dnssec_isvalid; - std::string oa_addr = DNSResolver::instance().get_dns_format_from_oa_address(url); - auto records = DNSResolver::instance().get_txt_record(oa_addr, dnssec_available, dnssec_isvalid); - - // TODO: update this to allow for conveying that dnssec was not available - if (dnssec_available && dnssec_isvalid) - { - dnssec_valid = true; - } - else dnssec_valid = false; - - // for each txt record, try to find a oxen address in it. - for (auto& rec : records) - { - std::string addr = address_from_txt_record(rec); - if (addr.size()) - { - addresses.push_back(std::move(addr)); - } - } - return addresses; -} - -std::string get_account_address_as_str_from_url(const std::string_view url, bool& dnssec_valid, - std::function&, bool)> dns_confirm) -{ - // attempt to get address from dns query - auto addresses = addresses_from_url(url, dnssec_valid); - if (addresses.empty()) - { - LOG_ERROR("wrong address: " << url); - return {}; - } - return dns_confirm(url, addresses, dnssec_valid); -} - -namespace -{ - bool dns_records_match(const std::vector& a, const std::vector& b) - { - if (a.size() != b.size()) return false; - - for (const auto& record_in_a : a) - { - bool ok = false; - for (const auto& record_in_b : b) - { - if (record_in_a == record_in_b) - { - ok = true; - break; - } - } - if (!ok) return false; - } - - return true; - } -} - -bool load_txt_records_from_dns(std::vector &good_records, const std::vector &dns_urls) -{ - // Prevent infinite recursion when distributing - if (dns_urls.empty()) return false; - - std::vector > records; - records.resize(dns_urls.size()); - - size_t first_index = crypto::rand_idx(dns_urls.size()); - - // send all requests in parallel - std::deque avail(dns_urls.size(), false), valid(dns_urls.size(), false); - tools::threadpool& tpool = tools::threadpool::getInstance(); - tools::threadpool::waiter waiter; - for (size_t n = 0; n < dns_urls.size(); ++n) - { - tpool.submit(&waiter,[n, dns_urls, &records, &avail, &valid](){ - records[n] = tools::DNSResolver::instance().get_txt_record(dns_urls[n], avail[n], valid[n]); - }); - } - waiter.wait(&tpool); - - size_t cur_index = first_index; - do - { - const std::string &url = dns_urls[cur_index]; - if (!avail[cur_index]) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC not available for hostname: " << url << ", skipping."); - } - if (!valid[cur_index]) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC validation failed for hostname: " << url << ", skipping."); - } - - cur_index++; - if (cur_index == dns_urls.size()) - { - cur_index = 0; - } - } while (cur_index != first_index); - - size_t num_valid_records = 0; - - for( const auto& record_set : records) - { - if (record_set.size() != 0) - { - num_valid_records++; - } - } - - if (num_valid_records < 2) - { - LOG_PRINT_L0("WARNING: no two valid DNS TXT records were received"); - return false; - } - - int good_records_index = -1; - for (size_t i = 0; i < records.size() - 1; ++i) - { - if (records[i].size() == 0) continue; - - for (size_t j = i + 1; j < records.size(); ++j) - { - if (dns_records_match(records[i], records[j])) - { - good_records_index = i; - break; - } - } - if (good_records_index >= 0) break; - } - - if (good_records_index < 0) - { - LOG_PRINT_L0("WARNING: no two DNS TXT records matched"); - return false; - } - - good_records = records[good_records_index]; - return true; -} - -std::vector parse_dns_public(const char *s) -{ - unsigned ip0, ip1, ip2, ip3; - char c; - std::vector dns_public_addr; - if (s == "tcp"sv) - { - for (auto& default_dns : DEFAULT_DNS_PUBLIC_ADDR) - dns_public_addr.emplace_back(default_dns); - LOG_PRINT_L0("Using default public DNS server(s): " << tools::join(", ", dns_public_addr) << " (TCP)"); - } - else if (std::sscanf(s, "tcp://%u.%u.%u.%u%c", &ip0, &ip1, &ip2, &ip3, &c) == 4) - { - if (ip0 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255) - { - MERROR("Invalid IP: " << s << ", using default"); - } - else - { - dns_public_addr.emplace_back(s + 6); - } - } - else - { - MERROR("Invalid DNS_PUBLIC contents, ignored"); - } - return dns_public_addr; -} - -} // namespace tools::dns_utils - -} // namespace tools diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h deleted file mode 100644 index 1a18021b6..000000000 --- a/src/common/dns_utils.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2014-2019, The Monero Project -// -// 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. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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. -#pragma once - -#include -#include -#include -#include -#include -#include - -struct ub_ctx; - -namespace tools -{ - -using namespace std::literals; - -// RFC defines for record types and classes for DNS, gleaned from ldns source -constexpr int DNS_CLASS_IN = 1; -constexpr int DNS_TYPE_A = 1; -constexpr int DNS_TYPE_TXT = 16; -constexpr int DNS_TYPE_AAAA = 8; - -struct ub_ctx_deleter { void operator()(ub_ctx*); }; - -/** - * @brief Provides high-level access to DNS resolution - * - * This class is designed to provide a high-level abstraction to DNS resolution - * functionality, including access to TXT records and such. It will also - * handle DNSSEC validation of the results. - */ -class DNSResolver -{ -private: - - /** - * @brief Constructs an instance of DNSResolver - * - * Constructs a class instance and does setup stuff for the backend resolver. - */ - DNSResolver(); - -public: - - /** - * @brief gets ipv4 addresses from DNS query of a URL - * - * returns a vector of all IPv4 "A" records for given URL. - * If no "A" records found, returns an empty vector. - * - * @param url A string containing a URL to query for - * - * @param dnssec_available - * - * @return vector of strings containing ipv4 addresses - */ - std::vector get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid); - - /** - * @brief gets ipv6 addresses from DNS query - * - * returns a vector of all IPv6 "A" records for given URL. - * If no "A" records found, returns an empty vector. - * - * @param url A string containing a URL to query for - * - * @return vector of strings containing ipv6 addresses - */ - std::vector get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid); - - /** - * @brief gets all TXT records from a DNS query for the supplied URL; - * if no TXT record present returns an empty vector. - * - * @param url A string containing a URL to query for - * - * @return A vector of strings containing a TXT record; or an empty vector - */ - // TODO: modify this to accommodate DNSSEC - std::vector get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid); - - /** - * @brief query multiple hostnames simultaneously for results, waiting up to a fixed amount of - * time for results before returning. - * - * @param type `DNS_TYPE_A` or `DNS_TYPE_AAAA` or `DNS_TYPE_TXT` indicating the lookup type. - * @param hostnames a vector of hostnames to look up - * @param timeout how long to wait for results before giving up. Any results not yet retrieved by - * the timeout are left empty. - * @param dnssec if true then validate DNSSEC if available (i.e. reject DNSSEC failures, but allow insecure results when DNSSEC not available) - * @param dnssec_required if true then require and validate DNSSEC (i.e. reject failures and reject when DNSSEC not available) - * - * Returns a vector of vector of results: the results for address [i] are in result element [i]. - * If lookup failed (or DNSSEC failed with the relevant options given) for element [i] then vector - * [i] will be empty. - */ - // TODO: this could be extended to support doing multiple lookup types at once (e.g. A and AAAA). - std::vector> get_many(int type, const std::vector& hostnames, std::chrono::milliseconds timeout = 10s, bool dnssec = false, bool dnssec_required = false); - - /** - * @brief Gets a DNS address from OpenAlias format - * - * If the address looks good, but contains one @ symbol, replace that with a . - * e.g. donate@getmonero.org becomes donate.getmonero.org - * - * @param oa_addr OpenAlias address - * - * @return dns_addr DNS address - */ - std::string get_dns_format_from_oa_address(std::string_view oa_addr); - - /** - * @brief Gets the singleton instance of DNSResolver - * - * @return returns a reference to the singleton - */ - static DNSResolver& instance(); - - /** - * @brief Gets a new instance of DNSResolver - * - * @return returns a pointer to the new object - */ - static DNSResolver create(); - -private: - - /** - * @brief gets all records of a given type from a DNS query for the supplied URL; - * if no such record is present returns an empty vector. - * - * @param url A string containing a URL to query for - * @param record_type the record type to retrieve (DNS_TYPE_A, etc) - * @param reader a function that converts a record data to a string - * - * @return A vector of strings containing the requested record; or an empty vector - */ - // TODO: modify this to accommodate DNSSEC - std::vector get_record(const std::string& url, int record_type, std::optional (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid); - - ub_ctx* m_ctx = nullptr; -}; // class DNSResolver - -namespace dns_utils -{ - -std::string address_from_txt_record(std::string_view s); -std::vector addresses_from_url(const std::string_view url, bool& dnssec_valid); - -std::string get_account_address_as_str_from_url(const std::string_view url, bool& dnssec_valid, - std::function&, bool)> confirm_dns); - -bool load_txt_records_from_dns(std::vector &records, const std::vector &dns_urls); - -std::vector parse_dns_public(const char *s); - -} // namespace tools::dns_utils - -} // namespace tools diff --git a/src/common/util.cpp b/src/common/util.cpp index a0c42c6d8..7a60e758c 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -33,8 +33,6 @@ #include #include -#include "unbound.h" - #include "epee/string_tools.h" #include "epee/wipeable_string.h" #include "crypto/crypto.h" @@ -57,21 +55,6 @@ namespace tools { - static bool unbound_built_with_threads() - { - ub_ctx *ctx = ub_ctx_create(); - if (!ctx) return false; // cheat a bit, should not happen unless OOM - char *oxen = strdup("oxen"), *unbound = strdup("unbound"); - ub_ctx_zone_add(ctx, oxen, unbound); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX - free(unbound); - free(oxen); - // if no threads, bails out early with UB_NOERROR, otherwise fails with UB_AFTERFINAL id already finalized - bool with_threads = ub_ctx_async(ctx, 1) != 0; // UB_AFTERFINAL is not defined in public headers, check any error - ub_ctx_delete(ctx); - MINFO("libunbound was built " << (with_threads ? "with" : "without") << " threads"); - return with_threads; - } - bool disable_core_dumps() { #ifdef __GLIBC__ @@ -112,9 +95,6 @@ namespace tools MCLOG_RED(el::Level::Warning, "global", "Running with glibc " << ver << ", hangs may occur - change glibc version if possible"); #endif - if (!unbound_built_with_threads()) - MCLOG_RED(el::Level::Warning, "global", "libunbound was not built with threads enabled - crashes may occur"); - return true; } namespace diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index d581ade72..e4b097502 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -39,7 +39,6 @@ #include "common/base58.h" #include "crypto/hash.h" #include "epee/int-util.h" -#include "common/dns_utils.h" #include "common/oxen.h" #include @@ -282,21 +281,6 @@ namespace cryptonote { return true; } //-------------------------------------------------------------------------------- - bool get_account_address_from_str_or_url( - address_parse_info& info - , network_type nettype - , const std::string_view str_or_url - , std::function&, bool)> dns_confirm - ) - { - if (get_account_address_from_str(info, nettype, str_or_url)) - return true; - bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm); - return !address_str.empty() && - get_account_address_from_str(info, nettype, address_str); - } - //-------------------------------------------------------------------------------- bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { return cryptonote::get_transaction_hash(a) == cryptonote::get_transaction_hash(b); } diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index fb1010180..9f67e6e14 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -140,13 +140,6 @@ namespace cryptonote { , const std::string_view str ); - bool get_account_address_from_str_or_url( - address_parse_info& info - , network_type nettype - , const std::string_view str_or_url - , std::function&, bool)> dns_confirm = return_first_address - ); - bool is_coinbase(const transaction& tx); bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b); diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 0837369bb..46e619133 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -56,7 +56,6 @@ extern "C" { #include "common/command_line.h" #include "common/hex.h" #include "common/base58.h" -#include "common/dns_utils.h" #include "epee/warnings.h" #include "crypto/crypto.h" #include "cryptonote_config.h" diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 30d4bfc12..618d657ba 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -29,7 +29,6 @@ #include -#include "common/dns_utils.h" #include "common/command_line.h" #include "common/hex.h" #include "version.h" @@ -490,45 +489,17 @@ bool command_parser_executor::start_mining(const std::vector& args) } cryptonote::address_parse_info info; - cryptonote::network_type nettype = cryptonote::MAINNET; - if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front())) + cryptonote::network_type nettype; + if (cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front())) + nettype = cryptonote::MAINNET; + else if (cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, args.front())) + nettype = cryptonote::TESTNET; + else if (cryptonote::get_account_address_from_str(info, cryptonote::DEVNET, args.front())) + nettype = cryptonote::DEVNET; + else { - if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, args.front())) - { - if(!cryptonote::get_account_address_from_str(info, cryptonote::DEVNET, args.front())) - { - bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid, - [](const std::string_view url, const std::vector &addresses, bool dnssec_valid){return addresses[0];}); - if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, address_str)) - { - if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, address_str)) - { - if(!cryptonote::get_account_address_from_str(info, cryptonote::DEVNET, address_str)) - { - std::cout << "target account address has wrong format" << std::endl; - return true; - } - else - { - nettype = cryptonote::DEVNET; - } - } - else - { - nettype = cryptonote::TESTNET; - } - } - } - else - { - nettype = cryptonote::DEVNET; - } - } - else - { - nettype = cryptonote::TESTNET; - } + std::cout << "target account address has wrong format" << std::endl; + return true; } if (info.is_subaddress) { diff --git a/src/debug_utilities/CMakeLists.txt b/src/debug_utilities/CMakeLists.txt index 734615653..38a10f77f 100644 --- a/src/debug_utilities/CMakeLists.txt +++ b/src/debug_utilities/CMakeLists.txt @@ -48,17 +48,3 @@ target_link_libraries(object_sizes cpr::cpr extra ) - -set(dns_checks_sources - dns_checks.cpp - ) - -oxen_add_executable(dns_checks "oxen-utils-dns-checks" dns_checks.cpp) - -target_link_libraries(dns_checks - PRIVATE - common - epee - version - Boost::program_options - Boost::thread) diff --git a/src/debug_utilities/dns_checks.cpp b/src/debug_utilities/dns_checks.cpp deleted file mode 100644 index e7b868e89..000000000 --- a/src/debug_utilities/dns_checks.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2019, The Monero Project -// -// 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. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 -#include -#include -#include -#include -#include "epee/misc_log_ex.h" -#include "common/util.h" -#include "common/command_line.h" -#include "common/dns_utils.h" -#include "version.h" - -#undef OXEN_DEFAULT_LOG_CATEGORY -#define OXEN_DEFAULT_LOG_CATEGORY "debugtools.dnschecks" - -namespace po = boost::program_options; - -enum lookup_t { LOOKUP_A, LOOKUP_TXT }; - -static std::vector lookup(lookup_t type, const char *hostname) -{ - bool dnssec_available = false, dnssec_valid = false; - std::vector res; - switch (type) - { - case LOOKUP_A: res = tools::DNSResolver::instance().get_ipv4(hostname, dnssec_available, dnssec_valid); break; - case LOOKUP_TXT: res = tools::DNSResolver::instance().get_txt_record(hostname, dnssec_available, dnssec_valid); break; - default: MERROR("Invalid lookup type: " << (int)type); return {}; - } - if (!dnssec_available) - { - MWARNING("No DNSSEC for " << hostname); - return {}; - } - if (!dnssec_valid) - { - MWARNING("Invalid DNSSEC check for " << hostname); - return {}; - } - MINFO(res.size() << " valid signed result(s) for " << hostname); - return res; -} - -static void lookup(lookup_t type, const std::vector hostnames) -{ - std::vector> results; - for (const std::string &hostname: hostnames) - { - auto res = lookup(type, hostname.c_str()); - if (!res.empty()) - { - std::sort(res.begin(), res.end()); - results.push_back(res); - } - } - std::map, size_t> counter; - for (const auto &e: results) - counter[e]++; - size_t count = 0; - for (const auto &e: counter) - count = std::max(count, e.second); - if (results.size() > 1) - { - if (count < results.size()) - MERROR("Only " << count << "/" << results.size() << " records match"); - else - MINFO(count << "/" << results.size() << " records match"); - } -} - -int main(int argc, char* argv[]) -{ - TRY_ENTRY(); - - tools::on_startup(); - - po::options_description desc_cmd_only("Command line options"); - po::options_description desc_cmd_sett("Command line options and settings options"); - - command_line::add_arg(desc_cmd_only, command_line::arg_help); - - po::options_description desc_options("Allowed options"); - desc_options.add(desc_cmd_only).add(desc_cmd_sett); - - po::variables_map vm; - bool r = command_line::handle_error_helper(desc_options, [&]() - { - po::store(po::parse_command_line(argc, argv, desc_options), vm); - po::notify(vm); - return true; - }); - if (! r) - return 1; - - if (command_line::get_arg(vm, command_line::arg_help)) - { - std::cout << "Oxen '" << OXEN_RELEASE_NAME << "' (v" << OXEN_VERSION_FULL << ")\n\n"; - std::cout << desc_options << std::endl; - return 1; - } - - mlog_configure("", true); - mlog_set_categories("+" OXEN_DEFAULT_LOG_CATEGORY ":INFO"); - - lookup(LOOKUP_A, {"seeds.moneroseeds.se", "seeds.moneroseeds.ae.org", "seeds.moneroseeds.ch", "seeds.moneroseeds.li"}); - - lookup(LOOKUP_TXT, {"updates.moneropulse.org", "updates.moneropulse.net", "updates.moneropulse.co", "updates.moneropulse.se"}); - - lookup(LOOKUP_TXT, {"checkpoints.moneropulse.org", "checkpoints.moneropulse.net", "checkpoints.moneropulse.co", "checkpoints.moneropulse.se"}); - - // those are in the code, but don't seem to actually exist -#if 0 - lookup(LOOKUP_TXT, {"testpoints.moneropulse.org", "testpoints.moneropulse.net", "testpoints.moneropulse.co", "testpoints.moneropulse.se"); - - lookup(LOOKUP_TXT, {"stagenetpoints.moneropulse.org", "stagenetpoints.moneropulse.net", "stagenetpoints.moneropulse.co", "stagenetpoints.moneropulse.se"}); -#endif - - lookup(LOOKUP_TXT, {"segheights.moneropulse.org", "segheights.moneropulse.net", "segheights.moneropulse.co", "segheights.moneropulse.se"}); - - return 0; - CATCH_ENTRY_L0("main", 1); -} diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 9c638bf51..b47a74ddf 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -38,7 +38,6 @@ target_link_libraries(device common cncrypto ringct_basic - OpenSSL::Crypto Boost::serialization PRIVATE version diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 7b52b9119..e7244d483 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -265,10 +265,6 @@ namespace nodetool virtual void clear_used_stripe_peers(); private: - const std::vector m_seed_nodes_list = - { - // TODO(oxen): "seeds.oxen.network" - }; bool islimitup=false; bool islimitdown=false; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index c36413924..5df65f0f2 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -45,7 +45,6 @@ #include "version.h" #include "epee/string_tools.h" #include "common/file.h" -#include "common/dns_utils.h" #include "common/pruning.h" #include "net/error.h" #include "common/periodic_task.h" @@ -599,50 +598,12 @@ namespace nodetool std::set node_server::get_seed_nodes() { if (!m_exclusive_peers.empty() || m_offline) - { return {}; - } if (m_nettype == cryptonote::TESTNET) - { return get_seed_nodes(cryptonote::TESTNET); - } if (m_nettype == cryptonote::DEVNET) - { return get_seed_nodes(cryptonote::DEVNET); - } - - std::set full_addrs; - - // for each hostname in the seed nodes list, attempt to DNS resolve and - // add the result addresses as seed nodes - // TODO: at some point add IPv6 support, but that won't be relevant - // for some time yet. - - auto dns_results = tools::DNSResolver::instance().get_many(tools::DNS_TYPE_A, m_seed_nodes_list, ::config::DNS_TIMEOUT); - - for (size_t i = 0; i < dns_results.size(); i++) - { - const auto& result = dns_results[i]; - MDEBUG("DNS lookup for " << m_seed_nodes_list[i] << ": " << result.size() << " results"); - // if no results for seed node then lookup failed or timed out - for (const auto& addr_string : result) - full_addrs.insert(addr_string + ":" + std::to_string(cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT)); - } - - // append the fallback nodes if we have too few seed nodes to start with - if (full_addrs.size() < MIN_WANTED_SEED_NODES) - { - if (full_addrs.empty()) - MINFO("DNS seed node lookup either timed out or failed, falling back to defaults"); - else - MINFO("Not enough DNS seed nodes found, using fallback defaults too"); - - for (const auto &peer: get_seed_nodes(cryptonote::MAINNET)) - full_addrs.insert(peer); - m_fallback_seed_nodes_added.test_and_set(); - } - - return full_addrs; + return get_seed_nodes(cryptonote::MAINNET); } //----------------------------------------------------------------------------------- template diff --git a/src/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 11ed559ee..935b32033 100644 --- a/src/ringct/CMakeLists.txt +++ b/src/ringct/CMakeLists.txt @@ -38,8 +38,6 @@ target_link_libraries(ringct_basic PUBLIC common PRIVATE - OpenSSL::SSL - OpenSSL::Crypto extra) add_library(ringct @@ -51,6 +49,4 @@ target_link_libraries(ringct cryptonote_basic device PRIVATE - OpenSSL::SSL - OpenSSL::Crypto extra) diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 3ee1298e7..e0b64b833 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -75,7 +75,6 @@ target_link_libraries(rpc cryptonote_protocol Boost::thread Boost::program_options - OpenSSL::SSL extra) target_link_libraries(daemon_rpc_server diff --git a/src/simplewallet/simplewallet-mms.inl b/src/simplewallet/simplewallet-mms.inl index 5899c6271..45721af03 100644 --- a/src/simplewallet/simplewallet-mms.inl +++ b/src/simplewallet/simplewallet-mms.inl @@ -375,7 +375,7 @@ void simple_wallet::mms_signer(const std::vector &args) if (args.size() == 4) { cryptonote::address_parse_info info; - bool ok = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[3], oa_prompter); + bool ok = cryptonote::get_account_address_from_str(info, m_wallet->nettype(), args[3]); if (!ok) { fail_msg_writer() << tr("Invalid Oxen address"); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index be083a153..e2be4f4f5 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -59,7 +59,6 @@ #include "common/command_line.h" #include "common/util.h" #include "common/signal_handler.h" -#include "common/dns_utils.h" #include "common/base58.h" #include "common/scoped_message_writer.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" @@ -427,42 +426,6 @@ namespace return "invalid"; } - std::string oa_prompter(const std::string_view url, const std::vector &addresses, bool dnssec_valid) - { - if (addresses.empty()) - return {}; - // prompt user for confirmation. - // inform user of DNSSEC validation status as well. - std::string dnssec_str; - if (dnssec_valid) - { - dnssec_str = sw::tr("DNSSEC validation passed"); - } - else - { - dnssec_str = sw::tr("WARNING: DNSSEC validation was unsuccessful, this address may not be correct!"); - } - std::stringstream prompt; - prompt << sw::tr("For URL: ") << url - << ", " << dnssec_str << std::endl - << sw::tr(" Oxen Address = ") << addresses[0] - << std::endl - << sw::tr("Is this OK?") - ; - // prompt the user for confirmation given the dns query and dnssec status - std::string confirm_dns_ok = input_line(prompt.str(), true); - if (std::cin.eof()) - { - return {}; - } - if (!command_line::is_yes(confirm_dns_ok)) - { - std::cout << sw::tr("you have cancelled the transfer request") << std::endl; - return {}; - } - return addresses[0]; - } - std::optional> parse_subaddress_lookahead(const std::string& str) { auto r = tools::parse_subaddress_lookahead(str); @@ -1212,7 +1175,7 @@ bool simple_wallet::export_multisig_main(const std::vector &args EN else #endif { - bool r = m_wallet->save_to_file(filename, ciphertext); + bool r = tools::dump_file(filename, ciphertext); if (!r) { fail_msg_writer() << tr("failed to save file ") << filename.u8string(); @@ -1275,7 +1238,7 @@ bool simple_wallet::import_multisig_main(const std::vector &args EN { const fs::path filename = fs::u8path(args[n]); std::string data; - bool r = m_wallet->load_from_file(filename, data); + bool r = tools::slurp_file(filename, data); if (!r) { fail_msg_writer() << tr("failed to read file ") << filename.u8string(); @@ -1592,7 +1555,7 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) if (!filenames.empty()) filenames += ", "; filenames += fn.u8string(); - if (!m_wallet->save_to_file(fn, cryptonote::tx_to_blob(ptx.tx))) + if (!tools::dump_file(fn, cryptonote::tx_to_blob(ptx.tx))) { fail_msg_writer() << tr("Failed to export multisig transaction to file ") << fn.u8string(); return true; @@ -2555,35 +2518,6 @@ bool simple_wallet::set_device_name(const std::vector &args/* = std return true; } -bool simple_wallet::set_export_format(const std::vector &args/* = std::vectorset_export_format(tools::wallet2::ExportFormat::Ascii); - } - else if (boost::algorithm::iequals(args[1], "binary")) - { - m_wallet->set_export_format(tools::wallet2::ExportFormat::Binary); - } - else - { - fail_msg_writer() << tr("Export format not recognized."); - return true; - } - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - } - return true; -} - bool simple_wallet::help(const std::vector &args/* = std::vector()*/) { if(args.empty()) @@ -3234,7 +3168,6 @@ bool simple_wallet::set_variable(const std::vector &args) success_msg_writer() << "ignore-outputs-below = " << cryptonote::print_money(m_wallet->ignore_outputs_below()); success_msg_writer() << "track-uses = " << m_wallet->track_uses(); success_msg_writer() << "device_name = " << m_wallet->device_name(); - success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary"); success_msg_writer() << "inactivity-lock-timeout = " << m_wallet->inactivity_lock_timeout().count() #ifdef _WIN32 << " (disabled on Windows)" @@ -3293,7 +3226,6 @@ bool simple_wallet::set_variable(const std::vector &args) CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)")); CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("")); - CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\"")); } fail_msg_writer() << tr("set: unrecognized argument(s)"); return true; @@ -5940,12 +5872,12 @@ bool simple_wallet::transfer_main(Transfer transfer_type, const std::vectornettype(), local_args[i], oa_prompter); + r = cryptonote::get_account_address_from_str(info, m_wallet->nettype(), local_args[i]); if (!r && m_wallet->is_trusted_daemon()) { std::optional address = m_wallet->resolve_address(local_args[i]); if (address) - r = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), *address, oa_prompter); + r = cryptonote::get_account_address_from_str(info, m_wallet->nettype(), *address); } if(!r) { @@ -7464,7 +7396,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, Transfer transf else addr = m_wallet->get_subaddress_as_str({m_current_subaddress_account, 0}); - if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), addr, oa_prompter)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), addr)) { fail_msg_writer() << tr("failed to parse address"); print_usage(); @@ -7560,7 +7492,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[1], oa_prompter)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), local_args[1])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -8021,7 +7953,7 @@ bool simple_wallet::get_tx_proof(const std::vector &args) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), args[1])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -8033,7 +7965,7 @@ bool simple_wallet::get_tx_proof(const std::vector &args) { std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : ""); const fs::path filename{"oxen_tx_proof"}; - if (m_wallet->save_to_file(filename, sig_str, true)) + if (tools::dump_file(filename, sig_str)) success_msg_writer() << tr("signature file saved to: ") << filename.u8string(); else fail_msg_writer() << tr("failed to save signature file"); @@ -8089,7 +8021,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[2], oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), local_args[2])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -8153,7 +8085,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) // parse address cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), args[1])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -8161,7 +8093,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) // read signature file std::string sig_str; - if (!m_wallet->load_from_file(args[2], sig_str)) + if (!tools::slurp_file(args[2], sig_str)) { fail_msg_writer() << tr("failed to load signature file"); return true; @@ -8245,7 +8177,7 @@ bool simple_wallet::get_spend_proof(const std::vector &args) { const std::string sig_str = m_wallet->get_spend_proof(txid, args.size() == 2 ? args[1] : ""); const fs::path filename{"oxen_spend_proof"}; - if (m_wallet->save_to_file(filename, sig_str, true)) + if (tools::dump_file(filename, sig_str)) success_msg_writer() << tr("signature file saved to: ") << filename.u8string(); else fail_msg_writer() << tr("failed to save signature file"); @@ -8275,7 +8207,7 @@ bool simple_wallet::check_spend_proof(const std::vector &args) return true; std::string sig_str; - if (!m_wallet->load_from_file(args[1], sig_str)) + if (!tools::slurp_file(args[1], sig_str)) { fail_msg_writer() << tr("failed to load signature file"); return true; @@ -8334,7 +8266,7 @@ bool simple_wallet::get_reserve_proof(const std::vector &args) { const std::string sig_str = m_wallet->get_reserve_proof(account_minreserve, args.size() == 2 ? args[1] : ""); const fs::path filename{"oxen_reserve_proof"}; - if (m_wallet->save_to_file(filename, sig_str, true)) + if (tools::dump_file(filename, sig_str)) success_msg_writer() << tr("signature file saved to: ") << filename.u8string(); else fail_msg_writer() << tr("failed to save signature file"); @@ -8357,7 +8289,7 @@ bool simple_wallet::check_reserve_proof(const std::vector &args) return true; cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[0], oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), args[0])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -8369,7 +8301,7 @@ bool simple_wallet::check_reserve_proof(const std::vector &args) } std::string sig_str; - if (!m_wallet->load_from_file(args[1], sig_str)) + if (!tools::slurp_file(args[1], sig_str)) { fail_msg_writer() << tr("failed to load signature file"); return true; @@ -9388,7 +9320,7 @@ bool simple_wallet::address_book(const std::vector &args/* = std::v else if (args[0] == "add") { cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), args[1])) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -9621,7 +9553,7 @@ bool simple_wallet::sign(const std::vector &args) const fs::path filename = fs::u8path(args.back()); std::string data; - if (!m_wallet->load_from_file(filename, data)) + if (!tools::slurp_file(filename, data)) { fail_msg_writer() << tr("failed to read file ") << filename.u8string(); return true; @@ -9633,7 +9565,7 @@ bool simple_wallet::sign(const std::vector &args) bool simple_wallet::verify_string(std::string_view value, std::string_view address, std::string_view signature) { cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), address, oa_prompter)) + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address)) fail_msg_writer() << tr("failed to parse address"); else if (!m_wallet->verify(value, info.address, signature)) fail_msg_writer() << tr("Bad signature from ") << address; @@ -9653,7 +9585,7 @@ bool simple_wallet::verify(const std::vector &args) } fs::path filename = fs::u8path(args[0]); std::string data; - if (!m_wallet->load_from_file(filename, data)) + if (!tools::slurp_file(filename, data)) { fail_msg_writer() << tr("failed to read file ") << filename.u8string(); return true; @@ -9892,7 +9824,7 @@ bool simple_wallet::export_outputs(const std::vector &args) try { std::string data = m_wallet->export_outputs_to_str(all); - bool r = m_wallet->save_to_file(filename, data); + bool r = tools::dump_file(filename, data); if (!r) { fail_msg_writer() << tr("failed to save file ") << filename.u8string(); @@ -9925,7 +9857,7 @@ bool simple_wallet::import_outputs(const std::vector &args) const fs::path filename = fs::u8path(args[0]); std::string data; - bool r = m_wallet->load_from_file(filename, data); + bool r = tools::slurp_file(filename, data); if (!r) { fail_msg_writer() << tr("failed to read file ") << filename.u8string(); @@ -10149,7 +10081,7 @@ void simple_wallet::commit_or_save(std::vector& ptx_ const std::string blob_hex = oxenc::to_hex(blob); fs::path filename = fs::u8path("raw_oxen_tx"); if (ptx_vector.size() > 1) filename += "_" + std::to_string(i++); - bool success = m_wallet->save_to_file(filename, blob_hex, true); + bool success = tools::dump_file(filename, blob_hex); if (success) msg_buf += tr("Transaction successfully saved to "); else msg_buf += tr("Failed to save transaction to "); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 20a85a87c..d1c8c6c0d 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -154,7 +154,6 @@ namespace cryptonote bool set_track_uses(const std::vector &args = std::vector()); bool set_inactivity_lock_timeout(const std::vector &args = std::vector()); bool set_device_name(const std::vector &args = std::vector()); - bool set_export_format(const std::vector &args = std::vector()); bool help(const std::vector &args = std::vector()); bool start_mining(const std::vector &args); bool stop_mining(const std::vector &args); diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 443332d4f..8d6399621 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -62,8 +62,6 @@ target_link_libraries(wallet filesystem Boost::thread PRIVATE - OpenSSL::SSL - OpenSSL::Crypto extra) oxen_add_executable(wallet_rpc_server "oxen-wallet-rpc" diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt index d5e36b5a4..f4d58bf08 100644 --- a/src/wallet/api/CMakeLists.txt +++ b/src/wallet/api/CMakeLists.txt @@ -125,9 +125,6 @@ if (STATIC AND BUILD_STATIC_DEPS) # Static deps: Boost::program_options Boost::serialization Boost::system Boost::thread zlib - OpenSSL::SSL OpenSSL::Crypto - expat - libunbound SQLite::SQLite3 ${merged_protobuf} sodium diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 3692a3e0b..3e5f42888 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1210,9 +1210,6 @@ struct WalletManagerBase //! returns current block target virtual uint64_t blockTarget() = 0; - - //! resolves an OpenAlias address to a monero address - virtual std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const = 0; }; struct WalletManagerFactory diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 25e5e910a..96fb58ced 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -35,7 +35,6 @@ #include "rpc/core_rpc_server_commands_defs.h" #include "wallet.h" #include "common_defines.h" -#include "common/dns_utils.h" #include "common/util.h" #include "version.h" #include "common/fs.h" @@ -271,15 +270,6 @@ uint64_t WalletManagerImpl::blockTarget() return res ? res->target : 0; } -EXPORT -std::string WalletManagerImpl::resolveOpenAlias(const std::string &address, bool &dnssec_valid) const -{ - std::vector addresses = tools::dns_utils::addresses_from_url(address, dnssec_valid); - if (addresses.empty()) - return ""; - return addresses.front(); -} - ///////////////////// WalletManagerFactory implementation ////////////////////// EXPORT WalletManagerBase *WalletManagerFactory::getWalletManager() diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 446ee9701..30aaea61d 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -76,7 +76,6 @@ public: uint64_t blockchainHeight() override; uint64_t blockchainTargetHeight() override; uint64_t blockTarget() override; - std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override; private: WalletManagerImpl() {} diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index dbd9ea56e..c7d4fc307 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -35,8 +35,6 @@ #include #include #include -#include -#include #include #include #include @@ -76,7 +74,6 @@ #include "epee/memwipe.h" #include "common/base58.h" #include "common/combinator.h" -#include "common/dns_utils.h" #include "common/notify.h" #include "common/perf_timer.h" #include "common/hex.h" @@ -1085,8 +1082,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_devices_registered(false), m_device_last_key_image_sync(0), m_offline(false), - m_rpc_version(0), - m_export_format(ExportFormat::Binary) + m_rpc_version(0) { } @@ -3869,7 +3865,7 @@ bool wallet2::store_keys(const fs::path& keys_file_name, const epee::wipeable_st bool r = false; try { buf = serialization::dump_binary(*keys_file_data); - r = save_to_file(tmp_file_name, buf); + r = tools::dump_file(tmp_file_name, buf); } catch (...) {} CHECK_AND_ASSERT_MES(r, false, "failed to generate wallet keys file " << tmp_file_name); @@ -4047,9 +4043,6 @@ std::optional wallet2::get_keys_file_data(const epee::w value2.SetInt(m_original_keys_available ? 1 : 0); json.AddMember("original_keys_available", value2, json.GetAllocator()); - value2.SetInt(m_export_format); - json.AddMember("export_format", value2, json.GetAllocator()); - value2.SetUint(1); json.AddMember("encrypted_secret_keys", value2, json.GetAllocator()); @@ -4123,7 +4116,7 @@ void wallet2::change_password(const fs::path& filename, const epee::wipeable_str bool wallet2::load_keys(const fs::path& keys_file_name, const epee::wipeable_string& password) { std::string keys_file_buf; - bool r = load_from_file(keys_file_name, keys_file_buf); + bool r = tools::slurp_file(keys_file_name, keys_file_buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name); // Load keys from buffer @@ -4206,7 +4199,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR; m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR; m_original_keys_available = false; - m_export_format = ExportFormat::Binary; m_device_name = ""; m_device_derivation_path = ""; m_key_device_type = hw::device::type::SOFTWARE; @@ -4372,9 +4364,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, encrypted_secret_keys, uint32_t, Uint, false, false); encrypted_secret_keys = field_encrypted_secret_keys; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, export_format, ExportFormat, Int, false, Binary); - m_export_format = field_export_format; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string()); if (m_device_name.empty()) { @@ -4513,7 +4502,7 @@ bool wallet2::verify_password(const fs::path& keys_file_name, const epee::wipeab wallet2::keys_file_data keys_file_data; std::string buf; bool encrypted_secret_keys = false; - bool r = load_from_file(keys_file_name, buf); + bool r = tools::slurp_file(keys_file_name, buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name); // Decrypt the contents @@ -4610,7 +4599,7 @@ void wallet2::create_keys_file(const fs::path &wallet_, bool watch_only, const e { auto addrfile = m_wallet_file; addrfile += ".address.txt"; - r = save_to_file(addrfile, m_account.get_public_address_str(m_nettype), true); + r = tools::dump_file(addrfile, m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } } @@ -4632,7 +4621,7 @@ bool wallet2::query_device(hw::device::type& device_type, const fs::path& keys_f rapidjson::Document json; wallet2::keys_file_data keys_file_data; std::string buf; - bool r = load_from_file(keys_file_name, buf); + bool r = tools::slurp_file(keys_file_name, buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name); // Decrypt the contents @@ -4958,7 +4947,7 @@ void wallet2::restore_from_device(const fs::path& wallet_, const epee::wipeable_ if (hwdev_label) { fs::path hwdev_txt = m_wallet_file; hwdev_txt += ".hwdev.txt"; - if (!save_to_file(hwdev_txt, *hwdev_label, true)) + if (!tools::dump_file(hwdev_txt, *hwdev_label)) MERROR("failed to write .hwdev.txt comment file"); } if (progress_callback) @@ -5209,7 +5198,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor addrfile += ".address.txt"; if (fs::exists(addrfile)) { - r = save_to_file(addrfile, m_account.get_public_address_str(m_nettype), true); + r = tools::dump_file(addrfile, m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } } @@ -5685,7 +5674,7 @@ void wallet2::load(const fs::path& wallet_, const epee::wipeable_string& passwor bool r = true; if (use_fs) { - load_from_file(m_wallet_file, cache_file_buf); + r = tools::slurp_file(m_wallet_file, cache_file_buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); } @@ -5910,7 +5899,7 @@ void wallet2::store_to(const fs::path &path, const epee::wipeable_string &passwo // save address to the new file fs::path address_file = path; address_file += ".address.txt"; - r = save_to_file(address_file, m_account.get_public_address_str(m_nettype), true); + r = tools::dump_file(address_file, m_account.get_public_address_str(m_nettype)); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); // remove old address file if (!fs::remove(old_address_file, ec)) @@ -7044,7 +7033,7 @@ bool wallet2::save_tx(const std::vector& ptx_vector, const fs::path& std::string ciphertext = dump_tx_to_str(ptx_vector); if (ciphertext.empty()) return false; - return save_to_file(filename, ciphertext); + return tools::dump_file(filename, ciphertext); } //---------------------------------------------------------------------------------------------------- std::string wallet2::dump_tx_to_str(const std::vector &ptx_vector) const @@ -7085,7 +7074,7 @@ bool wallet2::load_unsigned_tx(const fs::path& unsigned_filename, unsigned_tx_se } std::string s; - if (!load_from_file(unsigned_filename, s)) + if (!tools::slurp_file(unsigned_filename, s)) { LOG_PRINT_L0("Failed to load from " << unsigned_filename); return false; @@ -7309,7 +7298,7 @@ bool wallet2::sign_tx(unsigned_tx_set& exported_txs, const fs::path& signed_file return false; } - if (!save_to_file(signed_filename, ciphertext)) + if (!tools::dump_file(signed_filename, ciphertext)) { LOG_PRINT_L0("Failed to save file to " << signed_filename); return false; @@ -7323,7 +7312,7 @@ bool wallet2::sign_tx(unsigned_tx_set& exported_txs, const fs::path& signed_file fs::path raw_filename = signed_filename; raw_filename += "_raw"; if (signed_txes.ptx.size() > 1) raw_filename += "_" + std::to_string(i); - if (!save_to_file(raw_filename, tx_as_hex)) + if (!tools::dump_file(raw_filename, tx_as_hex)) { LOG_PRINT_L0("Failed to save file to " << raw_filename); return false; @@ -7368,7 +7357,7 @@ bool wallet2::load_tx(const fs::path& signed_filename, std::vector& ptx_vector) const @@ -7525,7 +7514,7 @@ bool wallet2::save_multisig_tx(const std::vector& ptx_vector, const std::string ciphertext = save_multisig_tx(ptx_vector); if (ciphertext.empty()) return false; - return save_to_file(filename, ciphertext); + return tools::dump_file(filename, ciphertext); } //---------------------------------------------------------------------------------------------------- bool wallet2::parse_multisig_tx_from_str(std::string_view multisig_tx_st, multisig_tx_set &exported_txs) const @@ -7614,7 +7603,7 @@ bool wallet2::load_multisig_tx_from_file(const fs::path& filename, multisig_tx_s } std::string s; - if (!load_from_file(filename, s)) + if (!tools::slurp_file(filename, s)) { LOG_PRINT_L0("Failed to load from " << filename); return false; @@ -13334,7 +13323,7 @@ bool wallet2::export_key_images_to_file(const fs::path& filename, bool requested PERF_TIMER(export_key_images_encrypt); std::string ciphertext{KEY_IMAGE_EXPORT_FILE_MAGIC}; ciphertext += encrypt_with_view_secret_key(data); - return save_to_file(filename, ciphertext); + return tools::dump_file(filename, ciphertext); } //---------------------------------------------------------------------------------------------------- @@ -13397,7 +13386,7 @@ uint64_t wallet2::import_key_images_from_file(const fs::path& filename, uint64_t { PERF_TIMER(__FUNCTION__); std::string data; - bool r = load_from_file(filename, data); + bool r = tools::slurp_file(filename, data); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename.u8string()); @@ -14748,71 +14737,6 @@ std::string wallet2::get_rpc_status(const std::string &s) const return ""; } //---------------------------------------------------------------------------------------------------- - -bool wallet2::save_to_file(const fs::path& path_to_file, std::string_view binary, bool is_printable) const -{ - if (is_printable || m_export_format == ExportFormat::Binary) - { - return tools::dump_file(path_to_file, binary); - } - -#ifdef _WIN32 - FILE *fp = _wfopen(path_to_file.c_str(), L"w+"); -#else - FILE *fp = fopen(path_to_file.c_str(), "w+"); -#endif - if (!fp) - { - MERROR("Failed to open wallet file for writing: " << path_to_file << ": " << strerror(errno)); - return false; - } - - // Save the result b/c we need to close the fp before returning success/failure. - int write_result = PEM_write(fp, ASCII_OUTPUT_MAGIC.c_str(), "", reinterpret_cast(binary.data()), binary.length()); - fclose(fp); - - return write_result != 0; -} -//---------------------------------------------------------------------------------------------------- - -bool wallet2::load_from_file(const fs::path& path_to_file, std::string& target_str) -{ - std::string data; - if (!tools::slurp_file(path_to_file, data)) - return false; - - if (data.find(ASCII_OUTPUT_MAGIC) == std::string::npos) - { - // It's NOT our ascii dump. - target_str = std::move(data); - return true; - } - - // Creating a BIO and calling PEM_read_bio instead of simpler PEM_read - // to avoid reading the file from disk twice. - BIO* b = BIO_new_mem_buf((const void*) data.data(), data.length()); - - char *name = nullptr; - char *header = nullptr; - unsigned char *openssl_data = nullptr; - long len = 0; - - // Save the result b/c we need to free the data before returning success/failure. - bool success = PEM_read_bio(b, &name, &header, &openssl_data, &len); - if (success) - { - target_str.clear(); - target_str.append((const char*) openssl_data, len); - } - - OPENSSL_free((void *) name); - OPENSSL_free((void *) header); - OPENSSL_free((void *) openssl_data); - BIO_free(b); - - return success; -} -//---------------------------------------------------------------------------------------------------- void wallet2::hash_m_transfer(const transfer_details & transfer, crypto::hash &hash) const { KECCAK_CTX state; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 26c062ede..15613dc8e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -258,11 +258,6 @@ private: AskPasswordToDecrypt = 2, }; - enum ExportFormat { - Binary = 0, - Ascii, - }; - static const char* tr(const char* str); static const char *ERR_MSG_NETWORK_VERSION_QUERY_FAILED; static const char *ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED; @@ -1043,8 +1038,6 @@ private: void device_address(std::string device_address) { m_device_address = std::move(device_address); } const std::string & device_derivation_path() const { return m_device_derivation_path; } void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; } - const ExportFormat & export_format() const { return m_export_format; } - void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; } bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &additional_tx_keys) const; void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys); @@ -1448,9 +1441,6 @@ private: bool frozen(const crypto::key_image &ki) const; bool frozen(const transfer_details &td) const; - bool save_to_file(const fs::path& path_to_file, std::string_view binary, bool is_printable = false) const; - static bool load_from_file(const fs::path& path_to_file, std::string& target_str); - uint64_t get_bytes_sent() const; uint64_t get_bytes_received() const; @@ -1738,8 +1728,6 @@ private: std::shared_ptr m_tx_notify; std::unique_ptr m_device_callback; - ExportFormat m_export_format; - inline static std::mutex default_daemon_address_mutex; inline static std::string default_daemon_address; }; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 1d3cd21bd..9b4afd9ed 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -870,41 +870,19 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ cryptonote::address_parse_info wallet_rpc_server::extract_account_addr( cryptonote::network_type nettype, - std::string_view addr_or_url) + std::string_view addr) { + cryptonote::address_parse_info info; if (m_wallet->is_trusted_daemon()) { - std::optional address = m_wallet->resolve_address(std::string{addr_or_url}); - if (address) - { - cryptonote::address_parse_info info; - if (!get_account_address_from_str_or_url(info, nettype, *address, - [](const std::string_view url, const std::vector &addresses, bool dnssec_valid) { - if (!dnssec_valid) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid DNSSEC for "s + std::string{url}}; - if (addresses.empty()) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "No Oxen address found at "s + std::string{url}}; - return addresses[0]; - })) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid address: "s + std::string{addr_or_url}}; + std::optional address = m_wallet->resolve_address(std::string{addr}); + if (cryptonote::address_parse_info info; address && get_account_address_from_str(info, nettype, *address)) return info; - } else { - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid address: "s + std::string{addr_or_url}}; - } - } else { - cryptonote::address_parse_info info; - if (!get_account_address_from_str_or_url(info, nettype, addr_or_url, - [](const std::string_view url, const std::vector &addresses, bool dnssec_valid) { - if (!dnssec_valid) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid DNSSEC for "s + std::string{url}}; - if (addresses.empty()) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "No Oxen address found at "s + std::string{url}}; - return addresses[0]; - })) - throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid address: "s + std::string{addr_or_url}}; - return info; } - return {}; + else if (get_account_address_from_str(info, nettype, addr)) + return info; + + throw wallet_rpc_error{error_code::WRONG_ADDRESS, "Invalid address: "s + std::string{addr}}; } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::validate_transfer(const std::list& destinations, const std::string& payment_id, std::vector& dsts, std::vector& extra, bool at_least_one_destination) diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp index c8659f70b..deaa85658 100644 --- a/tests/fuzz/signature.cpp +++ b/tests/fuzz/signature.cpp @@ -57,7 +57,7 @@ int SignatureFuzzer::init() wallet.generate("", "", spendkey, true, false); cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str_or_url(info, cryptonote::TESTNET, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN")) + if (!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN")) { std::cerr << "failed to parse address" << std::endl; return 1; diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 8ed825033..9c4bd32fa 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -29,7 +29,6 @@ add_executable(unit_tests account.cpp apply_permutation.cpp - address_from_url.cpp base58.cpp blockchain_db.cpp block_queue.cpp @@ -40,7 +39,6 @@ add_executable(unit_tests command_line.cpp crypto.cpp device.cpp - dns_resolver.cpp epee_boosted_tcp_server.cpp epee_levin_protocol_handler_async.cpp epee_utils.cpp diff --git a/tests/unit_tests/address_from_url.cpp b/tests/unit_tests/address_from_url.cpp deleted file mode 100644 index 805ed99f7..000000000 --- a/tests/unit_tests/address_from_url.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// 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. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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. - -// FIXME: move this into a full wallet2 unit test suite, if possible - -#include "gtest/gtest.h" - -#include "wallet/wallet2.h" -#include "common/dns_utils.h" -#include "simplewallet/simplewallet.h" -#include - -TEST(AddressFromTXT, Success) -{ - std::string addr = "46BeWrHpwXmHDpDEUmZBWZfoQpdc6HaERCNmx1pEYL2rAcuwufPN9rXHHtyUA4QVy66qeFQkn6sfK8aHYjA3jk3o1Bv16em"; - - std::string txtr = "oa1:xmr"; - txtr += " recipient_address="; - txtr += addr; - txtr += ";"; - - std::string res = tools::dns_utils::address_from_txt_record(txtr); - - EXPECT_STREQ(addr.c_str(), res.c_str()); - - std::string txtr2 = "foobar"; - - txtr2 += txtr; - - txtr2 += "more foobar"; - - res = tools::dns_utils::address_from_txt_record(txtr2); - - EXPECT_STREQ(addr.c_str(), res.c_str()); - - std::string txtr3 = "foobar oa1:xmr tx_description=\"Donation for Monero Development Fund\"; "; - txtr3 += "recipient_address="; - txtr3 += addr; - txtr3 += "; foobar"; - - res = tools::dns_utils::address_from_txt_record(txtr3); - - EXPECT_STREQ(addr.c_str(), res.c_str()); -} - -TEST(AddressFromTXT, Failure) -{ - std::string txtr = "oa1:xmr recipient_address=not a real address"; - - std::string res = tools::dns_utils::address_from_txt_record(txtr); - - ASSERT_STREQ("", res.c_str()); - - txtr += ";"; - - res = tools::dns_utils::address_from_txt_record(txtr); - ASSERT_STREQ("", res.c_str()); -} - -TEST(AddressFromURL, Success) -{ - const std::string addr = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H"; - - bool dnssec_result = false; - - std::vector addresses = tools::dns_utils::addresses_from_url("donate.getmonero.org", dnssec_result); - - EXPECT_EQ(1, addresses.size()); - if (addresses.size() == 1) - { - EXPECT_STREQ(addr.c_str(), addresses[0].c_str()); - } - - // OpenAlias address with an @ instead of first . - addresses = tools::dns_utils::addresses_from_url("donate@getmonero.org", dnssec_result); - EXPECT_EQ(1, addresses.size()); - if (addresses.size() == 1) - { - EXPECT_STREQ(addr.c_str(), addresses[0].c_str()); - } -} - -TEST(AddressFromURL, Failure) -{ - bool dnssec_result = false; - - std::vector addresses = tools::dns_utils::addresses_from_url("example.veryinvalid", dnssec_result); - - // for a non-existing domain such as "example.invalid", the non-existence is proved with NSEC records - ASSERT_TRUE(dnssec_result); - - ASSERT_EQ(0, addresses.size()); -} diff --git a/tests/unit_tests/dns_resolver.cpp b/tests/unit_tests/dns_resolver.cpp deleted file mode 100644 index 293e6655b..000000000 --- a/tests/unit_tests/dns_resolver.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// 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. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 -#include - -#include "gtest/gtest.h" - -#include "common/dns_utils.h" - -TEST(DNSResolver, IPv4Success) -{ - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv4("example.com", avail, valid); - - ASSERT_EQ(1, ips.size()); - - //ASSERT_STREQ("93.184.216.119", ips[0].c_str()); - - ips = tools::DNSResolver::instance().get_ipv4("example.com", avail, valid); - - ASSERT_EQ(1, ips.size()); - - //ASSERT_STREQ("93.184.216.119", ips[0].c_str()); -} - -TEST(DNSResolver, IPv4Failure) -{ - // guaranteed by IANA/ICANN/RFC to be invalid - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv4("example.invalid", avail, valid); - - ASSERT_EQ(0, ips.size()); - - ips = tools::DNSResolver::instance().get_ipv4("example.invalid", avail, valid); - - ASSERT_EQ(0, ips.size()); -} - -TEST(DNSResolver, DNSSECSuccess) -{ - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv4("example.com", avail, valid); - - ASSERT_EQ(1, ips.size()); - - //ASSERT_STREQ("93.184.216.119", ips[0].c_str()); - - ASSERT_TRUE(avail); - ASSERT_TRUE(valid); -} - -TEST(DNSResolver, DNSSECFailure) -{ - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv4("dnssec-failed.org", avail, valid); - - ASSERT_EQ(1, ips.size()); - - //ASSERT_STREQ("93.184.216.119", ips[0].c_str()); - - ASSERT_TRUE(avail); - ASSERT_FALSE(valid); -} - -// It would be great to include an IPv6 test and assume it'll pass, but not every ISP / resolver plays nicely with IPv6;) -/*TEST(DNSResolver, IPv6Success) -{ - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv6("example.com", avail, valid); - - ASSERT_EQ(1, ips.size()); - - ASSERT_STREQ("2606:2800:220:6d:26bf:1447:1097:aa7", ips[0].c_str()); - - ips = tools::DNSResolver::instance().get_ipv6("example.com", avail, valid); - - ASSERT_EQ(1, ips.size()); - - ASSERT_STREQ("2606:2800:220:6d:26bf:1447:1097:aa7", ips[0].c_str()); -}*/ - -TEST(DNSResolver, IPv6Failure) -{ - // guaranteed by IANA/ICANN/RFC to be invalid - tools::DNSResolver resolver = tools::DNSResolver::create(); - - bool avail, valid; - - auto ips = resolver.get_ipv6("example.invalid", avail, valid); - - ASSERT_EQ(0, ips.size()); - - ips = tools::DNSResolver::instance().get_ipv6("example.invalid", avail, valid); - - ASSERT_EQ(0, ips.size()); -} - -TEST(DNSResolver, GetTXTRecord) -{ - bool avail, valid; - - std::vector records = tools::DNSResolver::instance().get_txt_record("donate.getmonero.org", avail, valid); - - EXPECT_NE(0, records.size()); - - for (auto& rec : records) - { - std::cout << "TXT record for donate.getmonero.org: " << rec << std::endl; - } - - // replace first @ with . - std::string addr = tools::DNSResolver::instance().get_dns_format_from_oa_address("donate@getmonero.org"); - EXPECT_STREQ("donate.getmonero.org", addr.c_str()); - - // no change - addr = tools::DNSResolver::instance().get_dns_format_from_oa_address("donate.getmonero.org"); - EXPECT_STREQ("donate.getmonero.org", addr.c_str()); -} - -TEST(DNSResolver, GetMulti) -{ - auto records = tools::DNSResolver::instance().get_many(tools::DNS_TYPE_A, {"oxen.io", "example.invalid", "lokinet.org"}); - EXPECT_EQ(records.size(), 3); - EXPECT_TRUE(records[0].size() > 0); - EXPECT_EQ(records[1].size(), 0); - EXPECT_TRUE(records[2].size() > 0); -} - -std::vector testval(const char* s) { return {{s}}; } - -TEST(DNS_PUBLIC, empty) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("").empty()); } -TEST(DNS_PUBLIC, default) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp").size() > 0); } -TEST(DNS_PUBLIC, invalid_scheme) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("invalid").empty()); } -TEST(DNS_PUBLIC, invalid_ip_alpha) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://invalid").empty()); } -TEST(DNS_PUBLIC, invalid_ip_num1) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3").empty()); } -TEST(DNS_PUBLIC, invalid_ip_num3) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4.5").empty()); } -TEST(DNS_PUBLIC, invalid_ip_num4_extra) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4.5.6x").empty()); } -TEST(DNS_PUBLIC, invalid_ip_num4_range) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4.542.6").empty()); } -TEST(DNS_PUBLIC, invalid_ip_dot) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4.5.6.").empty()); } -TEST(DNS_PUBLIC, invalid_ip_num5) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4.5.6.7").empty()); } -TEST(DNS_PUBLIC, invalid_ip_4_missing) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("tcp://3.4..7").empty()); } -TEST(DNS_PUBLIC, valid_ip_lo) { EXPECT_EQ(testval("127.0.0.1"), tools::dns_utils::parse_dns_public("tcp://127.0.0.1")); } -TEST(DNS_PUBLIC, valid_ip) { EXPECT_EQ(testval("3.4.5.6"), tools::dns_utils::parse_dns_public("tcp://3.4.5.6")); }