diff --git a/.gitignore b/.gitignore index fbd81fc..b6b324c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ release *.o *.moc tests/*/tst_* +src/tests/*/tst_* !tst_*.pro !tst_*.cpp !tst_*.h @@ -22,7 +23,7 @@ tests/*/tst_* *.pb.cc packaging/installer/Qt packaging/installer/Output -translation/*.qm +src/tego_ui/translation/*.qm config config.ricochet config.log @@ -31,13 +32,17 @@ config.tests/*/* !config.tests/*/*.cpp !config.tests/*/*.h ricochet +src/ricochet.log build-tests* buildscripts/src/ricochet-refresh buildscripts/output buildscripts/lib target_wrapper\.sh moc_predefs.h +moc_*.cpp +qrc_*.cpp +ricochet-refresh +*.gch \.vscode/c_cpp_properties\.json - \.vscode/ notes/* diff --git a/.gitmodules b/.gitmodules index c242ba3..9e250b5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,6 @@ -[submodule "buildscripts/src/openssl"] - path = buildscripts/src/openssl - url = https://github.com/openssl/openssl.git -[submodule "buildscripts/src/tor"] - path = buildscripts/src/tor +[submodule "src/extern/fmt"] + path = src/extern/fmt + url = https://github.com/fmtlib/fmt.git +[submodule "src/extern/tor"] + path = src/extern/tor url = https://git.torproject.org/tor.git -[submodule "buildscripts/src/protobuf"] - path = buildscripts/src/protobuf - url = https://github.com/google/protobuf.git -[submodule "buildscripts/src/qt5"] - path = buildscripts/src/qt5 - url = https://github.com/qtproject/qt5.git -[submodule "buildscripts/src/libevent"] - path = buildscripts/src/libevent - url = https://github.com/libevent/libevent diff --git a/README.md b/README.md index 7d5f623..53a593c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ +# WORK IN PROGRESS PROJECT REPOSITORY - NOT FOR PRODUCTION USE + +## Tego-Core +Tego-Core is the work in progress repository for Ricochet Refresh. We are in the process of making significant changes to Ricochet Refresh to implement V3 Onion Service support as well as some exciting new features. The change to V3 Onion Services will not be backwards compatible with V2, which is the version currently implemented in Ricochet Refresh. As such, we are keeping development separate until we are ready to release a V3 Onion Services version of Ricochet Refresh. + +As noted above, this is a work in progress repository and should not be used in production. Security protocols may not be fully implemented or tested during the development process. + +Existing README is continued below. + ## R2: Ricochet Refresh Ricochet Refresh is the new updated version of Ricochet, supported by Blueprint for Free Speech.. We are a non-government, not-for-profit organisation working to safeguard the freedom of expression for whistleblowers, activists, and everybody else, worldwide. To find out more, check out our profile, or head to [http://blueprintforfreespeech.net]. Blueprint was the original sponsor of Ricochet, written by developer J. Brooks. diff --git a/buildscripts/README.md b/buildscripts/README.md deleted file mode 100644 index ebbd72b..0000000 --- a/buildscripts/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Ricochet Refresh Build Scripts ----------------------- - -These are the scripts and instructions used to build distribution binaries for Ricochet Refresh, for various platforms. - -If you don't know what Ricochet Refresh is or you're trying to find pre-built binaries, you're probably more interested in the [main repository](https://github.com/blueprint-freespeech/ricochet-refresh) or [website](https://ricochet.im/). - -If you want to build your own Ricochet Refresh for local use, there are general [build instructions](https://github.com/blueprint-freespeech/ricochet-refresh/blob/master/BUILDING.md). These scripts might still be useful to you, because they take care of all dependencies and create redistributable binaries. - -Platforms ---------- - -*linux-static* creates a portable Linux binary that statically links all non-standard libraries. It's intended to be a best-effort at creating one binary that can run unmodified on most modern Linux systems. The scripts are tailored to build from a Debian stable machine, but the resulting binaries should be compatible with many distributions. - -*mingw-cross* cross-compiles 32bit Windows binaries using the MinGW-w64 toolchain. It's compatible with mingw packages included in many distributions. This is the recommended way to build for Windows machines. - -*mingw* builds from a MSYS2/MinGW-w64 environment on Windows. This can be difficult to get working correctly, so cross-compilation is often a better choice. - -*osx* builds a MacOS self-contained .app and packages it into .dmg. This requires MacOS with xcode and commandline tools. - -Building --------- - -See individual directories for build instructions. Generally, set `MAKEOPTS=-j6`, run `./platform/build-deps.sh`, checkout the commit you want to `src/ricochet`, and run `./platform/build.sh` - -If a submodule has changed versions since the last time you ran a build, you will need to run `git submodule foreach --recursive git clean -x -f -d` to get submodules to a consistent state. - -In the case of macOS, you can specify these flags to just use the brew versions of each library (since it's impossible to build qt5 on macOS Mojave) `USE_LOCAL_QT=1 USE_LOCAL_OPENSSL=1 USE_LOCAL_TOR=1 USE_LOCAL_PROTOBUF=1 osx/make-deps.sh` diff --git a/buildscripts/common_functions.sh b/buildscripts/common_functions.sh deleted file mode 100755 index 59943ed..0000000 --- a/buildscripts/common_functions.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# Describe the current version of the repo using git -git_version() { - git describe --tags HEAD --always 2>/dev/null || git rev-parse --short HEAD -} diff --git a/buildscripts/get_build_name.sh b/buildscripts/get_build_name.sh deleted file mode 100755 index b09d1ef..0000000 --- a/buildscripts/get_build_name.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -source common_functions.sh - -RICOCHET_VERSION="$(git_version)" -TOR_VERSION="$(cd src/tor && git_version)" -OPENSSL_VERSION="$(cd src/openssl && git_version)" -echo "ricochet-${RICOCHET_VERSION} tor-${TOR_VERSION} openssl-${OPENSSL_VERSION}" diff --git a/buildscripts/linux-static/Dockerfile b/buildscripts/linux-static/Dockerfile deleted file mode 100644 index 407e799..0000000 --- a/buildscripts/linux-static/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -FROM ubuntu:18.04 - -RUN set -ex; \ - apt-get update \ - && apt-get install -y --no-install-recommends \ - automake \ - autotools-dev \ - build-essential \ - ca-certificates \ - curl \ - git \ - libasound2-dev \ - libevent-dev \ - libfontconfig1 \ - libfontconfig1-dev \ - libfreetype6 \ - libfreetype6-dev \ - libglu1-mesa-dev \ - libprotobuf-dev \ - libqt5gui5 \ - libqt5opengl5 \ - libqt5opengl5-dev \ - libqt5svg5 \ - libssl-dev \ - libtool \ - libx11-xcb-dev \ - '^libxcb.*' \ - '^libxkb.*' \ - libxrender-dev \ - libxrender1 \ - pkg-config \ - protobuf-compiler \ - python \ - qt5-default \ - qt5-qmake \ - qtbase5-dev \ - qtdeclarative5-dev \ - qttools5-dev-tools \ - tor \ - unzip \ - vim \ - xkb-data \ - xvfb \ - && apt-get autoremove -y -qq \ - && rm -rf /var/lib/apt/lists/* \ - && rm -rf /var/cache/man/* \ - && rm -rf /usr/share/doc/* \ - && rm -rf /usr/share/man/* \ - && rm -rf /usr/share/zoneinfo/* - -WORKDIR /root -RUN git clone https://github.com/blueprint-freespeech/ricochet-refresh -WORKDIR /root/ricochet-refresh/buildscripts/ -RUN linux-static/build-deps.sh - diff --git a/buildscripts/linux-static/README.md b/buildscripts/linux-static/README.md deleted file mode 100644 index a0432df..0000000 --- a/buildscripts/linux-static/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This is a very simple set of scripts to build Ricochet with a statically linked Qt, Tor, and OpenSSL. It produces a tarball that is generally usable on most modern linux installations. - -This is only tested on Debian 7. It builds an entire copy of Qt, which requires several GB of disk space and considerable time. - -In your preferred build directory, run `setup.sh` to clone repositories, and `build.sh` to pull, configure, and build them all. If all goes well, src/ricochet/build/ will contain a tar.bz2 at the end. - -Contributions to improve this process are welcome. diff --git a/buildscripts/linux-static/build-deps.sh b/buildscripts/linux-static/build-deps.sh deleted file mode 100755 index 3804e3b..0000000 --- a/buildscripts/linux-static/build-deps.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/bin/bash - -set -ex - -ROOT_SRC="$(pwd)/src" -ROOT_LIB="$(pwd)/lib" -BUILD_OUTPUT="$(pwd)/output" -# MAKEOPTS="-j$(nproc)" -test -e "${ROOT_SRC}" -test -e "${ROOT_LIB}" && rm -r "${ROOT_LIB}" -mkdir "${ROOT_LIB}" -test -e "${BUILD_OUTPUT}" && rm -r "${BUILD_OUTPUT}" -mkdir "${BUILD_OUTPUT}" - -# Build dependencies -git submodule update --init -pushd "$ROOT_SRC" - # Qt - pushd qt5 - if [[ -z $USE_LOCAL_QT ]]; then - git submodule deinit --all -f - git submodule update --init qtbase qtdeclarative qtgraphicaleffects qtimageformats qtquickcontrols qtsvg qtx11extras qttools qtmultimedia - git submodule foreach --recursive git reset --hard - git reset --hard - # Missing configure options - # -no-feature-concurrent \ - # -no-feature-dbus \ - # -no-feature-dom \ - # -no-feature-errormessage \ - # -no-feature-freetype \ - # -no-feature-im \ - # -no-feature-image_heuristic_mask \ - # -no-feature-image_text \ - # -no-feature-imageformat_bmp \ - # -no-feature-imageformat_jpeg \ - # -no-feature-imageformat_png \ - # -no-feature-imageformat_ppm \ - # -no-feature-imageformat_xbm \ - # -no-feature-mimetype \ - # -no-feature-process \ - # -no-feature-sharedmemory \ - # -no-feature-systemsemaphore \ - # -skip qtdeclarative \ - # -skip qtimageformats \ - # -skip qtmultimedia \ - # -skip qtquickcontrols \ - # -skip qtquickcontrols2 \ - # -skip qtsvg \ - # -skip qttools \ - # -skip qttranslations \ - # -skip qtx11extras \ - # - ./configure \ - -confirm-license \ - -fontconfig \ - -no-compile-examples \ - -no-cups \ - -no-feature-bearermanagement \ - -no-feature-big_codecs \ - -no-feature-calendarwidget \ - -no-feature-codecs \ - -no-feature-colordialog \ - -no-feature-colornames \ - -no-feature-completer \ - -no-feature-cups \ - -no-feature-datawidgetmapper \ - -no-feature-desktopservices \ - -no-feature-effects \ - -no-feature-filedialog \ - -no-feature-filesystemmodel \ - -no-feature-filesystemwatcher \ - -no-feature-fontdialog \ - -no-feature-fscompleter \ - -no-feature-ftp \ - -no-feature-gestures \ - -no-feature-graphicseffect \ - -no-feature-graphicsview \ - -no-feature-iconv \ - -no-feature-inputdialog \ - -no-feature-keysequenceedit \ - -no-feature-networkdiskcache \ - -no-feature-networkproxy \ - -no-feature-paint_debug \ - -no-feature-printpreviewdialog \ - -no-feature-printpreviewwidget \ - -no-feature-progressdialog \ - -no-feature-sizegrip \ - -no-feature-socks5 \ - -no-feature-statemachine \ - -no-feature-systemtrayicon \ - -no-feature-texthtmlparser \ - -no-feature-textodfwriter \ - -no-feature-translation \ - -no-feature-udpsocket \ - -no-feature-undocommand \ - -no-feature-undogroup \ - -no-feature-undostack \ - -no-feature-undoview \ - -no-feature-wizard \ - -no-openssl \ - -no-qml-debug \ - -nomake examples \ - -nomake tests \ - -opensource \ - -prefix "${ROOT_LIB}/qt5/" \ - -qt-freetype \ - -qt-libjpeg \ - -qt-libpng \ - -qt-pcre \ - -qt-xcb \ - -qt-zlib \ - -release \ - -skip qt3d \ - -skip qtandroidextras \ - -skip qtcanvas3d \ - -skip qtcharts \ - -skip qtconnectivity \ - -skip qtdatavis3d \ - -skip qtdoc \ - -skip qtgamepad \ - -skip qtgraphicaleffects \ - -skip qtlocation \ - -skip qtmacextras \ - -skip qtnetworkauth \ - -skip qtpurchasing \ - -skip qtscript \ - -skip qtscxml \ - -skip qtsensors \ - -skip qtserialbus \ - -skip qtserialport \ - -skip qtspeech \ - -skip qtvirtualkeyboard \ - -skip qtwayland \ - -skip qtwebchannel \ - -skip qtwebengine \ - -skip qtwebsockets \ - -skip qtwebview \ - -skip qtwinextras \ - -skip qtxmlpatterns \ - -static \ - -system-freetype \ - -xkbcommon - make ${MAKEOPTS} - make install - if [ ! -f "${ROOT_LIB}/qt5/bin/qmake" ]; then - ln -s "$(pwd)/qtbase/bin/qmake" "${ROOT_LIB}/qt5/bin/qmake" - fi - fi - export PATH="${ROOT_LIB}/qt5/bin:${PATH}" - popd - - if ! command -v qmake; then - echo "qmake not found" - exit 1 - fi - - # Openssl - pushd openssl - if [[ -n $USE_LOCAL_OPENSSL ]]; then - OPENSSL_DIR="$(pkg-config --variable=libdir openssl)" - else - OPENSSL_DIR="${ROOT_LIB}/openssl" - git clean -dfx . - git reset --hard - ./config no-shared no-zlib no-dso "--prefix=${OPENSSL_DIR}" "--openssldir=${OPENSSL_DIR}" -fPIC - make -j1 - make install_sw - fi - popd - - # Libevent - pushd libevent - if [[ -n $USE_LOCAL_LIBEVENT ]]; then - LIBEVENT_DIR="$(pkg-config --variable=libdir libevent)" - else - LIBEVENT_DIR="${ROOT_LIB}/libevent" - git clean -dfx . - git reset --hard - ./autogen.sh - ./configure "--prefix=${LIBEVENT_DIR}" --disable-openssl - make ${MAKEOPTS} - make install - fi - popd - - # Tor - pushd tor - git clean -dfx . - git reset --hard - ./autogen.sh - CFLAGS=-fPIC ./configure \ - --prefix="${ROOT_LIB}/tor" \ - --with-openssl-dir="${ROOT_LIB}/openssl/" \ - --with-libevent-dir="${ROOT_LIB}/libevent/" \ - --with-zlib-dir="$(pkg-config --variable=libdir zlib)" \ - --enable-static-tor --disable-asciidoc - - make ${MAKEOPTS} - make install - cp "${ROOT_LIB}/tor/bin/tor" "${BUILD_OUTPUT}/" - popd - - # Protobuf - pushd protobuf - if [[ -z $USE_LOCAL_PROTOBUF ]]; then - git clean -dfx . - git reset --hard - - # Protobuf will rudely fetch this over HTTP if it isn't present.. - if [ ! -e gtest ]; then - git clone https://github.com/google/googletest.git gtest - pushd gtest - git checkout release-1.5.0 - popd - fi - - ./autogen.sh - ./configure "--prefix=${ROOT_LIB}/protobuf/" --disable-shared --without-zlib --with-pic - make ${MAKEOPTS} - make install - fi - popd - -popd -echo "build-deps: done" diff --git a/buildscripts/linux-static/build.sh b/buildscripts/linux-static/build.sh deleted file mode 100755 index 9cbf7a6..0000000 --- a/buildscripts/linux-static/build.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -set -ex - -source common_functions.sh -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output -MAKEOPTS="-j$(nproc)" - -pushd .. - RICOCHET_VERSION=$(git_version) - - test -e build && rm -r build - mkdir build - pushd build - - export PKG_CONFIG_PATH="${ROOT_LIB}/protobuf/lib/pkgconfig:${PKG_CONFIG_PATH}" - export PATH="${ROOT_LIB}/qt5/bin/:${ROOT_LIB}/protobuf/bin/:${PATH}" - printf "qmake -query: \n%s" "$(qmake -query)" - qmake CONFIG+=release OPENSSLDIR="${ROOT_LIB}/openssl/" .. - make ${MAKEOPTS} - cp ricochet-refresh "${BUILD_OUTPUT}/ricochet-refresh-unstripped" - strip ricochet-refresh - - mkdir -p staging/ricochet-refresh - cp ricochet-refresh staging/ricochet-refresh - cp "${BUILD_OUTPUT}/tor" staging/ricochet-refresh - # cp -r ../packaging/linux-static/content/* staging/ricochet-refresh/ - - echo "ldd" - ldd ricochet-refresh - - pushd staging - tar cfj "${BUILD_OUTPUT}/ricochet-refresh-${RICOCHET_VERSION}-static.tar.bz2" ricochet-refresh - popd - popd -popd - -echo "---------------------" -ls -la "${BUILD_OUTPUT}/" -echo "build: done" diff --git a/buildscripts/linux-static/setup.sh b/buildscripts/linux-static/setup.sh deleted file mode 100755 index abdf717..0000000 --- a/buildscripts/linux-static/setup.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Run inside a new, Debian-based container to set up a build environment the first time - -set -e - -apt-get install -y git build-essential python curl vim unzip libtool - -# Qt -apt-get install -y "^libxcb.*" libx11-xcb-dev libglu1-mesa-dev libxrender-dev -apt-get install -y libfontconfig1-dev libglu1-mesa-dev libxrender-dev xkb-data -apt-get install -y libasound2-dev - -# Tor -apt-get install -y autoconf automake - diff --git a/buildscripts/linux-static/test.sh b/buildscripts/linux-static/test.sh deleted file mode 100755 index 559512d..0000000 --- a/buildscripts/linux-static/test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -ROOT_LIB=$(pwd)/lib -OPENSSLDIR="${OPENSSLDIR:-${ROOT_LIB}/openssl/}" - -pushd "../tests" - export PKG_CONFIG_PATH=${ROOT_LIB}/protobuf/lib/pkgconfig:${PKG_CONFIG_PATH} - export PATH="${ROOT_LIB}/protobuf/bin/:${ROOT_LIB}/qt5/bin:${PATH}" - - qmake tests.pro CONFIG+=x86_64 CONFIG+=qtquickcompiler "OPENSSLDIR=$OPENSSLDIR" && make qmake_all && make - TESTS=$(find . -type f -regextype sed -regex "./.*\(test_\|tst_\)[^/]*" -executable) - - if [ -n "$HEADLESS" ]; then - Xvfb :1 -screen 0 800x600x16 & - echo "$TESTS" | while read -r test; do xvfb-run -e /dev/stderr -a "$test" || exit $?; done - else - echo "$TESTS" | while read -r test; do "$test" || exit $?; done - fi -popd - diff --git a/buildscripts/mingw-cross/0001-windeployqt-Hack-to-use-objdump-for-PE-parsing.patch b/buildscripts/mingw-cross/0001-windeployqt-Hack-to-use-objdump-for-PE-parsing.patch deleted file mode 100644 index 89dc983..0000000 --- a/buildscripts/mingw-cross/0001-windeployqt-Hack-to-use-objdump-for-PE-parsing.patch +++ /dev/null @@ -1,105 +0,0 @@ -From f27bd6b818ec50408bcf58947ef7d2967202ddc5 Mon Sep 17 00:00:00 2001 -From: John Brooks -Date: Tue, 1 Nov 2016 15:32:41 -0600 -Subject: [PATCH] windeployqt: Hack to use objdump for PE parsing - -Hackishly use objdump to parse imports in PE executables, allowing -windeployqt to work for cross-compile MinGW environments. - -Also, hardcode the MinGW sysroot bin path, so windeployqt can find -compiler binaries. - -Also, include libssp with the deployed compiler binaries, because I need -it. Ideally these would be based on imports also. - -This is not suitable to upstream, but smarter PE parsing should be. ---- - src/windeployqt/main.cpp | 6 +++++- - src/windeployqt/utils.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++---- - 2 files changed, 48 insertions(+), 5 deletions(-) - -diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp -index 9b82628..31e6de3 100644 ---- a/src/windeployqt/main.cpp -+++ b/src/windeployqt/main.cpp -@@ -1013,13 +1013,17 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned - QStringList result; - switch (platform) { - case WindowsMinGW: { // MinGW: Add runtime libraries -- static const char *minGwRuntimes[] = {"*gcc_", "*stdc++", "*winpthread"}; -+ static const char *minGwRuntimes[] = {"*gcc_", "*stdc++", "*winpthread", "libssp*"}; -+#ifdef Q_OS_WIN - const QString gcc = findInPath(QStringLiteral("g++.exe")); - if (gcc.isEmpty()) { - std::wcerr << "Warning: Cannot find GCC installation directory. g++.exe must be in the path.\n"; - break; - } - const QString binPath = QFileInfo(gcc).absolutePath(); -+#else -+ const QString binPath = QStringLiteral("/usr/i686-w64-mingw32/sys-root/mingw/bin/"); -+#endif - QDir dir(binPath); - QStringList filters; - const QString suffix = QLatin1Char('*') + sharedLibrarySuffix(platform); -diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp -index a29b38b..dcf9bb3 100644 ---- a/src/windeployqt/utils.cpp -+++ b/src/windeployqt/utils.cpp -@@ -931,11 +931,50 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor - - #else // Q_OS_WIN - --bool readPeExecutable(const QString &, QString *errorMessage, -- QStringList *, unsigned *, bool *, bool) -+bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage, -+ QStringList *dependentLibrariesIn, unsigned *wordSizeIn, -+ bool *isDebugIn, bool) - { -- *errorMessage = QStringLiteral("Not implemented."); -- return false; -+ // XXX unsafe shell -+ FILE *f = popen(QStringLiteral("objdump -p %1 | grep 'DLL Name:'").arg(peExecutableFileName).toLocal8Bit(), "r"); -+ if (!f) { -+ if (errorMessage) -+ *errorMessage = QString::fromLocal8Bit(strerror(errno)); -+ return false; -+ } -+ -+ QByteArray output; -+ for (;;) { -+ char buf[1024]; -+ int r = fread(buf, sizeof(char), sizeof(buf), f); -+ if (r <= 0) { -+ if (feof(f)) { -+ break; -+ } else { -+ if (errorMessage) -+ *errorMessage = QString::fromLocal8Bit(strerror(errno)); -+ pclose(f); -+ return false; -+ } -+ } -+ output.append(buf, r); -+ } -+ pclose(f); -+ -+ QStringList libs; -+ QByteArray prefix("\tDLL Name: "); -+ foreach (const QByteArray &line, output.split('\n')) -+ libs << QString::fromLatin1(line.mid(prefix.size()).trimmed()); -+ -+ // XXX Assuming 32bit -+ if (wordSizeIn) -+ *wordSizeIn = 32; -+ // XXX Assuming release -+ if (isDebugIn) -+ *isDebugIn = false; -+ if (dependentLibrariesIn) -+ *dependentLibrariesIn = libs; -+ return true; - } - - QString findD3dCompiler(Platform, const QString &, unsigned) --- -2.7.4 - diff --git a/buildscripts/mingw-cross/README.md b/buildscripts/mingw-cross/README.md deleted file mode 100644 index 4cd0c4a..0000000 --- a/buildscripts/mingw-cross/README.md +++ /dev/null @@ -1,50 +0,0 @@ -These scripts will cross-compile Ricochet for Windows from a unixy system with the MinGW toolchain available. - -Prerequisites -------------- - -Install the mingw-w64 32bit toolchain, which is often available through package management. - -Fedora (as of 24) needs the following packages: - -``` -python -m4 autoconf automake flex bison libtool -mingw32-filesystem mingw32-crt mingw32-headers mingw32-bintuils mingw32-cpp mingw32-gcc mingw32-gcc-c++ -mingw32-pkg-config mingw32-zlib-static mingw32-winpthreads-static -``` - -The `0001-windeployqt-Hack-to-use-objdump-for-PE-parsing.patch` patch assumes a 32bit release build, and assumes that compiler library DLLs are in `/usr/i686-w64-mingw32/sys-root/mingw/bin/`. If these aren't true, you should modify the patch. A better solution is needed here. - -Build dependencies ------------------- - -All other dependencies are included as submodules of this repository. The scripts will handle init/update of the submodules. Dependencies are installed to `lib` under this repository. Nothing is installed or changed outside of this repository directory. - -Build dependencies with: - -``` -export MAKEOPTS=-j6 # Or whatever -j value you prefer -./mingw-cross/build-deps.sh -``` - -Build Ricochet --------------- - -Clone ricochet under the `src/` directory. If you want to build something other than `master`, checkout the branch/commit of your choice. - -``` -cd src -git clone https://github.com/ricochet-im/ricochet -``` - -The build script will not change HEAD or discard working copy changes in the ricochet repository, **but** it will be fully `git clean`ed (including untracked files) for every build. - -Build packages with: - -``` -./mingw-cross/build.sh -``` - -If successful, the `output` directory will contain `ricochet-VERSION.zip` and `ricochet-VERSION-installer-build.zip` as well as `tor.exe` and `ricochet.exe`. The zip files contain all necessary libraries and files. The `-installer-build.zip` file is not suitable to use directly, but contains everything necessary to build the installer with a copy of Inno Setup. - diff --git a/buildscripts/mingw-cross/build-deps.sh b/buildscripts/mingw-cross/build-deps.sh deleted file mode 100755 index ee18175..0000000 --- a/buildscripts/mingw-cross/build-deps.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -set -e - -ROOT_SRC=$(pwd)/src -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output -test -e "${ROOT_SRC}" -test -e "${ROOT_LIB}" && rm -r "${ROOT_LIB}" -mkdir "${ROOT_LIB}" -test -e "${BUILD_OUTPUT}" && rm -r "${BUILD_OUTPUT}" -mkdir "${BUILD_OUTPUT}" - -# Build dependencies -git submodule update --init -pushd "$ROOT_SRC" - - # Qt - pushd qt5 - git submodule update --init qtbase qtdeclarative qtimageformats qtquickcontrols qttools qttranslations qtwinextras qtmultimedia - git submodule foreach git clean -dfx . - git submodule foreach git reset --hard - pushd qttools - git apply --ignore-whitespace "${ROOT_SRC}/../mingw-cross/0001-windeployqt-Hack-to-use-objdump-for-PE-parsing.patch" - popd - ./configure -prefix "${ROOT_LIB}/qt5/" -release -opensource -confirm-license -no-dbus -no-qml-debug -no-glib -no-openssl -no-fontconfig -no-icu -qt-pcre -qt-zlib -qt-libpng -qt-libjpeg -nomake tools -nomake examples -xplatform win32-g++ -device-option "CROSS_COMPILE=/usr/bin/i686-w64-mingw32-" - make ${MAKEOPTS} - make install - popd - - # Openssl - pushd openssl - git clean -dfx . - git reset --hard - ./Configure no-shared no-zlib no-capieng --prefix="${ROOT_LIB}/openssl/" --openssldir="${ROOT_LIB}/openssl/" --cross-compile-prefix=i686-w64-mingw32- mingw - make -j1 depend - make -j1 - make install - popd - - # Libevent - pushd libevent - git clean -dfx . - git reset --hard - ./autogen.sh - ./configure --prefix="${ROOT_LIB}/libevent" --host=i686-w64-mingw32 - make ${MAKEOPTS} - make install - popd - - # Tor - pushd tor - git clean -dfx . - git reset --hard - ./autogen.sh - ./configure --prefix="${ROOT_LIB}/tor" --host=i686-w64-mingw32 --with-openssl-dir="${ROOT_LIB}/openssl/" --with-libevent-dir="${ROOT_LIB}/libevent/" --with-zlib-dir="$(i686-w64-mingw32-pkg-config --variable=libdir zlib)" --enable-static-tor --disable-asciidoc - make ${MAKEOPTS} - make install - cp "${ROOT_LIB}/tor/bin/tor.exe" "${BUILD_OUTPUT}/" - popd - - # Protobuf - pushd protobuf - git clean -dfx . - git reset --hard - # Protobuf will rudely fetch this over HTTP if it isn't present.. - if [ ! -e gtest ]; then - git clone https://github.com/google/googletest.git gtest - pushd gtest - git checkout release-1.7.0 - popd - fi - ./autogen.sh - # Build native protobuf (for the protoc compiler) - ./configure --prefix="${ROOT_LIB}/protobuf-native/" --disable-shared --without-zlib - make ${MAKEOPTS} - make install - # Build protobuf for target - make distclean - ./configure --prefix="${ROOT_LIB}/protobuf/" --host=i686-w64-mingw32 --with-protoc="${ROOT_LIB}/protobuf-native/bin/protoc" --disable-shared --without-zlib - make ${MAKEOPTS} - make install - popd -popd - -echo "build-deps: done" diff --git a/buildscripts/mingw-cross/build.sh b/buildscripts/mingw-cross/build.sh deleted file mode 100755 index f344e0b..0000000 --- a/buildscripts/mingw-cross/build.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -set -e - -ROOT_SRC=$(pwd)/src -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output - -cd "$ROOT_SRC" - -# Ricochet -test -e ricochet || git clone https://github.com/ricochet-im/ricochet.git -cd ricochet -git clean -dfx . - -RICOCHET_VERSION=$(git describe --tags HEAD) - -test -e build && rm -r build -mkdir build -cd build - -export PATH=${ROOT_LIB}/qt5/bin/:${ROOT_LIB}/protobuf-native/bin/:${PATH} -qmake CONFIG+=release OPENSSLDIR="${ROOT_LIB}/openssl/" PROTOBUFDIR="${ROOT_LIB}/protobuf/" .. -make ${MAKEOPTS} -cp release/ricochet.exe "${BUILD_OUTPUT}/" - -mkdir -p staging/ricochet -cd staging/ricochet -cp "${BUILD_OUTPUT}/ricochet.exe" . -cp "${BUILD_OUTPUT}/tor.exe" . -# windeployqt is (hackishly) patched to support reading PE binaries on non-windows -"${ROOT_LIB}/qt5/bin/windeployqt" --qmldir ../../../src/ui/qml ricochet.exe -test -e qmltooling && rm -r qmltooling -test -e imageformats && rm -r imageformats -test -e playlistformats && rm -r playlistformats -cd .. -zip -r "${BUILD_OUTPUT}/ricochet-${RICOCHET_VERSION}.zip" ricochet - -mkdir installer -cd installer -cp "${BUILD_OUTPUT}/ricochet.exe" . -cp "${BUILD_OUTPUT}/tor.exe" . -cp ../../../packaging/installer/* ../../../icons/ricochet.ico ../../../LICENSE . -mkdir translation -cp -r ../../../translation/{inno,installer_*.isl} translation -"${ROOT_LIB}/qt5/bin/windeployqt" --qmldir ../../../src/ui/qml --dir Qt ricochet.exe -test -e Qt/qmltooling && rm -r Qt/qmltooling -test -e Qt/imageformats && rm -r Qt/imageformats -test -e Qt/playlistformats && rm -r Qt/playlistformats -cd .. -zip -r "${BUILD_OUTPUT}/ricochet-${RICOCHET_VERSION}-installer-build.zip" installer -cd ../../../.. - -echo "---------------------" -ls -la "${BUILD_OUTPUT}/" -echo "build: done" diff --git a/buildscripts/mingw/0001-Workarounds-for-a-dynamic-opengl-build-under-msys.patch b/buildscripts/mingw/0001-Workarounds-for-a-dynamic-opengl-build-under-msys.patch deleted file mode 100644 index 8e7035f..0000000 --- a/buildscripts/mingw/0001-Workarounds-for-a-dynamic-opengl-build-under-msys.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 3d1d98e3edd2f0f2a881a0eeb11e5edba58e16b3 Mon Sep 17 00:00:00 2001 -From: John Brooks -Date: Mon, 11 Jan 2016 21:30:43 -0700 -Subject: [PATCH] Workarounds for a dynamic opengl build under msys - ---- - configure | 9 +++++++-- - src/angle/src/libGLESv2/libGLESv2.pro | 2 +- - 2 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/configure b/configure -index cea62fb..9605763 100755 ---- a/configure -+++ b/configure -@@ -1256,7 +1256,7 @@ while [ "$#" -gt 0 ]; do - opengl) - if [ "$VAL" = "auto" ] || [ "$VAL" = "desktop" ] || - [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || -- [ "$VAL" = "es2" ]; then -+ [ "$VAL" = "es2" ] || [ "$VAL" = "dynamic" ]; then - CFG_OPENGL="$VAL" - else - UNKNOWN_OPT=yes -@@ -6085,6 +6085,11 @@ if [ "$CFG_OPENGL" = "es2" ]; then - QT_CONFIG="$QT_CONFIG opengles2" - fi - -+if [ "$CFG_OPENGL" = "dynamic" ]; then -+ QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_DYNAMIC" -+ QT_CONFIG="$QT_CONFIG dynamicgl" -+fi -+ - if [ "$CFG_SHARED" = "yes" ]; then - QT_CONFIG="$QT_CONFIG shared" - QTCONFIG_CONFIG="$QTCONFIG_CONFIG shared" -@@ -7090,7 +7095,7 @@ report_support " OpenSSL .............." "$CFG_OPENSSL" yes "loading librarie - report_support " NIS ...................." "$CFG_NIS" - report_support " OpenGL / OpenVG:" - report_support " EGL .................." "$CFG_EGL" --report_support " OpenGL ..............." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.0+" -+report_support " OpenGL ..............." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.0+" dynamic "Dynamic" - report_support " OpenVG ..............." "$CFG_OPENVG-$CFG_OPENVG_SHIVA" yes-yes "ShivaVG" yes-no "native" - report_support " PCRE ..................." "$CFG_PCRE" yes "system library" qt "bundled copy" - if [ -n "$PKG_CONFIG" ]; then -diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro -index 5979b68..ff99c77 100644 ---- a/src/angle/src/libGLESv2/libGLESv2.pro -+++ b/src/angle/src/libGLESv2/libGLESv2.pro -@@ -555,7 +555,7 @@ angle_d3d11: SHADERS = VS_Passthrough2D \ - for (SHADER, SHADERS) { - INPUT = $$eval($${SHADER}.input) - OUT_DIR = $$OUT_PWD/libANGLE/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libANGLE)/compiled -- fxc_$${SHADER}.commands = $$FXC /nologo /E $${SHADER} /T $$eval($${SHADER}.type) /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} -+ fxc_$${SHADER}.commands = $$FXC //nologo //E $${SHADER} //T $$eval($${SHADER}.type) //Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_$${SHADER}.output = $$OUT_DIR/$$eval($${SHADER}.output) - fxc_$${SHADER}.input = $$INPUT - fxc_$${SHADER}.dependency_type = TYPE_C --- -1.9.5.github.0 - diff --git a/buildscripts/mingw/0001-fix-visibility-of-bundled-zlib-symbols-with-mingw.patch b/buildscripts/mingw/0001-fix-visibility-of-bundled-zlib-symbols-with-mingw.patch deleted file mode 100644 index 81356df..0000000 --- a/buildscripts/mingw/0001-fix-visibility-of-bundled-zlib-symbols-with-mingw.patch +++ /dev/null @@ -1,38 +0,0 @@ -From e12f54edfa3d062f2f0fd25df55468024d87eebe Mon Sep 17 00:00:00 2001 -From: John Brooks -Date: Wed, 2 Sep 2015 13:48:08 -0600 -Subject: [PATCH] fix visibility of bundled zlib symbols with mingw - -When QT_VISIBILITY_AVAILABLE is defined, the zlib header would use -visibility("default") instead of Q_DECL_EXPORT, but Windows needs -dllexport for these symbols to be available to QtGui/QtNetwork. - -In practice, Q_CORE_EXPORT always has the correct behavior for the -zlib symbols. ---- - src/3rdparty/zlib/zlib.h | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - -diff --git a/src/3rdparty/zlib/zlib.h b/src/3rdparty/zlib/zlib.h -index 5229707..d0908ab 100644 ---- a/src/3rdparty/zlib/zlib.h -+++ b/src/3rdparty/zlib/zlib.h -@@ -34,13 +34,8 @@ - #include "zconf.h" - - #include --#if defined(QT_VISIBILITY_AVAILABLE) --# undef ZEXTERN --# define ZEXTERN __attribute__((visibility("default"))) --#else --# undef ZEXTERN --# define ZEXTERN Q_DECL_EXPORT --#endif -+#undef ZEXTERN -+#define ZEXTERN Q_CORE_EXPORT - - #ifdef __cplusplus - extern "C" { --- -1.9.5.github.0 - diff --git a/buildscripts/mingw/README.txt b/buildscripts/mingw/README.txt deleted file mode 100644 index f39fcd4..0000000 --- a/buildscripts/mingw/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -Install Inno Setup 5 -Install DirectX sdk -Install msys2 according to its directions; remember the pacman commands for updating it post-install. - -There is no need to build or install Qt, Tor, or other dependencies manually. - -Run mingw32_shell.bat, and install dependencies with: - -pacman -S make perl autoconf automake pkg-config tar libtool flex bison git -pacman -S mingw32/mingw-w64-i686-gcc mingw32/mingw-w64-i686-libevent mingw32/mingw-w64-i686-zlib - -Remember to keep these packages up to date. - -Before running build.sh, you need to modify PATH to include iscc (inno setup). For example: - -export PATH=/c/Program\ Files\ \(x86\)/Inno\ Setup\ 5/:$PATH diff --git a/buildscripts/mingw/build-deps.sh b/buildscripts/mingw/build-deps.sh deleted file mode 100644 index b910f95..0000000 --- a/buildscripts/mingw/build-deps.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -set -e - -ROOT_SRC=$(pwd)/src -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output -test -e "${ROOT_SRC}" -test -e "${ROOT_LIB}" && rm -r "${ROOT_LIB}" -mkdir "${ROOT_LIB}" -test -e "${BUILD_OUTPUT}" && rm -r "${BUILD_OUTPUT}" -mkdir "${BUILD_OUTPUT}" - -# Build dependencies -git submodule update --init -pushd "$ROOT_SRC" - - # Qt - pushd qt5 - git submodule update --init qtbase qtdeclarative qtimageformats qtquickcontrols qttools qttranslations qtwinextras qtmultimedia - git submodule foreach git clean -dfx . - git submodule foreach git reset --hard - pushd qtbase - git apply --ignore-whitespace "${ROOT_SRC}/../mingw/0001-Workarounds-for-a-dynamic-opengl-build-under-msys.patch" - git apply --ignore-whitespace "${ROOT_SRC}/../mingw/0001-fix-visibility-of-bundled-zlib-symbols-with-mingw.patch" - popd - # Prefix needs to use the Windows style, not the mingw converted path - QT_PREFIX="$(cygpath -m "${ROOT_LIB}/qt5/")" - ./configure -prefix "${QT_PREFIX}" -release -opensource -confirm-license -no-dbus -no-qml-debug -no-glib -no-openssl -no-fontconfig -no-icu -qt-pcre -qt-zlib -qt-libpng -qt-libjpeg -nomake tools -nomake examples -platform win32-g++ -opengl dynamic - make ${MAKEOPTS} - make install - popd - - # Openssl - pushd openssl - # CRLF can break a perl script used by openssl's build; reset core.autocrlf on this repo - if [ "$(git config core.autocrlf)" != "false" ]; then - echo "Fixing core.autocrlf on OpenSSL repository" - git config core.autocrlf false - git rm --cached -r . - fi - git clean -dfx . - git reset --hard - ./config no-shared no-zlib --prefix="${ROOT_LIB}/openssl/" --openssldir="${ROOT_LIB}/openssl/" - make -j1 - make install - popd - - # Libevent - pushd libevent - git clean -dfx . - git reset --hard - ./autogen.sh - ./configure --prefix="${ROOT_LIB}/libevent" --disable-openssl - make ${MAKEOPTS} - make install - popd - - # Tor - pushd tor - git clean -dfx . - git reset --hard - ./autogen.sh - LIBS+=-lcrypt32 ./configure --prefix="${ROOT_LIB}/tor" --with-openssl-dir="${ROOT_LIB}/openssl/" --with-libevent-dir="${ROOT_LIB}/libevent/" --with-zlib-dir="$(pkg-config --variable=libdir zlib)" --enable-static-tor --disable-asciidoc - make ${MAKEOPTS} - make install - cp "${ROOT_LIB}/tor/bin/tor.exe" "${BUILD_OUTPUT}/" - popd - - # Protobuf - pushd protobuf - git clean -dfx . - git reset --hard - - # Protobuf will rudely fetch this over HTTP if it isn't present.. - if [ ! -e gtest ]; then - git clone https://github.com/google/googletest.git gtest - pushd gtest - git checkout release-1.5.0 - popd - fi - - ./autogen.sh - ./configure --prefix="${ROOT_LIB}/protobuf/" --disable-shared --without-zlib - make ${MAKEOPTS} - make install - popd - -popd -echo "build-deps: done" diff --git a/buildscripts/mingw/build.sh b/buildscripts/mingw/build.sh deleted file mode 100644 index 0a17273..0000000 --- a/buildscripts/mingw/build.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -e - -# Ensure PATH is set correctly -which iscc >/dev/null - -ROOT_SRC=$(pwd)/src -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output - -cd "$ROOT_SRC" - -# Ricochet -test -e ricochet || git clone https://github.com/ricochet-im/ricochet.git -cd ricochet -git clean -dfx . - -test -e build && rm -r build -mkdir build -cd build - -export PATH=${ROOT_LIB}/qt5/bin/:${ROOT_LIB}/protobuf/bin/:${PATH} -qmake CONFIG+=release OPENSSLDIR="${ROOT_LIB}/openssl/" PROTOBUFDIR="${ROOT_LIB}/protobuf/" .. -make "${MAKEOPTS}" -cp release/ricochet.exe "${BUILD_OUTPUT}/" - -mkdir installer -cd installer -cp "${BUILD_OUTPUT}/ricochet.exe" . -cp "${BUILD_OUTPUT}/tor.exe" . -"${ROOT_LIB}/qt5/bin/windeployqt" --qmldir ../../src/ui/qml --dir Qt ricochet.exe -test -e Qt/qmltooling && rm -r Qt/qmltooling -# libssp is needed for gcc's stack protector, and windeployqt won't grab it -cp "$(which libssp-0.dll)" Qt/ -cp ../../packaging/installer/* . -iscc installer.iss -cp Output/Ricochet.exe "${BUILD_OUTPUT}/setup.exe" -cd ../../.. - -echo "---------------------" -ls -la "${BUILD_OUTPUT}/" -echo "build: done" diff --git a/buildscripts/osx/README.md b/buildscripts/osx/README.md deleted file mode 100644 index 68bc095..0000000 --- a/buildscripts/osx/README.md +++ /dev/null @@ -1,8 +0,0 @@ -`build-deps.sh` - - Builds shippable versions of Qt, Tor, and OpenSSL. Assumes that a static libevent and pkg-config are available, such as through homebrew. - -`build.sh` - - Build Ricochet using those libraries. Set CODESIGN_ID in environment to sign the output; often this is "Developer ID Application". - diff --git a/buildscripts/osx/build-deps.sh b/buildscripts/osx/build-deps.sh deleted file mode 100755 index 2faf313..0000000 --- a/buildscripts/osx/build-deps.sh +++ /dev/null @@ -1,143 +0,0 @@ -#!/bin/bash - -set -ex - -ROOT_SRC=$(pwd)/src -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output -test -e "${ROOT_SRC}" -test -e "${ROOT_LIB}" && rm -rf "${ROOT_LIB}" -mkdir "${ROOT_LIB}" -test -e "${BUILD_OUTPUT}" && rm -rf "${BUILD_OUTPUT}" -mkdir "${BUILD_OUTPUT}" -MACOS_VERSION_MIN="${MACOS_VERSION_MIN:-10.7}" - -if [[ -n $USE_LOCAL_TOR ]]; then - echo "Warning: Using local tor means libevent is not statically compiled into the tor binary, making it less portable." - sleep 5 -fi - -# Build dependencies -git submodule update --init -pushd "$ROOT_SRC" - - # Qt - pushd qt5 - if [[ -n $USE_LOCAL_QT ]]; then - if ! brew info qt5 > /dev/null; then - echo "please install qt5 using brew" - exit 1 - fi - ln -s "$(brew --prefix qt5)" "${ROOT_LIB}/qt5" - else - git submodule update --init qtbase qtdeclarative qtgraphicaleffects qtimageformats qtquickcontrols qtsvg qtmacextras qttools qtmultimedia - git submodule foreach git clean -dfx . - git submodule foreach git reset --hard - ./configure -opensource -confirm-license -release \ - -no-qml-debug -no-dbus -no-openssl -no-cups \ - -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -qt-pcre \ - -nomake tests -nomake examples \ - -prefix "${ROOT_LIB}/qt5/" - make ${MAKEOPTS} - make install - fi - export PATH="$PATH:${ROOT_LIB}/qt5/bin" - popd - - if ! command -v qmake; then - echo "qmake not found" - exit 1 - fi - - # Openssl - pushd openssl - if [[ -n $USE_LOCAL_OPENSSL ]]; then - if ! brew info openssl > /dev/null; then - echo "please install openssl using brew" - exit 1 - fi - ln -s "$(brew --prefix openssl)" "${ROOT_LIB}/openssl" - else - git clean -dfx . - git reset --hard - ./Configure no-shared no-zlib "--prefix=${ROOT_LIB}/openssl/" \ - "--openssldir=${ROOT_LIB}/openssl/" -fPIC "-mmacosx-version-min=${MACOS_VERSION_MIN}" \ - darwin64-x86_64-cc - make -j1 - make install - fi - popd - - # Libevent - pushd libevent - if [[ -n $USE_LOCAL_LIBEVENT ]]; then - if ! brew info libevent > /dev/null; then - echo "please install libevent using brew" - exit 1 - fi - ln -s "$(brew --prefix libevent)" "${ROOT_LIB}/libevent" - else - git clean -dfx . - git reset --hard - # git apply "${ROOT_SRC}/../osx/libevent-0001-Forcefully-disable-clock_gettime-on-macOS-due-to-a-S.patch" - ./autogen.sh - CFLAGS="-mmacosx-version-min=${MACOS_VERSION_MIN}" ./configure "--prefix=${ROOT_LIB}/libevent" --disable-openssl - make ${MAKEOPTS} - make install - fi - popd - - # Tor - pushd tor - if [[ -n $USE_LOCAL_TOR ]]; then - if ! brew info tor > /dev/null; then - echo "please install tor using brew" - exit 1 - fi - ln -s "$(brew --prefix tor)" "${ROOT_LIB}/tor" - else - git clean -dfx . - git reset --hard - # git apply "${ROOT_SRC}/../osx/tor-0001-Forcefully-disable-getentropy-and-clock_gettime-on-m.patch" - ./autogen.sh - CFLAGS="-fPIC -mmacosx-version-min=${MACOS_VERSION_MIN}" ./configure --prefix="${ROOT_LIB}/tor" \ - --with-openssl-dir="${ROOT_LIB}/openssl/" --enable-static-openssl \ - --with-libevent-dir="${ROOT_LIB}/libevent/" --enable-static-libevent \ - --disable-asciidoc --disable-libscrypt --disable-lzma - make ${MAKEOPTS} - make install - fi - cp "${ROOT_LIB}/tor/bin/tor" "${BUILD_OUTPUT}/" - chmod +w "${BUILD_OUTPUT}/tor" - popd - - # Protobuf - pushd protobuf - if [[ -n $USE_LOCAL_PROTOBUF ]]; then - if ! brew info protobuf > /dev/null; then - echo "please install protobuf using brew" - exit 1 - fi - ln -s "$(brew --prefix protobuf)" "${ROOT_LIB}/protobuf" - else - git clean -dfx . - git reset --hard - - # Protobuf will rudely fetch this over HTTP if it isn't present.. - if [ ! -e gtest ]; then - git clone https://github.com/google/googletest.git gtest - pushd gtest - git checkout release-1.5.0 - popd - fi - - ./autogen.sh - CXX=clang++ CXXFLAGS="-mmacosx-version-min=${MACOS_VERSION_MIN} -stdlib=libc++" ./configure \ - "--prefix=${ROOT_LIB}/protobuf/" --disable-shared --without-zlib --with-pic - make ${MAKEOPTS} - make install - fi - popd - -popd -echo "build-deps: done" diff --git a/buildscripts/osx/build.sh b/buildscripts/osx/build.sh deleted file mode 100755 index e0da14b..0000000 --- a/buildscripts/osx/build.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -set -ex -source common_functions.sh -ROOT_LIB=$(pwd)/lib -BUILD_OUTPUT=$(pwd)/output - -OPENSSLDIR="${OPENSSLDIR:-${ROOT_LIB}/openssl/}" - -test -e "${BUILD_OUTPUT}/Ricochet Refresh.app" && rm -rf "${BUILD_OUTPUT}/Ricochet Refresh.app" -test -e "${BUILD_OUTPUT}/ricochet-refresh-unstripped" && rm -rf "${BUILD_OUTPUT}/ricochet-refresh-unstripped" -test -e "${BUILD_OUTPUT}/Ricochet*.dmg" && rm -rf "${BUILD_OUTPUT}/Ricochet*.dmg" - -pushd .. - RICOCHET_VERSION=$(git_version) - - test -e build && rm -r build - mkdir build - - pushd build - - export PKG_CONFIG_PATH=${ROOT_LIB}/protobuf/lib/pkgconfig:${PKG_CONFIG_PATH} - export PATH="${ROOT_LIB}/protobuf/bin/:${ROOT_LIB}/qt5/bin:${PATH}" - qmake CONFIG+=release OPENSSLDIR="$OPENSSLDIR" .. - make ${MAKEOPTS} - - cp ricochet-refresh.app/Contents/MacOS/ricochet-refresh "${BUILD_OUTPUT}/ricochet-refresh-unstripped" - cp "${BUILD_OUTPUT}/tor" "ricochet-refresh.app/Contents/MacOS" - strip ricochet-refresh.app/Contents/MacOS/* - - mv ricochet-refresh.app "Ricochet Refresh.app" - macdeployqt "Ricochet Refresh.app" -qmldir=../src/ui/qml - cp -R "Ricochet Refresh.app" "${BUILD_OUTPUT}/" - - pushd "${BUILD_OUTPUT}" - - if [ -n "$CODESIGN_ID" ]; then - codesign --verbose --sign "$CODESIGN_ID" --deep Ricochet\ Refresh.app - # Sign twice to work around a bug(?) that results in the asan library being invalid - codesign -f --verbose --sign "$CODESIGN_ID" --deep Ricochet\ Refresh.app - codesign -vvvv -d Ricochet\ Refresh.app - fi - - hdiutil create "Ricochet Refresh.dmg" -srcfolder "Ricochet Refresh.app" -format UDZO -volname "Ricochet Refresh" - codesign -f --verbose --sign "$CODESIGN_ID" --deep Ricochet\ Refresh.dmg - mv "Ricochet Refresh.dmg" "${BUILD_OUTPUT}/Ricochet-Refresh-${RICOCHET_VERSION}.dmg" - popd - popd - - echo "---------------------" - ls -la "${BUILD_OUTPUT}/" - if [ -z "$SKIP_CODESIGN" ]; then - spctl -vvvv --assess --type execute "${BUILD_OUTPUT}/Ricochet Refresh.app" - fi - echo "build: done" -popd diff --git a/buildscripts/osx/libevent-0001-Forcefully-disable-clock_gettime-on-macOS-due-to-a-S.patch b/buildscripts/osx/libevent-0001-Forcefully-disable-clock_gettime-on-macOS-due-to-a-S.patch deleted file mode 100644 index dc94456..0000000 --- a/buildscripts/osx/libevent-0001-Forcefully-disable-clock_gettime-on-macOS-due-to-a-S.patch +++ /dev/null @@ -1,33 +0,0 @@ -From bd7817e3f0f5ea7b9188788f124471fc0223c251 Mon Sep 17 00:00:00 2001 -From: John Brooks -Date: Mon, 7 Nov 2016 21:29:58 -0700 -Subject: [PATCH] Forcefully disable clock_gettime on macOS due to a SDK bug - -clock_gettime were added in macOS 10.12, but the __OSX_AVAILABLE_STARTING -macro was left off of the declaration in the SDK header, so the --mmacosx-version-min flag is ignored. This results in a libevent that links -to symbols only available on 10.12 and later. - -A cleaner, possibly upstreamable fix would be to check whether -(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12) and skip this -function test. ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index d42edd8..c616d8b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -289,7 +289,7 @@ AC_C_INLINE - AC_HEADER_TIME - - dnl Checks for library functions. --AC_CHECK_FUNCS([gettimeofday vasprintf fcntl clock_gettime strtok_r strsep]) -+AC_CHECK_FUNCS([gettimeofday vasprintf fcntl strtok_r strsep]) - AC_CHECK_FUNCS([getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getprotobynumber setenv unsetenv putenv sysctl]) - AC_CHECK_FUNCS([umask]) - --- -2.10.0 - diff --git a/buildscripts/osx/setup.sh b/buildscripts/osx/setup.sh deleted file mode 100644 index d12b93e..0000000 --- a/buildscripts/osx/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -brew install qt5 tor openssl pkg-config diff --git a/buildscripts/osx/test.sh b/buildscripts/osx/test.sh deleted file mode 100755 index b426260..0000000 --- a/buildscripts/osx/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e - -ROOT_LIB=$(pwd)/lib -OPENSSLDIR="${OPENSSLDIR:-${ROOT_LIB}/openssl/}" - -pushd "../tests" - export PKG_CONFIG_PATH=${ROOT_LIB}/protobuf/lib/pkgconfig:${PKG_CONFIG_PATH} - export PATH="${ROOT_LIB}/protobuf/bin/:${ROOT_LIB}/qt5/bin:${PATH}" - - qmake tests.pro -spec macx-clang CONFIG+=x86_64 CONFIG+=qtquickcompiler OPENSSLDIR="$OPENSSLDIR" && /usr/bin/make qmake_all - make ${MAKEOPTS} - - TESTS=$(/usr/bin/find -E . -type f -regex "./.*(test_|tst_)[^/]*" -perm +111) - - echo "$TESTS" | while read -r test; do $test || exit $?; done -popd diff --git a/buildscripts/osx/tor-0001-Forcefully-disable-getentropy-and-clock_gettime-on-m.patch b/buildscripts/osx/tor-0001-Forcefully-disable-getentropy-and-clock_gettime-on-m.patch deleted file mode 100644 index b308a4b..0000000 --- a/buildscripts/osx/tor-0001-Forcefully-disable-getentropy-and-clock_gettime-on-m.patch +++ /dev/null @@ -1,40 +0,0 @@ -From adf4cf4cb8c0e8c8753240d63aa6d68d70b8f20f Mon Sep 17 00:00:00 2001 -From: John Brooks -Date: Mon, 7 Nov 2016 21:21:13 -0700 -Subject: [PATCH] Forcefully disable getentropy and clock_gettime on macOS due - to a SDK bug - -getentropy and clock_gettime were added in macOS 10.12, but the -__OSX_AVAILABLE_STARTING macro was left off of the declaration in the SDK -header, so the -mmacosx-version-min flag is ignored. This results in a tor -that links to symbols only available on 10.12 and later. - -A cleaner, possibly upstreamable fix would be to check whether -(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12) and skip these -function tests. ---- - configure.ac | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 37827d6..e1b146a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -394,14 +394,12 @@ AC_CHECK_FUNCS( - accept4 \ - backtrace \ - backtrace_symbols_fd \ -- clock_gettime \ - eventfd \ - explicit_bzero \ - timingsafe_memcmp \ - flock \ - ftime \ - getaddrinfo \ -- getentropy \ - getifaddrs \ - getpass \ - getrlimit \ --- -2.10.0 - diff --git a/buildscripts/src/libevent b/buildscripts/src/libevent deleted file mode 160000 index 64a25bc..0000000 --- a/buildscripts/src/libevent +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 64a25bcdf54a3fc8001e76ea51e0506320567e17 diff --git a/buildscripts/src/openssl b/buildscripts/src/openssl deleted file mode 160000 index e71ebf2..0000000 --- a/buildscripts/src/openssl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e71ebf275da66dfd601c92e0e80a35114c32f6f8 diff --git a/buildscripts/src/protobuf b/buildscripts/src/protobuf deleted file mode 160000 index 582743b..0000000 --- a/buildscripts/src/protobuf +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 582743bf40c5d3639a70f98f183914a2c0cd0680 diff --git a/buildscripts/src/qt5 b/buildscripts/src/qt5 deleted file mode 160000 index 6e350af..0000000 --- a/buildscripts/src/qt5 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6e350aff34545e7b41b07617c9152f81db735702 diff --git a/buildscripts/src/tor b/buildscripts/src/tor deleted file mode 160000 index 5030edf..0000000 --- a/buildscripts/src/tor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5030edfb534245ed3f7e6b476f38a706247f3cb8 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..a35590a --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +ricochet-refresh (3.0.0) focal; urgency=medium + + * debian packaging + + -- Marco Simonelli Wed, 01 Jul 2020 16:14:29 +1000 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..c18db1f --- /dev/null +++ b/debian/control @@ -0,0 +1,19 @@ +Source: ricochet-refresh +Section: net +Priority: optional +Maintainer: Marco Simonelli +Build-Depends: debhelper (>= 9), pkg-config, libevent-dev, libssl-dev, libprotobuf-dev, protobuf-compiler, qtbase5-dev, qtdeclarative5-dev, qttools5-dev-tools, tor, make +Standards-Version: 4.4.1 +Homepage: https://ricochetrefresh.net/ + +Package: ricochet-refresh +Architecture: any +Depends: tor, ${shlibs:Depends}, ${misc:Depends}, + qml-module-qtgraphicaleffects, + qml-module-qtquick-controls, + qml-module-qtquick-layouts, + qml-module-qtquick-dialogs +Description: Anonymous metadata-resistant instant messaging + Ricochet refresh is an open source project to allow private and anonymous + instant messaging. It is metadata-resistant, anonymous, decentralised and + easy to use. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..b51a5fa --- /dev/null +++ b/debian/copyright @@ -0,0 +1,2 @@ +Copyright (C) 2019-2020, Blueprint For Free Speech +Copyright (C) 2014-2016, John Brooks \ No newline at end of file diff --git a/debian/icons/1024x1024/ricochet-refresh.png b/debian/icons/1024x1024/ricochet-refresh.png new file mode 100644 index 0000000..4c98412 Binary files /dev/null and b/debian/icons/1024x1024/ricochet-refresh.png differ diff --git a/debian/icons/128x128/ricochet-refresh.png b/debian/icons/128x128/ricochet-refresh.png new file mode 100644 index 0000000..e0a0a31 Binary files /dev/null and b/debian/icons/128x128/ricochet-refresh.png differ diff --git a/debian/icons/16x16/ricochet-refresh.png b/debian/icons/16x16/ricochet-refresh.png new file mode 100644 index 0000000..f6b9ecf Binary files /dev/null and b/debian/icons/16x16/ricochet-refresh.png differ diff --git a/debian/icons/192x192/ricochet-refresh.png b/debian/icons/192x192/ricochet-refresh.png new file mode 100644 index 0000000..5790df2 Binary files /dev/null and b/debian/icons/192x192/ricochet-refresh.png differ diff --git a/debian/icons/24x24/ricochet-refresh.png b/debian/icons/24x24/ricochet-refresh.png new file mode 100644 index 0000000..dda63e8 Binary files /dev/null and b/debian/icons/24x24/ricochet-refresh.png differ diff --git a/debian/icons/256x256/ricochet-refresh.png b/debian/icons/256x256/ricochet-refresh.png new file mode 100644 index 0000000..18931de Binary files /dev/null and b/debian/icons/256x256/ricochet-refresh.png differ diff --git a/debian/icons/32x32/ricochet-refresh.png b/debian/icons/32x32/ricochet-refresh.png new file mode 100644 index 0000000..20feb00 Binary files /dev/null and b/debian/icons/32x32/ricochet-refresh.png differ diff --git a/debian/icons/48x48/ricochet-refresh.png b/debian/icons/48x48/ricochet-refresh.png new file mode 100644 index 0000000..7a8b435 Binary files /dev/null and b/debian/icons/48x48/ricochet-refresh.png differ diff --git a/debian/icons/512x512/ricochet-refresh.png b/debian/icons/512x512/ricochet-refresh.png new file mode 100644 index 0000000..54dfeeb Binary files /dev/null and b/debian/icons/512x512/ricochet-refresh.png differ diff --git a/debian/icons/64x64/ricochet-refresh.png b/debian/icons/64x64/ricochet-refresh.png new file mode 100644 index 0000000..04b7ad7 Binary files /dev/null and b/debian/icons/64x64/ricochet-refresh.png differ diff --git a/debian/icons/96x96/ricochet-refresh.png b/debian/icons/96x96/ricochet-refresh.png new file mode 100644 index 0000000..b9dda8d Binary files /dev/null and b/debian/icons/96x96/ricochet-refresh.png differ diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..6740424 --- /dev/null +++ b/debian/install @@ -0,0 +1,2 @@ +src/ricochet-refresh.desktop usr/share/applications +ricochet-refresh usr/bin \ No newline at end of file diff --git a/debian/manpages b/debian/manpages new file mode 100644 index 0000000..49f06bf --- /dev/null +++ b/debian/manpages @@ -0,0 +1 @@ +doc/manpage \ No newline at end of file diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..d440676 --- /dev/null +++ b/debian/rules @@ -0,0 +1,11 @@ +#!/usr/bin/make -f +export QT_SELECT=qt5 + +%: + dh $@ --buildsystem=qmake --parallel + +#override_dh_auto_configure: +# dh_auto_configure $(AC_OPTS) + +#override_dh_auto_install: +# dh_auto_install diff --git a/debian/shlibs.local b/debian/shlibs.local new file mode 100644 index 0000000..40d74e8 --- /dev/null +++ b/debian/shlibs.local @@ -0,0 +1 @@ +libprotobuf 17 diff --git a/doc/manpage b/doc/manpage new file mode 100644 index 0000000..b7090b1 --- /dev/null +++ b/doc/manpage @@ -0,0 +1,28 @@ +.\" Manpage for Ricochet Refresh +.\" Submit a PR on the github repository for typos/errors (https://github.com/blueprint-freespeech/ricochet-refresh.git) +.Dd $Mdocdate$ +.Dt ricochet-refresh 1 +.Os +.Sh NAME +.Nm ricochet-refresh +.Nd Anonymous metadata-resistant instant messaging +.Sh SYNOPSIS +.Nm ricochet-refresh +.Op options +.Sh DESCRIPTION +.Nm +is an open source project to allow private and anonymous +instant messaging. It is metadata-resistant, anonymous and decentralised. +.Sh OPTIONS +.Nm +takes up to 1 argument, the ricochet folder path (relative to the current +working directory). If this folder does not exist, ricochet will create the +folder and inside that folder will create files containing tor keys and +contacts. If no argument is given, ricochet will create a config folder at +QStandardPaths::AppDataLocation (see +https://doc.qt.io/qt-5/qstandardpaths.html#StandardLocation-enum). +.Sh AUTHOR +.Nm +has been written by John Brooks and is +currently maintained by Blueprint For Free Speech + \ No newline at end of file diff --git a/hardened.pri b/hardened.pri deleted file mode 100644 index 1bd3aaf..0000000 --- a/hardened.pri +++ /dev/null @@ -1,47 +0,0 @@ -load(configure) -# Define common variables; these are used by config tests _and_ the actual build - -# Supported in gcc 4.8+ -HARDENED_SANITIZE_FLAGS = -fsanitize=address -# Supported in gcc 4.9+ -HARDENED_SANITIZE_UBSAN_FLAGS = -fsanitize=undefined -fsanitize=integer-divide-by-zero -fsanitize=bounds -fsanitize=alignment -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize-recover -# Supported in gcc 5.0+ -HARDENED_SANITIZE_UBSAN_MORE_FLAGS = -fsanitize=vptr -fsanitize=object-size -# vtable-verify requires some OS support; see https://bugzilla.novell.com/show_bug.cgi?id=877239 -HARDENED_VTABLE_VERIFY_FLAGS = -fvtable-verify=std - -HARDENED_STACK_PROTECTOR_STRONG_FLAGS = -fstack-protector-strong -HARDENED_STACK_PROTECTOR_FLAGS = -fstack-protector --param=ssp-buffer-size=4 - -HARDENED_MINGW_64ASLR_FLAGS = -Wl,--dynamicbase -Wl,--high-entropy-va - - -# Run tests and apply options where possible -CONFIG(hardened) { - # mingw is always PIC, and complains about the flag - !mingw:HARDEN_FLAGS = -fPIC - - CONFIG(debug,debug|release): qtCompileTest(sanitize):HARDEN_FLAGS += $$HARDENED_SANITIZE_FLAGS - qtCompileTest(sanitize-ubsan):HARDEN_FLAGS += $$HARDENED_SANITIZE_UBSAN_FLAGS - qtCompileTest(sanitize-ubsan-more):HARDEN_FLAGS += $$HARDENED_SANITIZE_UBSAN_MORE_FLAGS - qtCompileTest(vtable-verify):HARDEN_FLAGS += $$HARDENED_VTABLE_VERIFY_FLAGS - - qtCompileTest(stack-protector-strong) { - HARDEN_FLAGS += $$HARDENED_STACK_PROTECTOR_STRONG_FLAGS - } else { - qtCompileTest(stack-protector):HARDEN_FLAGS += $$HARDENED_STACK_PROTECTOR_FLAGS - } - - mingw { - qtCompileTest(mingw-64aslr):QMAKE_LFLAGS *= $$HARDENED_MINGW_64ASLR_FLAGS - QMAKE_LFLAGS *= -Wl,--nxcompat -Wl,--dynamicbase - } - - QMAKE_CXXFLAGS *= $$HARDEN_FLAGS - QMAKE_LFLAGS *= $$HARDEN_FLAGS - - # _FORTIFY_SOURCE requires -O, so only use on release builds - CONFIG(release,debug|release):QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2 - # Linux specific - unix:!macx:QMAKE_LFLAGS *= -pie -Wl,-z,relro,-z,now -} diff --git a/protobuf.pri b/protobuf.pri deleted file mode 100644 index 116626a..0000000 --- a/protobuf.pri +++ /dev/null @@ -1,58 +0,0 @@ -# Qt qmake integration with Google Protocol Buffers compiler protoc -# -# To compile protocol buffers with qt qmake, specify PROTOS variable and -# include this file -# -# Based on: -# https://vilimpoc.org/blog/2013/06/09/using-google-protocol-buffers-with-qmake/ - -PROTOC = protoc - -unix { - PKG_CONFIG = $$pkgConfigExecutable() - - # All our dependency resolution depends on pkg-config. If it isn't - # available, the errors we will get subsequently are a lot more cryptic than - # this. - !system($$PKG_CONFIG --version 2>&1 > /dev/null) { - error("pkg-config executable is not available. please install it so I can find dependencies.") - } - - !contains(QT_CONFIG, no-pkg-config) { - CONFIG += link_pkgconfig - PKGCONFIG += protobuf - } else { - # Some SDK builds (e.g. OS X 5.4.1) are no-pkg-config, so try to hack the linker flags in. - QMAKE_LFLAGS += $$system($$PKG_CONFIG --libs protobuf) - } - - gcc|clang { - # Add -isystem for protobuf includes to suppress some loud compiler warnings in their headers - PROTOBUF_CFLAGS = $$system($$PKG_CONFIG --cflags protobuf) - PROTOBUF_CFLAGS ~= s/^(?!-I).*//g - PROTOBUF_CFLAGS ~= s/^-I(.*)/-isystem \\1/g - QMAKE_CXXFLAGS += $$PROTOBUF_CFLAGS - } -} - -win32 { - isEmpty(PROTOBUFDIR):error(You must pass PROTOBUFDIR=path/to/protobuf to qmake on this platform) - INCLUDEPATH += $${PROTOBUFDIR}/include - LIBS += -L$${PROTOBUFDIR}/lib -lprotobuf - contains(QMAKE_HOST.os,Windows):PROTOC = $${PROTOBUFDIR}/bin/protoc.exe -} - -protobuf_decl.name = protobuf headers -protobuf_decl.input = PROTOS -protobuf_decl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h -protobuf_decl.commands = $$PROTOC --cpp_out=${QMAKE_FILE_IN_PATH} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME} -protobuf_decl.variable_out = HEADERS -QMAKE_EXTRA_COMPILERS += protobuf_decl - -protobuf_impl.name = protobuf sources -protobuf_impl.input = PROTOS -protobuf_impl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.cc -protobuf_impl.depends = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h -protobuf_impl.commands = $$escape_expand(\n) -protobuf_impl.variable_out = SOURCES -QMAKE_EXTRA_COMPILERS += protobuf_impl diff --git a/LICENSE b/src/LICENSE similarity index 100% rename from LICENSE rename to src/LICENSE diff --git a/src/extern/fmt b/src/extern/fmt new file mode 160000 index 0000000..0b6e7cc --- /dev/null +++ b/src/extern/fmt @@ -0,0 +1 @@ +Subproject commit 0b6e7cc60abd939685ebe339de1e19f008a9211f diff --git a/src/extern/tor b/src/extern/tor new file mode 160000 index 0000000..18d2c7c --- /dev/null +++ b/src/extern/tor @@ -0,0 +1 @@ +Subproject commit 18d2c7c5d7eb0441d891fb7642fbbabde6c53cf2 diff --git a/src/libtego/include/tego/logger.hpp b/src/libtego/include/tego/logger.hpp new file mode 100644 index 0000000..a72c048 --- /dev/null +++ b/src/libtego/include/tego/logger.hpp @@ -0,0 +1,72 @@ +#pragma once + +#ifdef ENABLE_TEGO_LOGGER + +// std +#include +#include +#include +#include +#include +#include +#include +using std::experimental::source_location; +#include + +// fmt +#include +#include + +// wrapper around fmt::print that writes to singleton log file libtego.log +class logger +{ +public: + template + static void println(const char (&format)[N], ARGS&&... args) + { + std::lock_guard guard(get_mutex()); + + auto& fs = get_stream(); + + fmt::print(fs, "[{:f}][{}] ", get_timestamp(), std::this_thread::get_id()); + fmt::print(fs, format, std::forward(args)...); + fs << std::endl; + } + + template + static void println(const char (&msg)[N]) + { + std::lock_guard guard(get_mutex()); + + auto& fs = get_stream(); + + fmt::print(fs, "[{:f}][{}] ", get_timestamp(), std::this_thread::get_id()); + fs << msg << std::endl; + } + + static void trace(const source_location& loc = source_location::current()); +private: + static std::ofstream& get_stream(); + static std::mutex& get_mutex(); + static double get_timestamp(); +}; + +std::ostream& operator<<(std::ostream& out, const class QString& str); +std::ostream& operator<<(std::ostream& out, const class QByteArray& blob); +std::ostream& operator<<(std::ostream& out, const std::type_info& ti); +#else // ENABLE_TEGO_LOGGER + +// mock no-op logger +class logger +{ +public: + template + static void println(const char (&)[N], ARGS&&...) {} + template + static void println(const char (&)[N]) {} + static void trace() {} +}; + + + +#endif // ENABLE_TEGO_LOGGER \ No newline at end of file diff --git a/src/libtego/include/tego/tego.h b/src/libtego/include/tego/tego.h new file mode 100644 index 0000000..15cbd5a --- /dev/null +++ b/src/libtego/include/tego/tego.h @@ -0,0 +1,236 @@ +#ifndef TEGO_H +#define TEGO_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define TEGO_TRUE 1 +#define TEGO_FALSE 0 + +// number of bytes in an ed25519 signature +#define TEGO_ED25519_SIGNATURE_SIZE 64 +// length of a valid v3 service id string not including null terminator +#define TEGO_V3_ONION_SERVICE_ID_LENGTH 56 +// length of a v3 service id string including null terminator +#define TEGO_V3_ONION_SERVICE_ID_SIZE (TEGO_V3_ONION_SERVICE_ID_LENGTH + 1) +// length of the ed25519 KeyBlob string not including null terminator +#define TEGO_ED25519_KEYBLOB_LENGTH 99 +// length of an ed25519 keyblob string including null terminator +#define TEGO_ED25519_KEYBLOB_SIZE (TEGO_ED25519_KEYBLOB_LENGTH + 1) + +typedef struct tego_error tego_error_t; + +/* + * Get error message form tego_error + * + * @param error : the error object to get the message from + * @return : null terminated string with error message whose + * lifetime is tied to the source tego_error_t + */ +const char* tego_error_get_message(const tego_error_t* error); + +// library init/uninit +void tego_initialize(tego_error_t** error); +void tego_uninitialize(tego_error_t** error); + +/* + * v3 onion/ed25519 functionality + */ + +typedef struct tego_ed25519_private_key tego_ed25519_private_key_t; +typedef struct tego_ed25519_public_key tego_ed25519_public_key_t; +typedef struct tego_ed25519_signature tego_ed25519_signature_t; +typedef struct tego_v3_onion_service_id tego_v3_onion_service_id_t; + +/* + * Conversion method for converting the KeyBlob string returned by + * ADD_ONION command into an ed25519_private_key_t + * + * @param out_privateKey : returned ed25519 private key + * @param keyBlob : an ED25519 KeyBlob string in the form + * "ED25519-V3:abcd1234..." + * @param keyBlobLength : number of characters in keyBlob not + * counting the null terminator + * @param error : filled with a tego_error_t on error + */ +void tego_ed25519_private_key_from_ed25519_keyblob( + tego_ed25519_private_key_t** out_privateKey, + const char* keyBlob, + size_t keyBlobLength, + tego_error_t** error); + +/* + * Conversion method for converting an ed25519 private key + * to a null-terminated KeyBlob string for use with ADD_ONION + * command + * + * @param out_keyBlob : buffer to be filled with ed25519 KeyBlob in + * the form "ED25519-V3:abcd1234...\0" + * @param keyBlobSize : size of out_keyBlob buffer in bytes, must be at + * least 100 characters (99 for string + 1 for null terminator) + * @param privateKey : the private key to encode + * @param error : filled with a tego_error_t on error + * @return : the number of characters written (including null terminator) + * to out_keyBlob + */ +size_t tego_ed25519_keyblob_from_ed25519_private_key( + char *out_keyBlob, + size_t keyBlobSize, + const tego_ed25519_private_key_t* privateKey, + tego_error_t** error); + +/* + * Calculate ed25519 public key from ed25519 private key + * + * @param out_publicKey : returned ed25519 public key + * @param privateKey : input ed25519 private key + * @param error : filled with a tego_error_t on error + */ +void tego_ed25519_public_key_from_ed25519_private_key( + tego_ed25519_public_key_t** out_publicKey, + const tego_ed25519_private_key_t* privateKey, + tego_error_t** error); + +/* + * Construct a service id object from string. Validates + * the checksum and version byte per spec: + * https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt + * + * @param out_serviceId : returned v3 onion service id + * @param serviceIdString : a string beginning with a v3 service id + * @param serviceIdStringLength : length of the service id string not + * counting the null terminator + * @param error : filled with a tego_error_t on error + */ +void tego_v3_onion_service_id_from_string( + tego_v3_onion_service_id_t** out_serviceId, + const char* serviceIdString, + size_t serviceIdStringLength, + tego_error_t** error); + +/* + * Serializes out a service id object as a null terminated string + * string to provided character buffer. + * + * @param serviceId : v3 onion service id object to serialize + * @param out_serviceIdString : destination buffer for string + * @param serviceIdStringSize : size of out_serviceIdString buffer in + * bytes, must be at least 57 bytes (56 bytes for string + null + * terminator) + * @param error : filled with a tego_error_t on error + */ +size_t tego_v3_onion_service_id_to_string( + const tego_v3_onion_service_id_t* serviceId, + char* out_serviceIdString, + size_t serviceIdStringSize, + tego_error_t** error); + +/* + * Extract public key from v3 service id per + * https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt + * + * @param out_publicKey : returned ed25519 public key + * @param serviceId : input service id + * @param error : filled with a tego_error_t on error + */ +void tego_ed25519_public_key_from_v3_onion_service_id( + tego_ed25519_public_key_t** out_publicKey, + const tego_v3_onion_service_id_t* serviceId, + tego_error_t** error); + +/* + * Derive an onion's service id from its ed25519 public key per + * https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt + * + * @param out_serviceId : returned service id + * @param publicKey : the public key input + * @param error : filled with a tego_error_t on error + */ +void tego_v3_onion_service_id_from_ed25519_public_key( + tego_v3_onion_service_id_t** out_serviceId, + const tego_ed25519_public_key_t* publicKey, + tego_error_t** error); + +/* + * Read in signature from length 64 byte buffer + * + * @param out_signature : returned ed25519 signature + * @param buffer : source memory buffer holding signature + * @param bufferSize : size of data in bytes, must be at least 64 bytes + * @param error : filled with a tego_error_t on error + */ +void tego_ed25519_signature_from_bytes( + tego_ed25519_signature_t** out_signature, + const uint8_t* buffer, + size_t bufferSize, + tego_error_t** error); + +/* + * Get the signature and place it in length 64 byte buffer + * + * @param signature : a calculated message signature + * @param out_buffer : output buffer to write signature to + * @param bufferSize : size of buffer in bytes, must be at least 64 bytes + * @param error : filled with a tego_error_t on error + * @return : number of bytes written to out_buffer + */ +size_t tego_ed25519_signature_to_bytes( + const tego_ed25519_signature_t* signature, + uint8_t* out_buffer, + size_t bufferSize, + tego_error_t** error); + +/* + * Sign a message with an ed25519 key-pair + * + * @param message : message binary to sign + * @param messageSize : size of message in bytes + * @param privateKey : the ed25519 private key + * @param publicKey : the ed25519 public key + * @param out_signature : the output signature + * @param error : filled with a tego_error_t on error + */ +void tego_message_ed25519_sign( + const uint8_t* message, + size_t messageSize, + const tego_ed25519_private_key_t* privateKey, + const tego_ed25519_public_key_t* publicKey, + tego_ed25519_signature_t** out_signature, + tego_error_t** error); + +/* + * Verify a message's signature given a public key + * + * @param signature : the signature to verify + * @param message : the message that was signed + * @param messageSize : size of the message in bytes + * @param publicKey : the public key to very the the signature against + * @param error : filled with a tego_error_t on error + * @return : TEGO_TRUE if signature is verified, TEGO_FALSE if it is not + * verified or if an error occurs + */ +int tego_ed25519_signature_verify( + const tego_ed25519_signature_t* signature, + const uint8_t* message, + size_t messageLength, + const tego_ed25519_public_key_t* publicKey, + tego_error_t** error); + +/* + Destructors for various tego types + */ + +void tego_ed25519_private_key_delete(tego_ed25519_private_key_t*); +void tego_ed25519_public_key_delete(tego_ed25519_public_key_t*); +void tego_ed25519_signature_delete(tego_ed25519_signature_t*); +void tego_v3_onion_service_id_delete(tego_v3_onion_service_id_t*); +void tego_error_delete(tego_error_t*); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // TEGO_H \ No newline at end of file diff --git a/src/libtego/include/tego/tego.hpp b/src/libtego/include/tego/tego.hpp new file mode 100644 index 0000000..cb5ec16 --- /dev/null +++ b/src/libtego/include/tego/tego.hpp @@ -0,0 +1,63 @@ +#pragma once +// C + +// libtego +#include + +// C++ + +// standard library +#include +#include +#include +#include +#include + +// libtego +#include +#include + +namespace tego +{ + // + // converts tego_error_t** C style error handling to exceptions + // + class throw_on_error + { + public: + ~throw_on_error() noexcept(false) + { + if (error_ != nullptr) + { + std::runtime_error ex(tego_error_get_message(error_)); + tego_error_delete(error_); + error_ = nullptr; + throw ex; + } + } + + operator tego_error_t**() + { + return &error_; + } + private: + tego_error_t* error_ = nullptr; + }; +} + + +// define deleters for using unique_ptr and shared_ptr with tego types + +#define TEGO_DEFAULT_DELETE_IMPL(TYPE)\ +namespace std {\ + template<> class default_delete {\ + public:\ + void operator()(TYPE##_t* val) { TYPE##_delete(val); }\ + };\ +} + +TEGO_DEFAULT_DELETE_IMPL(tego_ed25519_private_key) +TEGO_DEFAULT_DELETE_IMPL(tego_ed25519_public_key) +TEGO_DEFAULT_DELETE_IMPL(tego_ed25519_signature) +TEGO_DEFAULT_DELETE_IMPL(tego_v3_onion_service_id) + diff --git a/src/libtego/include/tego/utilities.hpp b/src/libtego/include/tego/utilities.hpp new file mode 100644 index 0000000..73906f8 --- /dev/null +++ b/src/libtego/include/tego/utilities.hpp @@ -0,0 +1,101 @@ +#pragma once + +namespace tego +{ + // + // call functor at end of scope + // + template + class scope_exit + { + public: + scope_exit() = delete; + scope_exit(const scope_exit&) = delete; + scope_exit& operator=(const scope_exit&) = delete; + scope_exit& operator=(scope_exit&&) = delete; + + scope_exit(scope_exit&&) = default; + scope_exit(T&& functor) + : functor_(new T(std::move(functor))) + { + static_assert(std::is_same::value); + } + + ~scope_exit() + { + if (functor_.get()) + { + functor_->operator()(); + } + } + + private: + std::unique_ptr functor_; + }; + + + template + auto make_scope_exit(FUNC&& func) -> + scope_exit::type> + { + return {std::move(func)}; + } + + // + // constexpr strlen for compile-time null terminated C String constants + // + template + constexpr size_t static_strlen(const char (&str)[N]) + { + if (str[N-1] != 0) throw "C String missing null terminator"; + for(size_t i = 0; i < (N - 1); i++) + { + if (str[i] == 0) throw "C String has early null terminator"; + } + return N-1; + } + + // + // helper class for populating out T** params into unique_ptr objects + // + template + class out_unique_ptr + { + public: + out_unique_ptr() = delete; + out_unique_ptr(const out_unique_ptr&) = delete; + out_unique_ptr(out_unique_ptr&&) = delete; + out_unique_ptr& operator=(const out_unique_ptr&) = delete; + out_unique_ptr& operator=(out_unique_ptr&&) = delete; + + out_unique_ptr(std::unique_ptr& u) : u_(u) {} + ~out_unique_ptr() + { + u_.reset(t_); + } + + operator T**() + { + return &t_; + } + + private: + T* t_ = nullptr; + std::unique_ptr& u_; + }; + + // + // helper function for populating out T** params + // example: + // + // void give_int(int** outInt); + // std::unique_ptr pint; + // give_int(tego::out(pint)); + // int val = *pint; + // + template + out_unique_ptr out(std::unique_ptr& ptr) + { + return {ptr}; + } +} diff --git a/src/libtego/libtego.pri b/src/libtego/libtego.pri new file mode 100644 index 0000000..cbbb8bc --- /dev/null +++ b/src/libtego/libtego.pri @@ -0,0 +1,8 @@ +INCLUDEPATH +=\ + $${PWD}/include\ + $${PWD}/../extern/fmt/include + +LIBS += -L$${DESTDIR}/../libtego -ltego + +QMAKE_INCLUDES = $${PWD}/../qmake_includes +include($${QMAKE_INCLUDES}/openssl.pri) \ No newline at end of file diff --git a/src/libtego/libtego.pro b/src/libtego/libtego.pro new file mode 100644 index 0000000..2b4bf35 --- /dev/null +++ b/src/libtego/libtego.pro @@ -0,0 +1,63 @@ +QMAKE_INCLUDES = $${PWD}/../qmake_includes + +include($${QMAKE_INCLUDES}/artifacts.pri) +include($${QMAKE_INCLUDES}/compiler_flags.pri) + +TEMPLATE = lib +TARGET = tego + +CONFIG += staticlib + +# setup precompiled headers +CONFIG += precompile_header +PRECOMPILED_HEADER = source/precomp.h + +# fmt sources +FMT_SOURCE_DIR = $${PWD}/../extern/fmt/src +FMT_INCLUDE_DIR = $${PWD}/../extern/fmt/include +SOURCES +=\ + $${FMT_SOURCE_DIR}/format.cc\ + $${FMT_SOURCE_DIR}/os.cc + +INCLUDEPATH +=\ + $${FMT_INCLUDE_DIR} + +# tor sources +TOR_ROOT_DIR = $${PWD}/../extern/tor +TOR_SOURCE_DIR = $${TOR_ROOT_DIR}/src + +SOURCES +=\ + $${TOR_SOURCE_DIR}/ext/ed25519/donna/ed25519_tor.c\ + $${TOR_SOURCE_DIR}/lib/encoding/binascii.c\ + $${TOR_SOURCE_DIR}/lib/crypt_ops/crypto_digest_openssl.c + +INCLUDEPATH +=\ + $${TOR_ROOT_DIR}\ + $${TOR_ROOT_DIR}/src\ + $${TOR_ROOT_DIR}/src/ext + +# libtego +HEADERS +=\ + include/tego/tego.h\ + include/tego/logger.hpp\ + include/tego/utilities.hpp\ + source/orconfig.h\ + source/error.hpp\ + source/ed25519.hpp + +SOURCES +=\ + source/libtego.cpp\ + source/delete.cpp\ + source/error.cpp\ + source/tor_stubs.cpp\ + source/ed25519.cpp\ + source/logger.cpp\ + + +# external +INCLUDEPATH +=\ + include\ + source\ + $${TOR_INCLUDE_DIR} + +include($${QMAKE_INCLUDES}/openssl.pri) \ No newline at end of file diff --git a/src/libtego/source/delete.cpp b/src/libtego/source/delete.cpp new file mode 100644 index 0000000..d6a6f47 --- /dev/null +++ b/src/libtego/source/delete.cpp @@ -0,0 +1,30 @@ +#include "ed25519.hpp" +#include "error.hpp" + +extern "C" +{ + void tego_ed25519_private_key_delete(tego_ed25519_private_key_t* privateKey) + { + delete privateKey; + } + + void tego_ed25519_public_key_delete(tego_ed25519_public_key_t* publicKey) + { + delete publicKey; + } + + void tego_ed25519_signature_delete(tego_ed25519_signature_t* signature) + { + delete signature; + } + + void tego_v3_onion_service_id_delete(tego_v3_onion_service_id_t* serviceId) + { + delete serviceId; + } + + void tego_error_delete(tego_error_t* error) + { + delete error; + } +} \ No newline at end of file diff --git a/src/libtego/source/ed25519.cpp b/src/libtego/source/ed25519.cpp new file mode 100644 index 0000000..117f391 --- /dev/null +++ b/src/libtego/source/ed25519.cpp @@ -0,0 +1,421 @@ +#include "error.hpp" +#include "ed25519.hpp" + +// header of ed25519 KeyBlob returned by ADD_ONION comand +#define TEGO_ED25519_KEYBLOB_HEADER "ED25519-V3:" +// length of ed25519 KeyBlob header string not including null terminator +constexpr size_t TEGO_ED25519_KEYBLOB_HEADER_LENGTH = tego::static_strlen(TEGO_ED25519_KEYBLOB_HEADER); +// length of ed25519 KeyBlob string not including null terminator +constexpr size_t TEGO_ED25519_KEYBLOB_BASE64_LENGTH = 88; +// number of bytes needed to encode KeyBlob including the null terminator +constexpr size_t TEGO_ED25519_KEYBLOB_BASE64_SIZE = TEGO_ED25519_KEYBLOB_BASE64_LENGTH + 1; +// number of bytes the base32 encoded service id string decodes to +constexpr size_t TEGO_V3_ONION_SERVICE_ID_RAW_SIZE = 35; +// offset to public key in raw service id +constexpr size_t TEGO_V3_ONION_SERVICE_ID_PUBLIC_KEY_OFFSET = 0; +// length of public key in raw service id +constexpr size_t TEGO_V3_ONION_SERVICE_ID_PUBLIC_KEY_SIZE = 32; +// offset to checksum in raw service id +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_OFFSET = 32; +// length of checksum in raw service id +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SIZE = 2; +// offset to version (which should be 0x03) in raw service id +constexpr size_t TEGO_V3_ONION_SERVICE_ID_VERSION_OFFSET = 34; +// prefix used when calculating service id checksum +#define TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX ".onion checksum" +// length of service id prefix not including null terminator +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX_LEGNTH = tego::static_strlen(TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX); +// offset to the public key in the service id checksum source +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PUBLIC_KEY_OFFSET = TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX_LEGNTH; +// size of source data used to calculate the serice id checksum +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_SIZE = TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX_LEGNTH + ED25519_PUBKEY_LEN + 1; +// offset for the version byte in the service id checksum source +constexpr size_t TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_VERSION_OFFSET = TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_SIZE - 1; + +namespace tego +{ + void truncated_checksum_from_ed25519_public_key( + uint8_t out_truncatedChecksum[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SIZE], + const uint8_t (&publicKey)[ED25519_PUBKEY_LEN]) + { + // build message for checksum + // prefix + uint8_t checksumSrc[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_SIZE] = TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PREFIX; + // public key + std::copy( + std::begin(publicKey), + std::begin(publicKey) + sizeof(publicKey), + checksumSrc + TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_PUBLIC_KEY_OFFSET); + // version byte 0x03 + checksumSrc[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SRC_VERSION_OFFSET] = 0x03; + + // verify checksum + uint8_t checksum[BASE32_DIGEST_LEN] = {0}; + + // calculate sha256 + // TODO: probably just call openssl APIs directly here rather than use tor's + // encapsulation to simplify build and include weirdness in precomp.h + TEGO_THROW_IF_FALSE(crypto_digest256( + reinterpret_cast(checksum), + reinterpret_cast(checksumSrc), + sizeof(checksumSrc), + DIGEST_SHA3_256) == 0); + + out_truncatedChecksum[0] = checksum[0]; + out_truncatedChecksum[1] = checksum[1]; + } +} + +extern "C" +{ + void tego_ed25519_private_key_from_ed25519_keyblob( + tego_ed25519_private_key_t** out_privateKey, + const char* keyBlob, + size_t keyBlobLength, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(out_privateKey != nullptr); + TEGO_THROW_IF_FALSE(*out_privateKey == nullptr); + TEGO_THROW_IF_FALSE(keyBlob != nullptr); + TEGO_THROW_IF_FALSE(keyBlobLength == TEGO_ED25519_KEYBLOB_LENGTH); + + // ensure KeyBlob starts with correct string constant + TEGO_THROW_IF_FALSE(std::string_view(keyBlob).starts_with(TEGO_ED25519_KEYBLOB_HEADER)); + + // get a string_view of the base64 blob + std::string_view base64(keyBlob + TEGO_ED25519_KEYBLOB_HEADER_LENGTH); + + // make sure the blob has enough characters to encode our privat ekey + const auto maxByteCount = ::base64_decode_maxsize(base64.size()); + TEGO_THROW_IF_FALSE(maxByteCount >= ED25519_SECKEY_LEN); + + // local buffer for private key + uint8_t privateKeyData[ED25519_SECKEY_LEN] = {0}; + const auto bytesWritten = ::base64_decode(reinterpret_cast(privateKeyData), sizeof(privateKeyData), base64.data(), base64.size()); + TEGO_THROW_IF_FALSE(bytesWritten == ED25519_SECKEY_LEN); + + // copy into returned tego_ed25519_private_key struct + auto privateKey = std::make_unique(); + std::copy(std::begin(privateKeyData), std::end(privateKeyData), privateKey->data); + + *out_privateKey = privateKey.release(); + }, error); + } + + size_t tego_ed25519_keyblob_from_ed25519_private_key( + char* out_keyBlob, + size_t keyBlobSize, + const tego_ed25519_private_key_t* privateKey, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> size_t + { + // verify arguments + TEGO_THROW_IF_FALSE(out_keyBlob != nullptr); + TEGO_THROW_IF_FALSE(keyBlobSize >= TEGO_ED25519_KEYBLOB_SIZE); + TEGO_THROW_IF_FALSE(privateKey != nullptr); + + // zero out output buffer first + std::fill(out_keyBlob, out_keyBlob + keyBlobSize, 0x00); + + // init KeyBlob buffer with the header + char keyBlob[TEGO_ED25519_KEYBLOB_SIZE] = TEGO_ED25519_KEYBLOB_HEADER; + + // encode privatekey as base64 (adds null terminator) + auto base64BytesWritten = base64_encode( + keyBlob + TEGO_ED25519_KEYBLOB_HEADER_LENGTH, + TEGO_ED25519_KEYBLOB_BASE64_SIZE, + reinterpret_cast(privateKey->data), + sizeof(privateKey->data), + 0); + + TEGO_THROW_IF_FALSE(keyBlob[TEGO_ED25519_KEYBLOB_LENGTH] == 0); + TEGO_THROW_IF_FALSE(base64BytesWritten == TEGO_ED25519_KEYBLOB_BASE64_LENGTH); + + // copy entire KeyBlob to output buffer + std::copy(std::begin(keyBlob), std::end(keyBlob), out_keyBlob); + return sizeof(keyBlob); + }, error, 0); + } + + void tego_ed25519_public_key_from_ed25519_private_key( + tego_ed25519_public_key_t** out_publicKey, + const tego_ed25519_private_key_t* privateKey, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(out_publicKey != nullptr); + TEGO_THROW_IF_FALSE(*out_publicKey == nullptr); + TEGO_THROW_IF_FALSE(privateKey != nullptr); + + // local buffer for public key + uint8_t publicKeyData[ED25519_PUBKEY_LEN] = {0}; + TEGO_THROW_IF_FALSE(ed25519_donna_pubkey(publicKeyData, privateKey->data) == 0); + + // copy into returned tego_ed25519_public_key struct + auto publicKey = std::make_unique(); + std::copy(std::begin(publicKeyData), std::end(publicKeyData), publicKey->data); + + *out_publicKey = publicKey.release(); + }, error); + } + + void tego_v3_onion_service_id_from_string( + tego_v3_onion_service_id_t** out_serviceId, + const char* serviceIdString, + size_t serviceIdStringLength, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + TEGO_THROW_IF_FALSE(out_serviceId != nullptr); + TEGO_THROW_IF_FALSE(*out_serviceId == nullptr); + TEGO_THROW_IF_FALSE(serviceIdString != nullptr); + TEGO_THROW_IF_FALSE(serviceIdStringLength >= TEGO_V3_ONION_SERVICE_ID_LENGTH); + + std::string_view serviceIdView(serviceIdString, TEGO_V3_ONION_SERVICE_ID_LENGTH); + uint8_t rawServiceId[TEGO_V3_ONION_SERVICE_ID_RAW_SIZE] = {0}; + + // base32 decode service id + const auto bytesDecoded = ::base32_decode( + reinterpret_cast(rawServiceId), + sizeof(rawServiceId), + serviceIdView.data(), + serviceIdView.size()); + TEGO_THROW_IF_FALSE(bytesDecoded == sizeof(rawServiceId)); + + // verify correct version byte + TEGO_THROW_IF_FALSE(rawServiceId[TEGO_V3_ONION_SERVICE_ID_VERSION_OFFSET] == 0x03); + + // first part of the rawServiceId is the publicKey + auto& rawPublicKey = reinterpret_cast(rawServiceId); + + // calculate the truncated checksum for the public key + uint8_t truncatedChecksum[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SIZE] = {0}; + tego::truncated_checksum_from_ed25519_public_key(truncatedChecksum, rawPublicKey); + + // verify the first two bytes of checksum in service id match our calculated checksum + TEGO_THROW_IF_FALSE( + rawServiceId[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_OFFSET ] == truncatedChecksum[0] && + rawServiceId[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_OFFSET + 1] == truncatedChecksum[1]); + + // verified checksum, copy service id string to new service id object + auto serviceId = std::make_unique(); + std::copy(std::begin(serviceIdView), std::end(serviceIdView), serviceId->data); + // write null terminator + serviceId->data[TEGO_V3_ONION_SERVICE_ID_LENGTH] = 0; + + *out_serviceId = serviceId.release(); + }, error); + } + + size_t tego_v3_onion_service_id_to_string( + const tego_v3_onion_service_id_t* serviceId, + char* out_serviceIdString, + size_t serviceIdStringSize, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> size_t + { + // verify arguments + TEGO_THROW_IF_FALSE(serviceId != nullptr); + TEGO_THROW_IF_FALSE(out_serviceIdString != nullptr); + TEGO_THROW_IF_FALSE(serviceIdStringSize >= TEGO_V3_ONION_SERVICE_ID_SIZE); + + std::copy( + std::begin(serviceId->data), + std::end(serviceId->data), + out_serviceIdString); + + return TEGO_V3_ONION_SERVICE_ID_SIZE; + }, error, 0); + } + + void tego_ed25519_public_key_from_v3_onion_service_id( + tego_ed25519_public_key_t** out_publicKey, + const tego_v3_onion_service_id_t* serviceId, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(out_publicKey != nullptr); + TEGO_THROW_IF_FALSE(*out_publicKey == nullptr); + TEGO_THROW_IF_FALSE(serviceId != nullptr); + + // https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n2135 + std::string_view serviceIdView(serviceId->data, TEGO_V3_ONION_SERVICE_ID_LENGTH); + uint8_t rawServiceId[TEGO_V3_ONION_SERVICE_ID_RAW_SIZE] = {0}; + + // base32 decode service id + const auto bytesDecoded = ::base32_decode( + reinterpret_cast(rawServiceId), + sizeof(rawServiceId), + serviceIdView.data(), + serviceIdView.size()); + TEGO_THROW_IF_FALSE(bytesDecoded == sizeof(rawServiceId)); + + // first part of the service id is the public key + + // copy over public key + auto publicKey = std::make_unique(); + std::copy(std::begin(rawServiceId), + std::begin(rawServiceId) + ED25519_PUBKEY_LEN, + publicKey->data); + + *out_publicKey = publicKey.release(); + }, error); + } + + void tego_v3_onion_service_id_from_ed25519_public_key( + tego_v3_onion_service_id_t** out_serviceId, + const tego_ed25519_public_key_t* publicKey, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(out_serviceId != nullptr); + TEGO_THROW_IF_FALSE(*out_serviceId == nullptr); + TEGO_THROW_IF_FALSE(publicKey != nullptr); + + // build the raw service id + uint8_t rawServiceId[TEGO_V3_ONION_SERVICE_ID_RAW_SIZE] = {0}; + + // copy over public key + std::copy(std::begin(publicKey->data), + std::end(publicKey->data), + rawServiceId); + + // calculate turncated checksum and copy it into raw service id + uint8_t truncatedChecksum[TEGO_V3_ONION_SERVICE_ID_CHECKSUM_SIZE] = {0}; + tego::truncated_checksum_from_ed25519_public_key(truncatedChecksum, publicKey->data); + std::copy(std::begin(truncatedChecksum), + std::end(truncatedChecksum), + rawServiceId + TEGO_V3_ONION_SERVICE_ID_CHECKSUM_OFFSET); + + // version 3 + rawServiceId[TEGO_V3_ONION_SERVICE_ID_VERSION_OFFSET] = 0x03; + + // encode to base32 + char serviceIdString[TEGO_V3_ONION_SERVICE_ID_SIZE] = {0}; + ::base32_encode(serviceIdString, sizeof(serviceIdString), reinterpret_cast(rawServiceId), sizeof(rawServiceId)); + + auto serviceId = std::make_unique(); + std::copy(std::begin(serviceIdString), std::end(serviceIdString), serviceId->data); + + *out_serviceId = serviceId.release(); + }, error); + } + + void tego_ed25519_signature_from_bytes( + tego_ed25519_signature_t** out_signature, + const uint8_t* buffer, + size_t bufferSize, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(out_signature != nullptr); + TEGO_THROW_IF_FALSE(*out_signature == nullptr); + TEGO_THROW_IF_FALSE(buffer != nullptr); + TEGO_THROW_IF_FALSE(bufferSize >= TEGO_ED25519_SIGNATURE_SIZE); + + // copy raw signature into signature struct + auto signature = std::make_unique(); + std::copy(buffer, buffer + TEGO_ED25519_SIGNATURE_SIZE, signature->data); + + *out_signature = signature.release(); + + }, error); + } + + size_t tego_ed25519_signature_to_bytes( + const tego_ed25519_signature_t* signature, + uint8_t* out_buffer, + size_t bufferSize, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> size_t + { + TEGO_THROW_IF_FALSE(signature != nullptr); + TEGO_THROW_IF_FALSE(out_buffer != nullptr); + TEGO_THROW_IF_FALSE(bufferSize >= TEGO_ED25519_SIGNATURE_SIZE) + + // get the data out of our signature type + std::copy(std::begin(signature->data), std::end(signature->data), out_buffer); + return sizeof(signature->data); + }, error, 0); + } + + void tego_message_ed25519_sign( + const uint8_t* message, + size_t messageSize, + const tego_ed25519_private_key_t* privateKey, + const tego_ed25519_public_key_t* publicKey, + tego_ed25519_signature_t** out_signature, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> void + { + // verify arguments + TEGO_THROW_IF_FALSE(message != nullptr); + TEGO_THROW_IF_FALSE(messageSize > 0); + TEGO_THROW_IF_FALSE(privateKey != nullptr); + TEGO_THROW_IF_FALSE(publicKey != nullptr); + TEGO_THROW_IF_FALSE(out_signature != nullptr); + TEGO_THROW_IF_FALSE(*out_signature == nullptr); + + // calculate message signature + uint8_t signatureBuffer[TEGO_ED25519_SIGNATURE_SIZE] = {0}; + TEGO_THROW_IF_FALSE( + ::ed25519_donna_sign( + signatureBuffer, + message, + messageSize, + privateKey->data, + publicKey->data) == 0); + + auto signature = std::make_unique(); + std::copy(std::begin(signatureBuffer), std::end(signatureBuffer), signature->data); + + *out_signature = signature.release(); + }, error); + } + + int tego_ed25519_signature_verify( + const tego_ed25519_signature_t* signature, + const uint8_t* message, + size_t messageSize, + const tego_ed25519_public_key_t* publicKey, + tego_error_t** error) + { + return tego::translateExceptions([&]() -> int + { + // verify arguments + TEGO_THROW_IF_FALSE(signature != nullptr); + TEGO_THROW_IF_FALSE(message != nullptr); + TEGO_THROW_IF_FALSE(messageSize > 0); + TEGO_THROW_IF_FALSE(publicKey != nullptr); + + // attempt to verify + auto result = ::ed25519_donna_open( + signature->data, + message, + messageSize, + publicKey->data); + + // result will be 0 if valid, -1 if not + TEGO_THROW_IF_FALSE(result == 0 || result == -1); + + if (result == 0) return TEGO_TRUE; + return TEGO_FALSE; + }, error, TEGO_FALSE); + } +} \ No newline at end of file diff --git a/src/libtego/source/ed25519.hpp b/src/libtego/source/ed25519.hpp new file mode 100644 index 0000000..a8ad3f4 --- /dev/null +++ b/src/libtego/source/ed25519.hpp @@ -0,0 +1,23 @@ +#pragma once + +static_assert(ED25519_SIG_LEN == TEGO_ED25519_SIGNATURE_SIZE); + +struct tego_ed25519_private_key +{ + uint8_t data[ED25519_SECKEY_LEN] = {0}; +}; + +struct tego_ed25519_public_key +{ + uint8_t data[ED25519_PUBKEY_LEN] = {0}; +}; + +struct tego_ed25519_signature +{ + uint8_t data[ED25519_SIG_LEN] = {0}; +}; + +struct tego_v3_onion_service_id +{ + char data[TEGO_V3_ONION_SERVICE_ID_SIZE] = {0}; +}; diff --git a/src/libtego/source/error.cpp b/src/libtego/source/error.cpp new file mode 100644 index 0000000..26c9135 --- /dev/null +++ b/src/libtego/source/error.cpp @@ -0,0 +1,9 @@ +#include "error.hpp" + +extern "C" +{ + const char* tego_error_get_message(const tego_error_t* error) + { + return error->message.c_str(); + } +} \ No newline at end of file diff --git a/src/libtego/source/error.hpp b/src/libtego/source/error.hpp new file mode 100644 index 0000000..892be63 --- /dev/null +++ b/src/libtego/source/error.hpp @@ -0,0 +1,49 @@ +#pragma once + +#define TEGO_THROW_IF_FALSE_MSG(B, MSG) if (!(B)) { throw std::runtime_error(fmt::format("assertion failed {}:{} : {}", __FILE__, __LINE__, MSG)); } +#define TEGO_THROW_IF_FALSE(B) TEGO_THROW_IF_FALSE_MSG(B, #B) + +struct tego_error +{ + std::string message; +}; + +namespace tego +{ + template + auto translateExceptions(FUNC&& fn, tego_error_t** out_error) noexcept(true) -> void + { + static_assert(std::is_same::value); + + try + { + fn(); + } + catch(const std::exception& ex) + { + if (out_error) + { + logger::println("Exception: {}", ex.what()); + *out_error = new tego_error{ex.what()}; + } + } + } + + template + auto translateExceptions(FUNC&& fn, tego_error_t** out_error, decltype(fn()) onErrorReturn) noexcept(true) -> decltype(fn()) + { + try + { + return fn(); + } + catch(const std::exception& ex) + { + if (out_error) + { + logger::println("Exception: {}", ex.what()); + *out_error = new tego_error{ex.what()}; + } + } + return onErrorReturn; + } +} \ No newline at end of file diff --git a/src/libtego/source/libtego.cpp b/src/libtego/source/libtego.cpp new file mode 100644 index 0000000..763d1ac --- /dev/null +++ b/src/libtego/source/libtego.cpp @@ -0,0 +1,20 @@ +#include "error.hpp" + +extern "C" +{ + void tego_initialize(tego_error_t** error) + { + return tego::translateExceptions([]() -> void + { + + }, error); + } + + void tego_uninitialize(tego_error_t** error) + { + return tego::translateExceptions([]() -> void + { + + }, error); + } +} \ No newline at end of file diff --git a/src/libtego/source/logger.cpp b/src/libtego/source/logger.cpp new file mode 100644 index 0000000..dcd93b9 --- /dev/null +++ b/src/libtego/source/logger.cpp @@ -0,0 +1,110 @@ +#ifdef ENABLE_TEGO_LOGGER + +// +// logger methods +// + +void logger::trace(const source_location& loc) +{ + println("{}({})", loc.file_name(), loc.line()); +} + +std::ofstream& logger::get_stream() +{ + static std::ofstream fs("libtego.log", std::ios::binary); + return fs; +} + +std::mutex& logger::get_mutex() +{ + static std::mutex m; + return m; +} + +double logger::get_timestamp() +{ + const static auto start = std::chrono::system_clock::now(); + const auto now = std::chrono::system_clock::now(); + std::chrono::duration duration(now - start); + return duration.count(); +} + +// +// std::ostream << operators +// + +std::ostream& operator<<(std::ostream& out, const QString& str) +{ + auto utf8str = str.toUtf8(); + out << utf8str.constData(); + return out; +} + +// hex dump QByteArray +std::ostream& operator<<(std::ostream& out, const QByteArray& blob) +{ + constexpr size_t rowWidth = 32; + const size_t rowCount = blob.size() / rowWidth; + + const char* head = blob.data(); + size_t address = 0; + + out << '\n'; + + auto printRow = [&](size_t count) -> void + { + constexpr auto octetGrouping = 4; + fmt::print(out, "{:08x} : ", address); + for(size_t k = 0; k < count; k++) + { + if ((k % octetGrouping) == 0) { + fmt::print(out, " "); + } + fmt::print(out, "{:02x}", (uint8_t)head[k]); + } + for(size_t k = count; k < rowWidth; k++) + { + if ((k % octetGrouping) == 0) { + fmt::print(out, " "); + } + fmt::print(out, ".."); + } + + fmt::print(out, " | "); + for(size_t k = 0; k < count; k++) + { + char c = head[k]; + if (std::isprint(c)) + { + fmt::print(out, "{}", c); + } + else + { + fmt::print(out, "."); + } + } + + out << '\n'; + + address += rowWidth; + head += rowWidth; + }; + + // foreach row + for(size_t i = 0; i < rowCount; i++) + { + printRow(rowWidth); + + } + + // remainder + const size_t remainder = (blob.size() % rowWidth); + if (remainder > 0) + { + printRow(remainder); + } + + return out; +} + +#endif // ENABLE_TEGO_LOGGER \ No newline at end of file diff --git a/src/libtego/source/orconfig.h b/src/libtego/source/orconfig.h new file mode 100644 index 0000000..788edbe --- /dev/null +++ b/src/libtego/source/orconfig.h @@ -0,0 +1,25 @@ +#ifndef ORCONFIG_H +#define ORCONFIG_H + +// This header provides needed #defines normally stored in the orconfig.h header +// generatd by the tor build process + +/* Define to 1 iff memset(0) sets pointers to NULL */ +#define NULL_REP_IS_ZERO_BYTES 1 + +/* Define to 1 iff memset(0) sets doubles to 0.0 */ +#define DOUBLE_0_REP_IS_ZERO_BYTES 1 + +/* Define to 1 if the system has the type `ssize_t'. */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 iff we represent negative integers with two's complement */ +#define USING_TWOS_COMPLEMENT 1 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* Define to 1 if you have the `EVP_sha3_256' function. */ +#define HAVE_EVP_SHA3_256 1 + +#endif // ORCONFIG_H \ No newline at end of file diff --git a/src/libtego/source/precomp.h b/src/libtego/source/precomp.h new file mode 100644 index 0000000..16560d8 --- /dev/null +++ b/src/libtego/source/precomp.h @@ -0,0 +1,45 @@ +// C headers + +// standard library +#include + +// tor +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +# include +# ifdef HAVE_EVP_SHA3_256 +# define OPENSSL_HAS_SHA3 +# endif // HAVE_EVP_SHA3_256 +# define ALL_BUGS_ARE_FATAL +# include +# include +# include +# include +# include +#ifdef __cplusplus +} + +// include our public header +#include + +#endif // __cplusplus + +// C++ headers +#ifdef __cplusplus + +// standard library +#include +#include +#include +#include + +// fmt +#include +#include + +// Qt +#include +#include + +#endif //__cplusplus#i \ No newline at end of file diff --git a/src/libtego/source/tor_stubs.cpp b/src/libtego/source/tor_stubs.cpp new file mode 100644 index 0000000..fcdac2e --- /dev/null +++ b/src/libtego/source/tor_stubs.cpp @@ -0,0 +1,56 @@ + +extern "C" +{ + void *tor_malloc_(size_t size) + { + return std::malloc(size); + } + + void *tor_malloc_zero_(size_t size) + { + void* retval = tor_malloc_(size); + if (retval) { + std::memset(retval, 0x00, size); + } + return retval; + } + + // convert assert to thrown exception + void tor_assertion_failed_( + const char *fname, + unsigned int line, + const char *func, + const char *expr, + const char *fmt, + ...) + { + (void)func; + (void)fmt; + throw std::runtime_error( + fmt::format("tor assertion failed {}:{} : {}", fname, line, expr)); + } + + // no-op, called as part of tor_assertion macro which + // ultimately goes to tor_assertion_failed which throws an exception + void tor_abort_(void) + { + throw std::runtime_error(__FUNCTION__); + } + + // no-op swallow logging calls + void log_fn_(int severity, log_domain_mask_t domain, const char *fn, + const char *format, ...) + { + (void)severity; + (void)domain; + (void)fn; + (void)format; + } + +#ifdef _WIN32 + const char* tor_fix_source_file(const char* fname) + { + return fname; + } +#endif +} diff --git a/src/core/ContactIDValidator.cpp b/src/libtego_ui/core/ContactIDValidator.cpp similarity index 88% rename from src/core/ContactIDValidator.cpp rename to src/libtego_ui/core/ContactIDValidator.cpp index 0d09d1d..0c0254a 100644 --- a/src/core/ContactIDValidator.cpp +++ b/src/libtego_ui/core/ContactIDValidator.cpp @@ -31,8 +31,11 @@ */ #include "ContactIDValidator.h" +#include "utils/StringUtil.h" -static QRegularExpression regex(QStringLiteral("(torsion|ricochet):([a-z2-7]{16})")); +// multiple consumers of this regex object seems to cause thread contention issues +// and segfaults, so make it thread_local to sidestep the issue for now +static thread_local QRegularExpression regex(QStringLiteral("(torsion|ricochet):([a-z2-7]{56})")); ContactIDValidator::ContactIDValidator(QObject *parent) : QRegularExpressionValidator(parent), m_uniqueIdentity(0) @@ -96,14 +99,11 @@ QString ContactIDValidator::hostnameFromID(const QString &ID) QString ContactIDValidator::idFromHostname(const QString &hostname) { - QString re = hostname; - - if (re.size() != 16) - { - if (re.size() == 22 && re.toLower().endsWith(QLatin1String(".onion"))) - re.chop(6); - else - return QString(); + #define DOT_ONION ".onion" + + QString re = hostname.toLower(); + if (re.endsWith(DOT_ONION)) { + re.chop(static_strlen(DOT_ONION)); } re.prepend(QStringLiteral("ricochet:")); diff --git a/src/core/ContactIDValidator.h b/src/libtego_ui/core/ContactIDValidator.h similarity index 98% rename from src/core/ContactIDValidator.h rename to src/libtego_ui/core/ContactIDValidator.h index f75e8a4..8b53c33 100644 --- a/src/core/ContactIDValidator.h +++ b/src/libtego_ui/core/ContactIDValidator.h @@ -33,7 +33,6 @@ #ifndef CONTACTIDVALIDATOR_H #define CONTACTIDVALIDATOR_H -#include #include "UserIdentity.h" class ContactIDValidator : public QRegularExpressionValidator diff --git a/src/core/ContactUser.cpp b/src/libtego_ui/core/ContactUser.cpp similarity index 99% rename from src/core/ContactUser.cpp rename to src/libtego_ui/core/ContactUser.cpp index 3bc7505..c0c5af5 100644 --- a/src/core/ContactUser.cpp +++ b/src/libtego_ui/core/ContactUser.cpp @@ -40,10 +40,6 @@ #include "core/ConversationModel.h" #include "tor/HiddenService.h" #include "protocol/OutboundConnector.h" -#include -#include -#include -#include ContactUser::ContactUser(UserIdentity *ident, int id, QObject *parent) : QObject(parent) diff --git a/src/core/ContactUser.h b/src/libtego_ui/core/ContactUser.h similarity index 98% rename from src/core/ContactUser.h rename to src/libtego_ui/core/ContactUser.h index 40ee9be..db01b1e 100644 --- a/src/core/ContactUser.h +++ b/src/libtego_ui/core/ContactUser.h @@ -33,11 +33,6 @@ #ifndef CONTACTUSER_H #define CONTACTUSER_H -#include -#include -#include -#include -#include #include "utils/Settings.h" #include "protocol/Connection.h" diff --git a/src/core/ContactsManager.cpp b/src/libtego_ui/core/ContactsManager.cpp similarity index 98% rename from src/core/ContactsManager.cpp rename to src/libtego_ui/core/ContactsManager.cpp index 05ffd76..e92abc5 100644 --- a/src/core/ContactsManager.cpp +++ b/src/libtego_ui/core/ContactsManager.cpp @@ -35,12 +35,6 @@ #include "OutgoingContactRequest.h" #include "ContactIDValidator.h" #include "ConversationModel.h" -#include -#include - -#ifdef Q_OS_MAC -#include -#endif ContactsManager *contactsManager = 0; diff --git a/src/core/ContactsManager.h b/src/libtego_ui/core/ContactsManager.h similarity index 99% rename from src/core/ContactsManager.h rename to src/libtego_ui/core/ContactsManager.h index 1c06277..94d294d 100644 --- a/src/core/ContactsManager.h +++ b/src/libtego_ui/core/ContactsManager.h @@ -33,8 +33,6 @@ #ifndef CONTACTSMANAGER_H #define CONTACTSMANAGER_H -#include -#include #include "ContactUser.h" #include "IncomingRequestManager.h" diff --git a/src/core/ConversationModel.cpp b/src/libtego_ui/core/ConversationModel.cpp similarity index 99% rename from src/core/ConversationModel.cpp rename to src/libtego_ui/core/ConversationModel.cpp index 96c6381..80b3280 100644 --- a/src/core/ConversationModel.cpp +++ b/src/libtego_ui/core/ConversationModel.cpp @@ -33,7 +33,6 @@ #include "ConversationModel.h" #include "protocol/Connection.h" #include "protocol/ChatChannel.h" -#include ConversationModel::ConversationModel(QObject *parent) : QAbstractListModel(parent) diff --git a/src/core/ConversationModel.h b/src/libtego_ui/core/ConversationModel.h similarity index 98% rename from src/core/ConversationModel.h rename to src/libtego_ui/core/ConversationModel.h index 5c95909..619aea2 100644 --- a/src/core/ConversationModel.h +++ b/src/libtego_ui/core/ConversationModel.h @@ -33,8 +33,6 @@ #ifndef CONVERSATIONMODEL_H #define CONVERSATIONMODEL_H -#include -#include #include "core/ContactUser.h" #include "protocol/ChatChannel.h" diff --git a/src/core/IdentityManager.cpp b/src/libtego_ui/core/IdentityManager.cpp similarity index 95% rename from src/core/IdentityManager.cpp rename to src/libtego_ui/core/IdentityManager.cpp index 4e8fd23..1e80835 100644 --- a/src/core/IdentityManager.cpp +++ b/src/libtego_ui/core/IdentityManager.cpp @@ -33,7 +33,6 @@ #include "IdentityManager.h" #include "ContactIDValidator.h" #include "core/OutgoingContactRequest.h" -#include IdentityManager *identityManager = 0; @@ -80,15 +79,12 @@ void IdentityManager::loadFromSettings() } } -UserIdentity *IdentityManager::createIdentity(const QString &serviceDirectory, const QString &nickname) +UserIdentity *IdentityManager::createIdentity() { - UserIdentity *identity = UserIdentity::createIdentity(++highestID, serviceDirectory); + UserIdentity *identity = UserIdentity::createIdentity(++highestID); if (!identity) return identity; - if (!nickname.isEmpty()) - identity->setNickname(nickname); - addIdentity(identity); return identity; diff --git a/src/core/IdentityManager.h b/src/libtego_ui/core/IdentityManager.h similarity index 95% rename from src/core/IdentityManager.h rename to src/libtego_ui/core/IdentityManager.h index ccf9fdf..f8a992a 100644 --- a/src/core/IdentityManager.h +++ b/src/libtego_ui/core/IdentityManager.h @@ -33,7 +33,6 @@ #ifndef IDENTITYMANAGER_H #define IDENTITYMANAGER_H -#include #include "UserIdentity.h" class IdentityManager : public QObject @@ -50,7 +49,7 @@ class IdentityManager : public QObject UserIdentity *lookupHostname(const QString &hostname) const; UserIdentity *lookupUniqueID(int uniqueID) const; - UserIdentity *createIdentity(const QString &serviceDirectory = QString(), const QString &nickname = QString()); + UserIdentity *createIdentity(); signals: void identityAdded(UserIdentity *identity); diff --git a/src/core/IncomingRequestManager.cpp b/src/libtego_ui/core/IncomingRequestManager.cpp similarity index 100% rename from src/core/IncomingRequestManager.cpp rename to src/libtego_ui/core/IncomingRequestManager.cpp diff --git a/src/core/IncomingRequestManager.h b/src/libtego_ui/core/IncomingRequestManager.h similarity index 98% rename from src/core/IncomingRequestManager.h rename to src/libtego_ui/core/IncomingRequestManager.h index 6c86f10..dc25743 100644 --- a/src/core/IncomingRequestManager.h +++ b/src/libtego_ui/core/IncomingRequestManager.h @@ -33,9 +33,6 @@ #ifndef INCOMINGREQUESTMANAGER_H #define INCOMINGREQUESTMANAGER_H -#include -#include -#include #include "protocol/Connection.h" class IncomingRequestManager; diff --git a/src/core/OutgoingContactRequest.cpp b/src/libtego_ui/core/OutgoingContactRequest.cpp similarity index 99% rename from src/core/OutgoingContactRequest.cpp rename to src/libtego_ui/core/OutgoingContactRequest.cpp index 4def05f..b1ff52e 100644 --- a/src/core/OutgoingContactRequest.cpp +++ b/src/libtego_ui/core/OutgoingContactRequest.cpp @@ -37,7 +37,6 @@ #include "IncomingRequestManager.h" #include "utils/Useful.h" #include "protocol/ContactRequestChannel.h" -#include OutgoingContactRequest *OutgoingContactRequest::createNewRequest(ContactUser *user, const QString &myNickname, const QString &message) diff --git a/src/core/OutgoingContactRequest.h b/src/libtego_ui/core/OutgoingContactRequest.h similarity index 99% rename from src/core/OutgoingContactRequest.h rename to src/libtego_ui/core/OutgoingContactRequest.h index a8df18e..8f94a17 100644 --- a/src/core/OutgoingContactRequest.h +++ b/src/libtego_ui/core/OutgoingContactRequest.h @@ -33,7 +33,6 @@ #ifndef OUTGOINGCONTACTREQUEST_H #define OUTGOINGCONTACTREQUEST_H -#include #include "utils/Settings.h" class ContactUser; diff --git a/src/core/UserIdentity.cpp b/src/libtego_ui/core/UserIdentity.cpp similarity index 86% rename from src/core/UserIdentity.cpp rename to src/libtego_ui/core/UserIdentity.cpp index 2c1d6c1..8f16151 100644 --- a/src/core/UserIdentity.cpp +++ b/src/libtego_ui/core/UserIdentity.cpp @@ -36,10 +36,6 @@ #include "core/ContactIDValidator.h" #include "protocol/Connection.h" #include "utils/Useful.h" -#include -#include -#include -#include using namespace Protocol; @@ -59,7 +55,7 @@ UserIdentity::UserIdentity(int id, QObject *parent) contacts.loadFromSettings(); } -UserIdentity *UserIdentity::createIdentity(int uniqueID, const QString &dataDirectory) +UserIdentity *UserIdentity::createIdentity(int uniqueID) { // There is actually no support for multiple identities currently. Q_ASSERT(uniqueID == 0); @@ -68,10 +64,6 @@ UserIdentity *UserIdentity::createIdentity(int uniqueID, const QString &dataDire SettingsObject settings(QStringLiteral("identity")); settings.write("initializing", true); - if (dataDirectory.isEmpty()) - settings.write("dataDirectory", QString::fromLatin1("data-%1").arg(uniqueID)); - else - settings.write("dataDirectory", dataDirectory); return new UserIdentity(uniqueID); } @@ -80,36 +72,22 @@ UserIdentity *UserIdentity::createIdentity(int uniqueID, const QString &dataDire void UserIdentity::setupService() { QString keyData = m_settings->read("serviceKey").toString(); - QString legacyDir = m_settings->read("dataDirectory").toString(); if (!keyData.isEmpty()) { CryptoKey key; - if (!key.loadFromData(QByteArray::fromBase64(keyData.toLatin1()), CryptoKey::PrivateKey, CryptoKey::DER)) { + if (!key.loadFromKeyBlob(keyData.toLatin1())) { qWarning() << "Cannot load service key from configuration"; return; } - - m_hiddenService = new Tor::HiddenService(key, legacyDir, this); - } else if (!legacyDir.isEmpty() && QFile::exists(legacyDir + QLatin1String("/private_key"))) { - qDebug() << "Attempting to load key from legacy filesystem format in" << legacyDir; - - CryptoKey key; - if (!key.loadFromFile(legacyDir + QLatin1String("/private_key"), CryptoKey::PrivateKey)) { - qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion"; - return; - } else { - keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64()); - m_settings->write("serviceKey", keyData); - m_hiddenService = new Tor::HiddenService(key, legacyDir, this); - } + m_hiddenService = new Tor::HiddenService(key, this); } else if (!m_settings->read("initializing").toBool()) { qWarning() << "Missing private key for initialized identity"; return; } else { - m_hiddenService = new Tor::HiddenService(legacyDir, this); + m_hiddenService = new Tor::HiddenService(this); connect(m_hiddenService, &Tor::HiddenService::privateKeyChanged, this, [&]() { - QString key = QString::fromLatin1(m_hiddenService->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64()); + QString key = QString::fromLatin1(m_hiddenService->privateKey().encodedKeyBlob()); m_settings->write("serviceKey", key); } ); diff --git a/src/core/UserIdentity.h b/src/libtego_ui/core/UserIdentity.h similarity index 95% rename from src/core/UserIdentity.h rename to src/libtego_ui/core/UserIdentity.h index 457227c..660a424 100644 --- a/src/core/UserIdentity.h +++ b/src/libtego_ui/core/UserIdentity.h @@ -34,10 +34,6 @@ #define USERIDENTITY_H #include "ContactsManager.h" -#include -#include -#include -#include namespace Tor { @@ -119,7 +115,7 @@ private slots: QTcpServer *m_incomingServer; QVector> m_incomingConnections; - static UserIdentity *createIdentity(int uniqueID, const QString &dataDirectory = QString()); + static UserIdentity *createIdentity(int uniqueID); void handleIncomingAuthedConnection(Protocol::Connection *connection); void setupService(); diff --git a/src/libtego_ui/libtego_ui.pri b/src/libtego_ui/libtego_ui.pri new file mode 100644 index 0000000..d2e8a8e --- /dev/null +++ b/src/libtego_ui/libtego_ui.pri @@ -0,0 +1,10 @@ +INCLUDEPATH += $${PWD} + +LIBS += -L$${DESTDIR}/../libtego_ui -ltego_ui + +macx { + QT += macextras +} +QMAKE_INCLUDES = $${PWD}/../qmake_includes +include($${QMAKE_INCLUDES}/protobuf.pri) +include($${QMAKE_INCLUDES}/openssl.pri) \ No newline at end of file diff --git a/src/libtego_ui/libtego_ui.pro b/src/libtego_ui/libtego_ui.pro new file mode 100644 index 0000000..9160036 --- /dev/null +++ b/src/libtego_ui/libtego_ui.pro @@ -0,0 +1,116 @@ +QMAKE_INCLUDES = $${PWD}/../qmake_includes + +include($${QMAKE_INCLUDES}/artifacts.pri) +include($${QMAKE_INCLUDES}/compiler_flags.pri) + +TEMPLATE = lib +TARGET = tego_ui +CONFIG += staticlib + +QT += core gui network quick widgets + +CONFIG(release,debug|release):DEFINES += QT_NO_DEBUG_OUTPUT QT_NO_WARNING_OUTPUT + +# INCLUDEPATH += $${PWD} +# INCLUDEPATH += $${PWD}/../extern/fmt/include + +macx { + QT += macextras +} + +CONFIG += precompile_header +PRECOMPILED_HEADER = precomp.hpp + +SOURCES += \ + ui/MainWindow.cpp \ + ui/ContactsModel.cpp \ + tor/TorControl.cpp \ + tor/TorControlSocket.cpp \ + tor/TorControlCommand.cpp \ + tor/ProtocolInfoCommand.cpp \ + tor/AuthenticateCommand.cpp \ + tor/SetConfCommand.cpp \ + tor/AddOnionCommand.cpp \ + utils/StringUtil.cpp \ + core/ContactsManager.cpp \ + core/ContactUser.cpp \ + tor/GetConfCommand.cpp \ + tor/HiddenService.cpp \ + utils/CryptoKey.cpp \ + utils/SecureRNG.cpp \ + core/OutgoingContactRequest.cpp \ + core/IncomingRequestManager.cpp \ + core/ContactIDValidator.cpp \ + core/UserIdentity.cpp \ + core/IdentityManager.cpp \ + core/ConversationModel.cpp \ + tor/TorProcess.cpp \ + tor/TorManager.cpp \ + tor/TorSocket.cpp \ + ui/LinkedText.cpp \ + utils/Settings.cpp \ + utils/PendingOperation.cpp \ + ui/LanguagesModel.cpp + +HEADERS += \ + ui/MainWindow.h \ + ui/ContactsModel.h \ + tor/TorControl.h \ + tor/TorControlSocket.h \ + tor/TorControlCommand.h \ + tor/ProtocolInfoCommand.h \ + tor/AuthenticateCommand.h \ + tor/SetConfCommand.h \ + tor/AddOnionCommand.h \ + utils/StringUtil.h \ + core/ContactsManager.h \ + core/ContactUser.h \ + tor/GetConfCommand.h \ + tor/HiddenService.h \ + utils/CryptoKey.h \ + utils/SecureRNG.h \ + core/OutgoingContactRequest.h \ + core/IncomingRequestManager.h \ + core/ContactIDValidator.h \ + core/UserIdentity.h \ + core/IdentityManager.h \ + core/ConversationModel.h \ + tor/TorProcess.h \ + tor/TorProcess_p.h \ + tor/TorManager.h \ + tor/TorSocket.h \ + ui/LinkedText.h \ + utils/Settings.h \ + utils/PendingOperation.h \ + ui/LanguagesModel.h + +SOURCES += \ + protocol/Channel.cpp \ + protocol/ControlChannel.cpp \ + protocol/Connection.cpp \ + protocol/OutboundConnector.cpp \ + protocol/AuthHiddenServiceChannel.cpp \ + protocol/ChatChannel.cpp \ + protocol/ContactRequestChannel.cpp + +HEADERS += \ + protocol/Channel.h \ + protocol/Channel_p.h \ + protocol/ControlChannel.h \ + protocol/Connection.h \ + protocol/Connection_p.h \ + protocol/OutboundConnector.h \ + protocol/AuthHiddenServiceChannel.h \ + protocol/ChatChannel.h \ + protocol/ContactRequestChannel.h + +include($${QMAKE_INCLUDES}/protobuf.pri) + +PROTOS += \ + protocol/ControlChannel.proto \ + protocol/AuthHiddenService.proto \ + protocol/ChatChannel.proto \ + protocol/ContactRequestChannel.proto + +include($${QMAKE_INCLUDES}/openssl.pri) +include($${PWD}/../libtego/libtego.pri) diff --git a/src/libtego_ui/precomp.hpp b/src/libtego_ui/precomp.hpp new file mode 100644 index 0000000..7298c58 --- /dev/null +++ b/src/libtego_ui/precomp.hpp @@ -0,0 +1,115 @@ +#include + +// C headers + +// os +#ifdef Q_OS_WIN +#define WIN32_LEAN_AND_MEAN +#include +#include +// workaround because protobuffer defines a GetMessage function +#undef GetMessage +#endif + +// standard library +#include + +// openssl +#include +#include +#include +#include +#include +#include + +// C++ headers +#ifdef __cplusplus + +// standard library +#include +#include +#include +#include +#include + +// Qt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef Q_OS_MAC +# include +#endif // Q_OS_MAC +#include +#include +#include +#include +#include +#include + +// tego +#include +#include + +#endif // __cplusplus + + diff --git a/src/protocol/AuthHiddenService.proto b/src/libtego_ui/protocol/AuthHiddenService.proto similarity index 76% rename from src/protocol/AuthHiddenService.proto rename to src/libtego_ui/protocol/AuthHiddenService.proto index afbe209..a6d4734 100644 --- a/src/protocol/AuthHiddenService.proto +++ b/src/libtego_ui/protocol/AuthHiddenService.proto @@ -1,3 +1,5 @@ +syntax = "proto2"; + package Protocol.Data.AuthHiddenService; import "ControlChannel.proto"; @@ -15,8 +17,8 @@ message Packet { } message Proof { - optional bytes public_key = 1; // DER encoded public key - optional bytes signature = 2; // RSA signature + optional bytes signature = 1; // RSA signature + optional string service_id = 2; // sans .onion prefix } message Result { diff --git a/src/protocol/AuthHiddenServiceChannel.cpp b/src/libtego_ui/protocol/AuthHiddenServiceChannel.cpp similarity index 81% rename from src/protocol/AuthHiddenServiceChannel.cpp rename to src/libtego_ui/protocol/AuthHiddenServiceChannel.cpp index 350c1ad..8814b91 100644 --- a/src/protocol/AuthHiddenServiceChannel.cpp +++ b/src/libtego_ui/protocol/AuthHiddenServiceChannel.cpp @@ -37,7 +37,7 @@ #include "utils/SecureRNG.h" #include "utils/CryptoKey.h" #include "utils/Useful.h" -#include +#include "utils/StringUtil.h" using namespace Protocol; @@ -193,31 +193,14 @@ void AuthHiddenServiceChannel::sendAuthMessage() return; } - QByteArray publicKey = d->privateKey.encodedPublicKey(CryptoKey::DER); - if (publicKey.size() > 150) { - BUG() << "Unexpected size for encoded public key"; - closeChannel(); - return; - } - - QByteArray signature; QByteArray proofData = d->getProofData(d->privateKey.torServiceID()); - if (!proofData.isEmpty()) { - QByteArray proofHMAC = QMessageAuthenticationCode::hash(proofData, d->clientCookie + d->serverCookie, - QCryptographicHash::Sha256); - signature = d->privateKey.signSHA256(proofHMAC); - } - - if (signature.isEmpty()) { - BUG() << "Creating proof on AuthHiddenServiceChannel failed"; - closeChannel(); - return; - } + auto signature = d->privateKey.signData(proofData); QScopedPointer proof(new Data::AuthHiddenService::Proof); - proof->set_public_key(std::string(publicKey.constData(), publicKey.size())); proof->set_signature(std::string(signature.constData(), signature.size())); + proof->set_service_id(d->privateKey.torServiceID().toStdString()); + Data::AuthHiddenService::Packet message; message.set_allocated_proof(proof.take()); sendMessage(message); @@ -227,15 +210,16 @@ void AuthHiddenServiceChannel::sendAuthMessage() QByteArray AuthHiddenServiceChannelPrivate::getProofData(const QString &client) { - QByteArray serverHostname = connection->serverHostname().toLatin1().mid(0, 16); + QByteArray serverHostname = connection->serverHostname().toLatin1().mid(0, TEGO_V3_ONION_SERVICE_ID_LENGTH); QByteArray clientHostname = client.toLatin1(); - if (clientHostname.size() != 16 || serverHostname.size() != 16) { + if (clientHostname.size() != TEGO_V3_ONION_SERVICE_ID_LENGTH || serverHostname.size() != TEGO_V3_ONION_SERVICE_ID_LENGTH) { BUG() << "AuthHiddenServiceChannel can't figure out the client and server hostnames"; return QByteArray(); } - return clientHostname + serverHostname; + auto proofData = clientHostname + serverHostname; + return proofData; } void AuthHiddenServiceChannel::receivePacket(const QByteArray &packet) @@ -272,42 +256,28 @@ void AuthHiddenServiceChannel::handleProof(const Data::AuthHiddenService::Proof return; } - QByteArray publicKeyData(message.public_key().c_str(), message.public_key().size()); QByteArray signature(message.signature().c_str(), message.signature().size()); + QByteArray serviceId(message.service_id().c_str(), message.service_id().size()); QScopedPointer result(new Data::AuthHiddenService::Result); + result->set_accepted(false); - // Hidden services always use a 1024bit key. A valid signature will always be exactly 128 bytes. CryptoKey publicKey; - if (signature.size() != 128) { - qWarning() << "Received invalid signature (size" << signature.size() << ") on" << type(); - } else if (publicKeyData.size() > 150) { - qWarning() << "Received invalid public key (size" << publicKeyData.size() << ") on" << type(); - } else if (!publicKey.loadFromData(publicKeyData, CryptoKey::PublicKey, CryptoKey::DER)) { + if(!publicKey.loadFromServiceId(serviceId)) { qWarning() << "Unable to parse public key from" << type(); - } else if (publicKey.bits() != 1024) { - qWarning() << "Received invalid public key (" << publicKey.bits() << "bits) on" << type(); + } + auto proofData = d->getProofData(serviceId); + if (publicKey.verifyData(proofData, signature)) { + result->set_accepted(true); } else { - bool ok = false; - QByteArray proofData = d->getProofData(publicKey.torServiceID()); - if (!proofData.isEmpty()) { - QByteArray proofHMAC = QMessageAuthenticationCode::hash(proofData, d->clientCookie + d->serverCookie, - QCryptographicHash::Sha256); - ok = publicKey.verifySHA256(proofHMAC, signature); - } - - if (!ok) { - qWarning() << "Signature verification failed on" << type(); - result->set_accepted(false); - } else { - result->set_accepted(true); - qDebug() << type() << "accepted inbound authentication for" << publicKey.torServiceID(); - } + qWarning() << "Signature verification failed on" << type(); } + const auto hostname = serviceId + ".onion"; + if (result->accepted()) { - connection()->grantAuthentication(Connection::HiddenServiceAuth, publicKey.torServiceID() + QStringLiteral(".onion")); + connection()->grantAuthentication(Connection::HiddenServiceAuth, hostname); d->accepted = true; result->set_is_known_contact(connection()->purpose() == Connection::Purpose::KnownContact); } else { diff --git a/src/protocol/AuthHiddenServiceChannel.h b/src/libtego_ui/protocol/AuthHiddenServiceChannel.h similarity index 100% rename from src/protocol/AuthHiddenServiceChannel.h rename to src/libtego_ui/protocol/AuthHiddenServiceChannel.h diff --git a/src/protocol/Channel.cpp b/src/libtego_ui/protocol/Channel.cpp similarity index 99% rename from src/protocol/Channel.cpp rename to src/libtego_ui/protocol/Channel.cpp index 891c73a..907e2bd 100644 --- a/src/protocol/Channel.cpp +++ b/src/libtego_ui/protocol/Channel.cpp @@ -34,8 +34,6 @@ #include "Connection_p.h" #include "ControlChannel.h" #include "utils/Useful.h" -#include - #include "AuthHiddenServiceChannel.h" #include "ChatChannel.h" #include "ContactRequestChannel.h" diff --git a/src/protocol/Channel.h b/src/libtego_ui/protocol/Channel.h similarity index 99% rename from src/protocol/Channel.h rename to src/libtego_ui/protocol/Channel.h index e6b13f8..2adbe23 100644 --- a/src/protocol/Channel.h +++ b/src/libtego_ui/protocol/Channel.h @@ -33,8 +33,6 @@ #ifndef PROTOCOL_CHANNEL_H #define PROTOCOL_CHANNEL_H -#include -#include #include "ControlChannel.pb.h" namespace Protocol diff --git a/src/protocol/Channel_p.h b/src/libtego_ui/protocol/Channel_p.h similarity index 99% rename from src/protocol/Channel_p.h rename to src/libtego_ui/protocol/Channel_p.h index 5178384..620e641 100644 --- a/src/protocol/Channel_p.h +++ b/src/libtego_ui/protocol/Channel_p.h @@ -36,7 +36,6 @@ #include "Channel.h" #include "Connection_p.h" #include "utils/Useful.h" -#include namespace Protocol { diff --git a/src/protocol/ChatChannel.cpp b/src/libtego_ui/protocol/ChatChannel.cpp similarity index 100% rename from src/protocol/ChatChannel.cpp rename to src/libtego_ui/protocol/ChatChannel.cpp diff --git a/src/protocol/ChatChannel.h b/src/libtego_ui/protocol/ChatChannel.h similarity index 98% rename from src/protocol/ChatChannel.h rename to src/libtego_ui/protocol/ChatChannel.h index d45cf66..aee1bea 100644 --- a/src/protocol/ChatChannel.h +++ b/src/libtego_ui/protocol/ChatChannel.h @@ -35,8 +35,6 @@ #include "Channel.h" #include "ChatChannel.pb.h" -#include -#include namespace Protocol { diff --git a/src/protocol/ChatChannel.proto b/src/libtego_ui/protocol/ChatChannel.proto similarity index 96% rename from src/protocol/ChatChannel.proto rename to src/libtego_ui/protocol/ChatChannel.proto index 30adac4..3a52e5b 100644 --- a/src/protocol/ChatChannel.proto +++ b/src/libtego_ui/protocol/ChatChannel.proto @@ -1,3 +1,5 @@ +syntax = "proto2"; + package Protocol.Data.Chat; message Packet { diff --git a/src/protocol/Connection.cpp b/src/libtego_ui/protocol/Connection.cpp similarity index 99% rename from src/protocol/Connection.cpp rename to src/libtego_ui/protocol/Connection.cpp index 042c858..00e2b6e 100644 --- a/src/protocol/Connection.cpp +++ b/src/libtego_ui/protocol/Connection.cpp @@ -33,10 +33,6 @@ #include "Connection_p.h" #include "ControlChannel.h" #include "utils/Useful.h" -#include -#include -#include -#include using namespace Protocol; @@ -469,7 +465,7 @@ int ConnectionPrivate::availableOutboundChannelId() // Find an unused id, trying a maximum of 100 times, using a random step to avoid collision for (int i = 0; i < 100 && channels.contains(nextOutboundChannelId); i++) { - nextOutboundChannelId += 1 + (qrand() % 200); + nextOutboundChannelId += 1 + (QRandomGenerator::global()->bounded(200)); if (evenNumbered) nextOutboundChannelId += nextOutboundChannelId % 2; if (nextOutboundChannelId > maxId) diff --git a/src/protocol/Connection.h b/src/libtego_ui/protocol/Connection.h similarity index 99% rename from src/protocol/Connection.h rename to src/libtego_ui/protocol/Connection.h index e29f1ac..d4a90f4 100644 --- a/src/protocol/Connection.h +++ b/src/libtego_ui/protocol/Connection.h @@ -33,8 +33,6 @@ #ifndef PROTOCOL_CONNECTION_H #define PROTOCOL_CONNECTION_H -#include -#include #include "Channel.h" class QTcpSocket; diff --git a/src/protocol/Connection_p.h b/src/libtego_ui/protocol/Connection_p.h similarity index 98% rename from src/protocol/Connection_p.h rename to src/libtego_ui/protocol/Connection_p.h index cdaad9c..41a34bf 100644 --- a/src/protocol/Connection_p.h +++ b/src/libtego_ui/protocol/Connection_p.h @@ -34,9 +34,6 @@ #define PROTOCOL_CONNECTION_P_H #include "Connection.h" -#include -#include -#include namespace Protocol { diff --git a/src/protocol/ContactRequestChannel.cpp b/src/libtego_ui/protocol/ContactRequestChannel.cpp similarity index 100% rename from src/protocol/ContactRequestChannel.cpp rename to src/libtego_ui/protocol/ContactRequestChannel.cpp diff --git a/src/protocol/ContactRequestChannel.h b/src/libtego_ui/protocol/ContactRequestChannel.h similarity index 100% rename from src/protocol/ContactRequestChannel.h rename to src/libtego_ui/protocol/ContactRequestChannel.h diff --git a/src/protocol/ContactRequestChannel.proto b/src/libtego_ui/protocol/ContactRequestChannel.proto similarity index 97% rename from src/protocol/ContactRequestChannel.proto rename to src/libtego_ui/protocol/ContactRequestChannel.proto index 75591d4..a1a81c4 100644 --- a/src/protocol/ContactRequestChannel.proto +++ b/src/libtego_ui/protocol/ContactRequestChannel.proto @@ -1,3 +1,5 @@ +syntax = "proto2"; + package Protocol.Data.ContactRequest; import "ControlChannel.proto"; diff --git a/src/protocol/ControlChannel.cpp b/src/libtego_ui/protocol/ControlChannel.cpp similarity index 99% rename from src/protocol/ControlChannel.cpp rename to src/libtego_ui/protocol/ControlChannel.cpp index 877ffdf..9eb7518 100644 --- a/src/protocol/ControlChannel.cpp +++ b/src/libtego_ui/protocol/ControlChannel.cpp @@ -34,8 +34,6 @@ #include "Channel_p.h" #include "Connection_p.h" #include "utils/Useful.h" -#include -#include using namespace Protocol; diff --git a/src/protocol/ControlChannel.h b/src/libtego_ui/protocol/ControlChannel.h similarity index 100% rename from src/protocol/ControlChannel.h rename to src/libtego_ui/protocol/ControlChannel.h diff --git a/src/protocol/ControlChannel.proto b/src/libtego_ui/protocol/ControlChannel.proto similarity index 98% rename from src/protocol/ControlChannel.proto rename to src/libtego_ui/protocol/ControlChannel.proto index 7d66516..40e3615 100644 --- a/src/protocol/ControlChannel.proto +++ b/src/libtego_ui/protocol/ControlChannel.proto @@ -1,3 +1,5 @@ +syntax = "proto2"; + package Protocol.Data.Control; message Packet { diff --git a/src/protocol/OutboundConnector.cpp b/src/libtego_ui/protocol/OutboundConnector.cpp similarity index 99% rename from src/protocol/OutboundConnector.cpp rename to src/libtego_ui/protocol/OutboundConnector.cpp index 410bbff..517463f 100644 --- a/src/protocol/OutboundConnector.cpp +++ b/src/libtego_ui/protocol/OutboundConnector.cpp @@ -35,7 +35,6 @@ #include "tor/TorSocket.h" #include "ControlChannel.h" #include "AuthHiddenServiceChannel.h" -#include using namespace Protocol; diff --git a/src/protocol/OutboundConnector.h b/src/libtego_ui/protocol/OutboundConnector.h similarity index 98% rename from src/protocol/OutboundConnector.h rename to src/libtego_ui/protocol/OutboundConnector.h index ba54059..69f895c 100644 --- a/src/protocol/OutboundConnector.h +++ b/src/libtego_ui/protocol/OutboundConnector.h @@ -33,8 +33,6 @@ #ifndef PROTOCOL_OUTBOUNDCONNECTOR_H #define PROTOCOL_OUTBOUNDCONNECTOR_H -#include -#include #include "Connection.h" #include "utils/CryptoKey.h" diff --git a/src/tor/AddOnionCommand.cpp b/src/libtego_ui/tor/AddOnionCommand.cpp similarity index 88% rename from src/tor/AddOnionCommand.cpp rename to src/libtego_ui/tor/AddOnionCommand.cpp index 53add93..483caea 100644 --- a/src/tor/AddOnionCommand.cpp +++ b/src/libtego_ui/tor/AddOnionCommand.cpp @@ -53,10 +53,10 @@ QByteArray AddOnionCommand::build() QByteArray out("ADD_ONION"); if (m_service->privateKey().isLoaded()) { - out += " RSA1024:"; - out += m_service->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64(); + out += " "; + out += m_service->privateKey().encodedKeyBlob(); } else { - out += " NEW:RSA1024"; + out += " NEW:ED25519-V3"; } foreach (const HiddenService::Target &target, m_service->targets()) { @@ -80,15 +80,16 @@ void AddOnionCommand::onReply(int statusCode, const QByteArray &data) return; } - const QByteArray keyPrefix("PrivateKey=RSA1024:"); - if (data.startsWith(keyPrefix)) { - QByteArray keyData(QByteArray::fromBase64(data.mid(keyPrefix.size()))); + const char PRIVATE_KEY_EQUALS[] = "PrivateKey="; + + if(data.startsWith(PRIVATE_KEY_EQUALS)) + { CryptoKey key; - if (!key.loadFromData(keyData, CryptoKey::PrivateKey, CryptoKey::DER)) { + if(!key.loadFromKeyBlob(data.mid(static_strlen(PRIVATE_KEY_EQUALS)))) + { m_errorMessage = QStringLiteral("Key decoding failed"); return; } - m_service->setPrivateKey(key); } } diff --git a/src/tor/AddOnionCommand.h b/src/libtego_ui/tor/AddOnionCommand.h similarity index 97% rename from src/tor/AddOnionCommand.h rename to src/libtego_ui/tor/AddOnionCommand.h index 7c0afaf..e9c2b46 100644 --- a/src/tor/AddOnionCommand.h +++ b/src/libtego_ui/tor/AddOnionCommand.h @@ -34,9 +34,6 @@ #define ADDONIONCOMMAND_H #include "TorControlCommand.h" -#include -#include -#include namespace Tor { diff --git a/src/tor/AuthenticateCommand.cpp b/src/libtego_ui/tor/AuthenticateCommand.cpp similarity index 100% rename from src/tor/AuthenticateCommand.cpp rename to src/libtego_ui/tor/AuthenticateCommand.cpp diff --git a/src/tor/AuthenticateCommand.h b/src/libtego_ui/tor/AuthenticateCommand.h similarity index 100% rename from src/tor/AuthenticateCommand.h rename to src/libtego_ui/tor/AuthenticateCommand.h diff --git a/src/tor/GetConfCommand.cpp b/src/libtego_ui/tor/GetConfCommand.cpp similarity index 99% rename from src/tor/GetConfCommand.cpp rename to src/libtego_ui/tor/GetConfCommand.cpp index 77b511e..6195219 100644 --- a/src/tor/GetConfCommand.cpp +++ b/src/libtego_ui/tor/GetConfCommand.cpp @@ -32,7 +32,6 @@ #include "GetConfCommand.h" #include "utils/StringUtil.h" -#include using namespace Tor; diff --git a/src/tor/GetConfCommand.h b/src/libtego_ui/tor/GetConfCommand.h similarity index 98% rename from src/tor/GetConfCommand.h rename to src/libtego_ui/tor/GetConfCommand.h index 0de97d1..72e479e 100644 --- a/src/tor/GetConfCommand.h +++ b/src/libtego_ui/tor/GetConfCommand.h @@ -34,8 +34,6 @@ #define GETCONFCOMMAND_H #include "TorControlCommand.h" -#include -#include namespace Tor { diff --git a/src/tor/HiddenService.cpp b/src/libtego_ui/tor/HiddenService.cpp similarity index 75% rename from src/tor/HiddenService.cpp rename to src/libtego_ui/tor/HiddenService.cpp index 0621400..1ebca35 100644 --- a/src/tor/HiddenService.cpp +++ b/src/libtego_ui/tor/HiddenService.cpp @@ -35,10 +35,6 @@ #include "TorSocket.h" #include "utils/CryptoKey.h" #include "utils/Useful.h" -#include -#include -#include -#include using namespace Tor; @@ -47,19 +43,8 @@ HiddenService::HiddenService(QObject *parent) { } -HiddenService::HiddenService(const QString &path, QObject *parent) - : QObject(parent), m_dataPath(path), m_status(NotCreated) -{ - /* Set the initial status and, if possible, load the hostname */ - if (QDir(m_dataPath).exists(QLatin1String("private_key"))) { - loadPrivateKey(); - if (!m_hostname.isEmpty()) - m_status = Offline; - } -} - -HiddenService::HiddenService(const CryptoKey &privateKey, const QString &path, QObject *parent) - : QObject(parent), m_dataPath(path), m_status(NotCreated) +HiddenService::HiddenService(const CryptoKey &privateKey, QObject *parent) + : QObject(parent), m_status(NotCreated) { setPrivateKey(privateKey); m_status = Offline; @@ -107,25 +92,8 @@ void HiddenService::setPrivateKey(const CryptoKey &key) emit privateKeyChanged(); } -void HiddenService::loadPrivateKey() -{ - if (m_privateKey.isLoaded() || m_dataPath.isEmpty()) - return; - - bool ok = m_privateKey.loadFromFile(m_dataPath + QLatin1String("/private_key"), CryptoKey::PrivateKey); - if (!ok) { - qWarning() << "Failed to load hidden service key"; - return; - } - - m_hostname = m_privateKey.torServiceID(); - emit privateKeyChanged(); -} - void HiddenService::servicePublished() { - loadPrivateKey(); - if (m_hostname.isEmpty()) { qDebug() << "Failed to read hidden service hostname"; return; diff --git a/src/tor/HiddenService.h b/src/libtego_ui/tor/HiddenService.h similarity index 89% rename from src/tor/HiddenService.h rename to src/libtego_ui/tor/HiddenService.h index af7790e..501674c 100644 --- a/src/tor/HiddenService.h +++ b/src/libtego_ui/tor/HiddenService.h @@ -33,9 +33,6 @@ #ifndef HIDDENSERVICE_H #define HIDDENSERVICE_H -#include -#include -#include #include "utils/CryptoKey.h" namespace Tor @@ -65,13 +62,11 @@ class HiddenService : public QObject }; HiddenService(QObject *parent = 0); - HiddenService(const QString &dataPath, QObject *parent = 0); - HiddenService(const CryptoKey &privateKey, const QString &dataPath = QString(), QObject *parent = 0); + HiddenService(const CryptoKey &privateKey, QObject *parent = 0); Status status() const { return m_status; } const QString &hostname() const { return m_hostname; } - const QString &dataPath() const { return m_dataPath; } CryptoKey privateKey() { return m_privateKey; } void setPrivateKey(const CryptoKey &privateKey); @@ -89,13 +84,11 @@ private slots: void servicePublished(); private: - QString m_dataPath; QList m_targets; QString m_hostname; Status m_status; CryptoKey m_privateKey; - void loadPrivateKey(); void setStatus(Status newStatus); }; diff --git a/src/tor/ProtocolInfoCommand.cpp b/src/libtego_ui/tor/ProtocolInfoCommand.cpp similarity index 99% rename from src/tor/ProtocolInfoCommand.cpp rename to src/libtego_ui/tor/ProtocolInfoCommand.cpp index 8222d80..70c61c8 100644 --- a/src/tor/ProtocolInfoCommand.cpp +++ b/src/libtego_ui/tor/ProtocolInfoCommand.cpp @@ -33,7 +33,6 @@ #include "ProtocolInfoCommand.h" #include "TorControl.h" #include "utils/StringUtil.h" -#include using namespace Tor; diff --git a/src/tor/ProtocolInfoCommand.h b/src/libtego_ui/tor/ProtocolInfoCommand.h similarity index 99% rename from src/tor/ProtocolInfoCommand.h rename to src/libtego_ui/tor/ProtocolInfoCommand.h index 7789cfe..c484556 100644 --- a/src/tor/ProtocolInfoCommand.h +++ b/src/libtego_ui/tor/ProtocolInfoCommand.h @@ -34,7 +34,6 @@ #define PROTOCOLINFOCOMMAND_H #include "TorControlCommand.h" -#include namespace Tor { diff --git a/src/tor/SetConfCommand.cpp b/src/libtego_ui/tor/SetConfCommand.cpp similarity index 100% rename from src/tor/SetConfCommand.cpp rename to src/libtego_ui/tor/SetConfCommand.cpp diff --git a/src/tor/SetConfCommand.h b/src/libtego_ui/tor/SetConfCommand.h similarity index 97% rename from src/tor/SetConfCommand.h rename to src/libtego_ui/tor/SetConfCommand.h index 5bdcb93..79f3384 100644 --- a/src/tor/SetConfCommand.h +++ b/src/libtego_ui/tor/SetConfCommand.h @@ -34,9 +34,6 @@ #define SETCONFCOMMAND_H #include "TorControlCommand.h" -#include -#include -#include namespace Tor { diff --git a/src/tor/TorControl.cpp b/src/libtego_ui/tor/TorControl.cpp similarity index 88% rename from src/tor/TorControl.cpp rename to src/libtego_ui/tor/TorControl.cpp index e4c81fa..4cee540 100644 --- a/src/tor/TorControl.cpp +++ b/src/libtego_ui/tor/TorControl.cpp @@ -41,14 +41,6 @@ #include "utils/StringUtil.h" #include "utils/Settings.h" #include "utils/PendingOperation.h" -#include -#include -#include -#include -#include -#include -#include -#include Tor::TorControl *torControl = 0; @@ -484,55 +476,16 @@ void TorControlPrivate::publishServices() return; } - if (q->torVersionAsNewAs(QStringLiteral("0.2.7"))) { - foreach (HiddenService *service, services) { - if (service->hostname().isEmpty()) - qDebug() << "torctrl: Creating a new hidden service"; - else - qDebug() << "torctrl: Publishing hidden service" << service->hostname(); - AddOnionCommand *onionCommand = new AddOnionCommand(service); - QObject::connect(onionCommand, &AddOnionCommand::succeeded, service, &HiddenService::servicePublished); - socket->sendCommand(onionCommand, onionCommand->build()); - } - } else { - qDebug() << "torctrl: Using legacy SETCONF hidden service configuration for tor" << torVersion; - SetConfCommand *command = new SetConfCommand; - QList > torConfig; - - foreach (HiddenService *service, services) - { - if (service->dataPath().isEmpty()) - continue; - - if (service->privateKey().isLoaded() && !QFile::exists(service->dataPath() + QStringLiteral("/private_key"))) { - // This case can happen if tor is downgraded after the profile is created - qWarning() << "Cannot publish ephemeral hidden services with this version of tor; skipping"; - continue; - } + Q_ASSERT(q->torVersionAsNewAs(QStringLiteral("0.2.7"))); - qDebug() << "torctrl: Configuring hidden service at" << service->dataPath(); - - QDir dir(service->dataPath()); - torConfig.append(qMakePair(QByteArray("HiddenServiceDir"), dir.absolutePath().toLocal8Bit())); - - const QList &targets = service->targets(); - for (QList::ConstIterator tit = targets.begin(); tit != targets.end(); ++tit) - { - QString target = QString::fromLatin1("%1 %2:%3").arg(tit->servicePort) - .arg(tit->targetAddress.toString()) - .arg(tit->targetPort); - torConfig.append(qMakePair(QByteArray("HiddenServicePort"), target.toLatin1())); - - // Via github user @kradan: https://github.com/kradan/ricochet/commit/a34e8123b382b6e4ec490c633141510f26ff11dd - QString version = QString::fromLatin1("3"); - torConfig.append(qMakePair(QByteArray("HiddenServiceVersion"), version.toLatin1())); - } - - QObject::connect(command, &SetConfCommand::setConfSucceeded, service, &HiddenService::servicePublished); - } - - if (!torConfig.isEmpty()) - socket->sendCommand(command, command->build(torConfig)); + foreach (HiddenService *service, services) { + if (service->hostname().isEmpty()) + qDebug() << "torctrl: Creating a new hidden service"; + else + qDebug() << "torctrl: Publishing hidden service" << service->hostname(); + AddOnionCommand *onionCommand = new AddOnionCommand(service); + QObject::connect(onionCommand, &AddOnionCommand::succeeded, service, &HiddenService::servicePublished); + socket->sendCommand(onionCommand, onionCommand->build()); } } diff --git a/src/tor/TorControl.h b/src/libtego_ui/tor/TorControl.h similarity index 99% rename from src/tor/TorControl.h rename to src/libtego_ui/tor/TorControl.h index 23b9b71..bb6abd4 100644 --- a/src/tor/TorControl.h +++ b/src/libtego_ui/tor/TorControl.h @@ -33,8 +33,6 @@ #ifndef TORCONTROL_H #define TORCONTROL_H -#include -#include #include "utils/PendingOperation.h" class QNetworkProxy; diff --git a/src/tor/TorControlCommand.cpp b/src/libtego_ui/tor/TorControlCommand.cpp similarity index 99% rename from src/tor/TorControlCommand.cpp rename to src/libtego_ui/tor/TorControlCommand.cpp index 48d4aab..1fe0811 100644 --- a/src/tor/TorControlCommand.cpp +++ b/src/libtego_ui/tor/TorControlCommand.cpp @@ -31,7 +31,6 @@ */ #include "TorControlCommand.h" -#include using namespace Tor; diff --git a/src/tor/TorControlCommand.h b/src/libtego_ui/tor/TorControlCommand.h similarity index 98% rename from src/tor/TorControlCommand.h rename to src/libtego_ui/tor/TorControlCommand.h index 8943810..6fb9f76 100644 --- a/src/tor/TorControlCommand.h +++ b/src/libtego_ui/tor/TorControlCommand.h @@ -33,9 +33,6 @@ #ifndef TORCONTROLCOMMAND_H #define TORCONTROLCOMMAND_H -#include -#include - namespace Tor { diff --git a/src/tor/TorControlSocket.cpp b/src/libtego_ui/tor/TorControlSocket.cpp similarity index 99% rename from src/tor/TorControlSocket.cpp rename to src/libtego_ui/tor/TorControlSocket.cpp index 33b411c..23cb306 100644 --- a/src/tor/TorControlSocket.cpp +++ b/src/libtego_ui/tor/TorControlSocket.cpp @@ -32,7 +32,6 @@ #include "TorControlSocket.h" #include "TorControlCommand.h" -#include using namespace Tor; diff --git a/src/tor/TorControlSocket.h b/src/libtego_ui/tor/TorControlSocket.h similarity index 98% rename from src/tor/TorControlSocket.h rename to src/libtego_ui/tor/TorControlSocket.h index 2db9115..af62b2e 100644 --- a/src/tor/TorControlSocket.h +++ b/src/libtego_ui/tor/TorControlSocket.h @@ -33,9 +33,6 @@ #ifndef TORCONTROLSOCKET_H #define TORCONTROLSOCKET_H -#include -#include - namespace Tor { diff --git a/src/tor/TorManager.cpp b/src/libtego_ui/tor/TorManager.cpp similarity index 99% rename from src/tor/TorManager.cpp rename to src/libtego_ui/tor/TorManager.cpp index 27f814c..dc2c021 100644 --- a/src/tor/TorManager.cpp +++ b/src/libtego_ui/tor/TorManager.cpp @@ -35,9 +35,6 @@ #include "TorControl.h" #include "GetConfCommand.h" #include "utils/Settings.h" -#include -#include -#include using namespace Tor; diff --git a/src/tor/TorManager.h b/src/libtego_ui/tor/TorManager.h similarity index 98% rename from src/tor/TorManager.h rename to src/libtego_ui/tor/TorManager.h index 1de5133..d26a24f 100644 --- a/src/tor/TorManager.h +++ b/src/libtego_ui/tor/TorManager.h @@ -33,9 +33,6 @@ #ifndef TORMANAGER_H #define TORMANAGER_H -#include -#include - namespace Tor { diff --git a/src/tor/TorProcess.cpp b/src/libtego_ui/tor/TorProcess.cpp similarity index 99% rename from src/tor/TorProcess.cpp rename to src/libtego_ui/tor/TorProcess.cpp index 0601578..12e1338 100644 --- a/src/tor/TorProcess.cpp +++ b/src/libtego_ui/tor/TorProcess.cpp @@ -33,9 +33,6 @@ #include "TorProcess_p.h" #include "utils/CryptoKey.h" #include "utils/SecureRNG.h" -#include -#include -#include using namespace Tor; @@ -56,7 +53,7 @@ TorProcessPrivate::TorProcessPrivate(TorProcess *q) connect(&process, &QProcess::started, this, &TorProcessPrivate::processStarted); connect(&process, (void (QProcess::*)(int, QProcess::ExitStatus))&QProcess::finished, this, &TorProcessPrivate::processFinished); - connect(&process, (void (QProcess::*)(QProcess::ProcessError))&QProcess::error, + connect(&process, (void (QProcess::*)(QProcess::ProcessError))&QProcess::errorOccurred, this, &TorProcessPrivate::processError); connect(&process, &QProcess::readyRead, this, &TorProcessPrivate::processReadable); diff --git a/src/tor/TorProcess.h b/src/libtego_ui/tor/TorProcess.h similarity index 98% rename from src/tor/TorProcess.h rename to src/libtego_ui/tor/TorProcess.h index ad489dc..c4ff5fc 100644 --- a/src/tor/TorProcess.h +++ b/src/libtego_ui/tor/TorProcess.h @@ -33,9 +33,6 @@ #ifndef TORPROCESS_H #define TORPROCESS_H -#include -#include - namespace Tor { diff --git a/src/tor/TorProcess_p.h b/src/libtego_ui/tor/TorProcess_p.h similarity index 98% rename from src/tor/TorProcess_p.h rename to src/libtego_ui/tor/TorProcess_p.h index 9aa2585..60dc5e2 100644 --- a/src/tor/TorProcess_p.h +++ b/src/libtego_ui/tor/TorProcess_p.h @@ -34,8 +34,6 @@ #define TORPROCESS_P_H #include "TorProcess.h" -#include -#include namespace Tor { diff --git a/src/tor/TorSocket.cpp b/src/libtego_ui/tor/TorSocket.cpp similarity index 99% rename from src/tor/TorSocket.cpp rename to src/libtego_ui/tor/TorSocket.cpp index 615369b..a18b71b 100644 --- a/src/tor/TorSocket.cpp +++ b/src/libtego_ui/tor/TorSocket.cpp @@ -32,7 +32,6 @@ #include "TorSocket.h" #include "TorControl.h" -#include using namespace Tor; diff --git a/src/tor/TorSocket.h b/src/libtego_ui/tor/TorSocket.h similarity index 98% rename from src/tor/TorSocket.h rename to src/libtego_ui/tor/TorSocket.h index 0c68f78..066ea04 100644 --- a/src/tor/TorSocket.h +++ b/src/libtego_ui/tor/TorSocket.h @@ -33,9 +33,6 @@ #ifndef TORSOCKET_H #define TORSOCKET_H -#include -#include - namespace Tor { /* Specialized QTcpSocket which makes connections over the SOCKS proxy diff --git a/src/ui/ContactsModel.cpp b/src/libtego_ui/ui/ContactsModel.cpp similarity index 97% rename from src/ui/ContactsModel.cpp rename to src/libtego_ui/ui/ContactsModel.cpp index 6a9a878..cc382ea 100644 --- a/src/ui/ContactsModel.cpp +++ b/src/libtego_ui/ui/ContactsModel.cpp @@ -33,7 +33,6 @@ #include "ContactsModel.h" #include "core/IdentityManager.h" #include "core/ContactsManager.h" -#include inline bool contactSort(const ContactUser *c1, const ContactUser *c2) { @@ -134,7 +133,7 @@ void ContactsModel::contactAdded(ContactUser *user) connectSignals(user); - QList::Iterator lp = qLowerBound(contacts.begin(), contacts.end(), user, contactSort); + QList::Iterator lp = std::lower_bound(contacts.begin(), contacts.end(), user, contactSort); int row = lp - contacts.begin(); beginInsertRows(QModelIndex(), row, row); diff --git a/src/ui/ContactsModel.h b/src/libtego_ui/ui/ContactsModel.h similarity index 98% rename from src/ui/ContactsModel.h rename to src/libtego_ui/ui/ContactsModel.h index 3d60a0d..92ee0c9 100644 --- a/src/ui/ContactsModel.h +++ b/src/libtego_ui/ui/ContactsModel.h @@ -33,9 +33,6 @@ #ifndef CONTACTSMODEL_H #define CONTACTSMODEL_H -#include -#include - class UserIdentity; class ContactUser; diff --git a/src/ui/LanguagesModel.cpp b/src/libtego_ui/ui/LanguagesModel.cpp similarity index 98% rename from src/ui/LanguagesModel.cpp rename to src/libtego_ui/ui/LanguagesModel.cpp index 3f7eb2d..98f031b 100644 --- a/src/ui/LanguagesModel.cpp +++ b/src/libtego_ui/ui/LanguagesModel.cpp @@ -31,9 +31,6 @@ */ #include "LanguagesModel.h" -#include -#include -#include LanguagesModel::LanguagesModel(QObject* parent) : QAbstractListModel(parent) diff --git a/src/ui/LanguagesModel.h b/src/libtego_ui/ui/LanguagesModel.h similarity index 98% rename from src/ui/LanguagesModel.h rename to src/libtego_ui/ui/LanguagesModel.h index 797e8ee..67a1da7 100644 --- a/src/ui/LanguagesModel.h +++ b/src/libtego_ui/ui/LanguagesModel.h @@ -33,8 +33,6 @@ #ifndef LANGUAGESMODEL_H #define LANGUAGESMODEL_H -#include - class LanguagesModel : public QAbstractListModel { Q_OBJECT diff --git a/src/ui/LinkedText.cpp b/src/libtego_ui/ui/LinkedText.cpp similarity index 96% rename from src/ui/LinkedText.cpp rename to src/libtego_ui/ui/LinkedText.cpp index ec9ae68..a178410 100644 --- a/src/ui/LinkedText.cpp +++ b/src/libtego_ui/ui/LinkedText.cpp @@ -31,11 +31,6 @@ */ #include "LinkedText.h" -#include -#include -#include -#include -#include LinkedText::LinkedText(QObject *parent) : QObject(parent) diff --git a/src/ui/LinkedText.h b/src/libtego_ui/ui/LinkedText.h similarity index 97% rename from src/ui/LinkedText.h rename to src/libtego_ui/ui/LinkedText.h index deb7475..c24c72d 100644 --- a/src/ui/LinkedText.h +++ b/src/libtego_ui/ui/LinkedText.h @@ -33,9 +33,6 @@ #ifndef LINKEDTEXT_H #define LINKEDTEXT_H -#include -#include - class LinkedText : public QObject { Q_OBJECT diff --git a/src/ui/MainWindow.cpp b/src/libtego_ui/ui/MainWindow.cpp similarity index 96% rename from src/ui/MainWindow.cpp rename to src/libtego_ui/ui/MainWindow.cpp index 356b652..4fa9a0c 100644 --- a/src/ui/MainWindow.cpp +++ b/src/libtego_ui/ui/MainWindow.cpp @@ -46,16 +46,7 @@ #include "utils/PendingOperation.h" #include "utils/Useful.h" #include "ui/LanguagesModel.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + MainWindow *uiMain = 0; @@ -81,6 +72,8 @@ class BlockedNetworkAccessManager : public QNetworkAccessManager /* Either of these is sufficient to cause any network request to fail. * Both of them should be redundant, because createRequest below also * blackholes every request (and crashes for assert builds). */ + + /* XXX: setNetworkAccessible is deprecated */ setNetworkAccessible(QNetworkAccessManager::NotAccessible); setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QLatin1String("0.0.0.0"), 0)); } diff --git a/src/ui/MainWindow.h b/src/libtego_ui/ui/MainWindow.h similarity index 98% rename from src/ui/MainWindow.h rename to src/libtego_ui/ui/MainWindow.h index 575789c..b5f44fd 100644 --- a/src/ui/MainWindow.h +++ b/src/libtego_ui/ui/MainWindow.h @@ -33,9 +33,6 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include -#include - class ContactUser; class UserIdentity; class IncomingContactRequest; diff --git a/src/ui/qml/AboutPreferences.qml b/src/libtego_ui/ui/qml/AboutPreferences.qml similarity index 100% rename from src/ui/qml/AboutPreferences.qml rename to src/libtego_ui/ui/qml/AboutPreferences.qml diff --git a/src/ui/qml/AddContactDialog.qml b/src/libtego_ui/ui/qml/AddContactDialog.qml similarity index 97% rename from src/ui/qml/AddContactDialog.qml rename to src/libtego_ui/ui/qml/AddContactDialog.qml index 4c9a982..945d281 100644 --- a/src/ui/qml/AddContactDialog.qml +++ b/src/libtego_ui/ui/qml/AddContactDialog.qml @@ -4,7 +4,7 @@ import QtQuick.Layouts 1.0 ApplicationWindow { id: addContactWindow - width: 400 + width: 620 height: 300 minimumWidth: width maximumWidth: width @@ -56,7 +56,7 @@ ApplicationWindow { Layout.fillWidth: true readOnly: true text: userIdentity.contactID - horizontalAlignment: Qt.AlignHCenter + horizontalAlignment: Qt.AlignLeft } Item { height: 1 } diff --git a/src/ui/qml/AudioNotifications.qml b/src/libtego_ui/ui/qml/AudioNotifications.qml similarity index 100% rename from src/ui/qml/AudioNotifications.qml rename to src/libtego_ui/ui/qml/AudioNotifications.qml diff --git a/src/ui/qml/Bubble.qml b/src/libtego_ui/ui/qml/Bubble.qml similarity index 100% rename from src/ui/qml/Bubble.qml rename to src/libtego_ui/ui/qml/Bubble.qml diff --git a/src/ui/qml/ChatMessageArea.qml b/src/libtego_ui/ui/qml/ChatMessageArea.qml similarity index 100% rename from src/ui/qml/ChatMessageArea.qml rename to src/libtego_ui/ui/qml/ChatMessageArea.qml diff --git a/src/ui/qml/ChatPage.qml b/src/libtego_ui/ui/qml/ChatPage.qml similarity index 94% rename from src/ui/qml/ChatPage.qml rename to src/libtego_ui/ui/qml/ChatPage.qml index e24a3a9..64677ad 100644 --- a/src/ui/qml/ChatPage.qml +++ b/src/libtego_ui/ui/qml/ChatPage.qml @@ -24,7 +24,9 @@ FocusScope { Connections { target: conversationModel - onUnreadCountChanged: if (active) conversationModel.resetUnreadCount() + function onUnreadCountChanged(user, unreadCount) { + if (active) conversationModel.resetUnreadCount() + } } RowLayout { @@ -40,11 +42,12 @@ FocusScope { spacing: 8 PresenceIcon { - status: contact.status + // 1 = Status::Offline + status: contact != null ? contact.status : 1 } Label { - text: contact.nickname + text: contact != null ? contact.nickname : "" textFormat: Text.PlainText font.pointSize: styleHelper.pointSize } diff --git a/src/ui/qml/ChatWindow.qml b/src/libtego_ui/ui/qml/ChatWindow.qml similarity index 100% rename from src/ui/qml/ChatWindow.qml rename to src/libtego_ui/ui/qml/ChatWindow.qml diff --git a/src/ui/qml/ContactActions.qml b/src/libtego_ui/ui/qml/ContactActions.qml similarity index 100% rename from src/ui/qml/ContactActions.qml rename to src/libtego_ui/ui/qml/ContactActions.qml diff --git a/src/ui/qml/ContactIDField.qml b/src/libtego_ui/ui/qml/ContactIDField.qml similarity index 100% rename from src/ui/qml/ContactIDField.qml rename to src/libtego_ui/ui/qml/ContactIDField.qml diff --git a/src/ui/qml/ContactList.qml b/src/libtego_ui/ui/qml/ContactList.qml similarity index 100% rename from src/ui/qml/ContactList.qml rename to src/libtego_ui/ui/qml/ContactList.qml diff --git a/src/ui/qml/ContactListDelegate.qml b/src/libtego_ui/ui/qml/ContactListDelegate.qml similarity index 98% rename from src/ui/qml/ContactListDelegate.qml rename to src/libtego_ui/ui/qml/ContactListDelegate.qml index 15f7c27..231736f 100644 --- a/src/ui/qml/ContactListDelegate.qml +++ b/src/libtego_ui/ui/qml/ContactListDelegate.qml @@ -5,7 +5,7 @@ import im.ricochet 1.0 Rectangle { id: delegate color: highlighted ? "#c4e7ff" : "white" - width: parent.width + width: parent != null ? parent.width : 0 height: nameLabel.height + 8 property bool highlighted: ListView.isCurrentItem diff --git a/src/ui/qml/ContactPreferences.qml b/src/libtego_ui/ui/qml/ContactPreferences.qml similarity index 100% rename from src/ui/qml/ContactPreferences.qml rename to src/libtego_ui/ui/qml/ContactPreferences.qml diff --git a/src/ui/qml/ContactRequestDialog.qml b/src/libtego_ui/ui/qml/ContactRequestDialog.qml similarity index 96% rename from src/ui/qml/ContactRequestDialog.qml rename to src/libtego_ui/ui/qml/ContactRequestDialog.qml index 22b7d21..835ddb8 100644 --- a/src/ui/qml/ContactRequestDialog.qml +++ b/src/libtego_ui/ui/qml/ContactRequestDialog.qml @@ -18,7 +18,7 @@ ApplicationWindow { onVisibleChanged: if (!visible) closed() property QtObject request - property bool hasValidContact: request.hostname != "" && fields.name.text.length + property bool hasValidContact: request != null && request.hostname != "" && fields.name.text.length function close() { visible = false diff --git a/src/ui/qml/ContactRequestFields.qml b/src/libtego_ui/ui/qml/ContactRequestFields.qml similarity index 100% rename from src/ui/qml/ContactRequestFields.qml rename to src/libtego_ui/ui/qml/ContactRequestFields.qml diff --git a/src/ui/qml/ContactWindow.js b/src/libtego_ui/ui/qml/ContactWindow.js similarity index 100% rename from src/ui/qml/ContactWindow.js rename to src/libtego_ui/ui/qml/ContactWindow.js diff --git a/src/ui/qml/GeneralPreferences.qml b/src/libtego_ui/ui/qml/GeneralPreferences.qml similarity index 100% rename from src/ui/qml/GeneralPreferences.qml rename to src/libtego_ui/ui/qml/GeneralPreferences.qml diff --git a/src/ui/qml/MainToolBar.qml b/src/libtego_ui/ui/qml/MainToolBar.qml similarity index 97% rename from src/ui/qml/MainToolBar.qml rename to src/libtego_ui/ui/qml/MainToolBar.qml index a384a1a..41bfe13 100644 --- a/src/ui/qml/MainToolBar.qml +++ b/src/libtego_ui/ui/qml/MainToolBar.qml @@ -51,7 +51,7 @@ ToolBar { width: parent.width TorStateWidget { - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } Item { diff --git a/src/ui/qml/MainWindow.qml b/src/libtego_ui/ui/qml/MainWindow.qml similarity index 93% rename from src/ui/qml/MainWindow.qml rename to src/libtego_ui/ui/qml/MainWindow.qml index b318995..5b8e8de 100644 --- a/src/ui/qml/MainWindow.qml +++ b/src/libtego_ui/ui/qml/MainWindow.qml @@ -10,14 +10,12 @@ ApplicationWindow { title: "Ricochet" visibility: Window.AutomaticVisibility - width: 250 + width: 650 height: 400 minimumHeight: 400 minimumWidth: uiSettings.data.combinedChatWindow ? 650 : 250 - maximumWidth: uiSettings.data.combinedChatWindow ? (1 << 24) - 1 : 250 onMinimumWidthChanged: width = Math.max(width, minimumWidth) - onMaximumWidthChanged: width = Math.min(width, maximumWidth) // OS X Menu Loader { @@ -35,7 +33,7 @@ ApplicationWindow { Connections { target: userIdentity.contacts - onUnreadCountChanged: { + function onUnreadCountChanged(user, unreadCount) { if (unreadCount > 0) { if (audioNotifications !== null) audioNotifications.message.play() @@ -46,7 +44,7 @@ ApplicationWindow { w.alert(Qt.platform.os == "osx" ? 1000 : 0) } } - onContactStatusChanged: { + function onContactStatusChanged(user, status) { if (status === ContactUser.Online && audioNotifications !== null) { audioNotifications.contactOnline.play() } @@ -77,7 +75,7 @@ ApplicationWindow { anchors.fill: parent opacity: offlineLoader.item !== null ? (1 - offlineLoader.item.opacity) : 1 - onContactActivated: { + function onContactActivated(contact, actions) { if (contact.status === ContactUser.RequestPending || contact.status === ContactUser.RequestRejected) { actions.openPreferences() } else if (!uiSettings.data.combinedChatWindow) { @@ -88,7 +86,7 @@ ApplicationWindow { Loader { id: offlineLoader - active: torControl.torStatus !== TorControl.TorReady || (item !== null && item.visible) + active: torControl.torStatus !== TorControl.TorReady anchors.fill: parent source: Qt.resolvedUrl("OfflineStateItem.qml") } diff --git a/src/ui/qml/MessageDelegate.qml b/src/libtego_ui/ui/qml/MessageDelegate.qml similarity index 100% rename from src/ui/qml/MessageDelegate.qml rename to src/libtego_ui/ui/qml/MessageDelegate.qml diff --git a/src/ui/qml/MessageDialogWrapper.qml b/src/libtego_ui/ui/qml/MessageDialogWrapper.qml similarity index 65% rename from src/ui/qml/MessageDialogWrapper.qml rename to src/libtego_ui/ui/qml/MessageDialogWrapper.qml index 54e04f3..0e885f7 100644 --- a/src/ui/qml/MessageDialogWrapper.qml +++ b/src/libtego_ui/ui/qml/MessageDialogWrapper.qml @@ -5,9 +5,9 @@ import "utils.js" as Utils MessageDialog { id: removeContactDialog - title: qsTr("Remove %1").arg(Utils.htmlEscaped(contact.nickname)) + title: contact != null ? qsTr("Remove %1").arg(Utils.htmlEscaped(contact.nickname)) : "" //: %1 nickname - text: qsTr("Do you want to permanently remove %1?").arg(Utils.htmlEscaped(contact.nickname)) + text: contact != null ? qsTr("Do you want to permanently remove %1?").arg(Utils.htmlEscaped(contact.nickname)) : "" informativeText: qsTr("This contact will no longer be able to message you, and will be notified about the removal. They may choose to send a new connection request.") standardButtons: StandardButton.Yes | StandardButton.No onYes: contact.deleteContact() diff --git a/src/ui/qml/NetworkSetupWizard.qml b/src/libtego_ui/ui/qml/NetworkSetupWizard.qml similarity index 100% rename from src/ui/qml/NetworkSetupWizard.qml rename to src/libtego_ui/ui/qml/NetworkSetupWizard.qml diff --git a/src/ui/qml/OfflineStateItem.qml b/src/libtego_ui/ui/qml/OfflineStateItem.qml similarity index 100% rename from src/ui/qml/OfflineStateItem.qml rename to src/libtego_ui/ui/qml/OfflineStateItem.qml diff --git a/src/ui/qml/OpenBrowserDialog.qml b/src/libtego_ui/ui/qml/OpenBrowserDialog.qml similarity index 100% rename from src/ui/qml/OpenBrowserDialog.qml rename to src/libtego_ui/ui/qml/OpenBrowserDialog.qml diff --git a/src/ui/qml/PageView.qml b/src/libtego_ui/ui/qml/PageView.qml similarity index 100% rename from src/ui/qml/PageView.qml rename to src/libtego_ui/ui/qml/PageView.qml diff --git a/src/ui/qml/PreferencesDialog.qml b/src/libtego_ui/ui/qml/PreferencesDialog.qml similarity index 100% rename from src/ui/qml/PreferencesDialog.qml rename to src/libtego_ui/ui/qml/PreferencesDialog.qml diff --git a/src/ui/qml/PresenceIcon.qml b/src/libtego_ui/ui/qml/PresenceIcon.qml similarity index 100% rename from src/ui/qml/PresenceIcon.qml rename to src/libtego_ui/ui/qml/PresenceIcon.qml diff --git a/src/ui/qml/StartupStatusPage.qml b/src/libtego_ui/ui/qml/StartupStatusPage.qml similarity index 100% rename from src/ui/qml/StartupStatusPage.qml rename to src/libtego_ui/ui/qml/StartupStatusPage.qml diff --git a/src/ui/qml/TorBootstrapStatus.qml b/src/libtego_ui/ui/qml/TorBootstrapStatus.qml similarity index 100% rename from src/ui/qml/TorBootstrapStatus.qml rename to src/libtego_ui/ui/qml/TorBootstrapStatus.qml diff --git a/src/ui/qml/TorConfigurationPage.qml b/src/libtego_ui/ui/qml/TorConfigurationPage.qml similarity index 100% rename from src/ui/qml/TorConfigurationPage.qml rename to src/libtego_ui/ui/qml/TorConfigurationPage.qml diff --git a/src/ui/qml/TorLogDisplay.qml b/src/libtego_ui/ui/qml/TorLogDisplay.qml similarity index 89% rename from src/ui/qml/TorLogDisplay.qml rename to src/libtego_ui/ui/qml/TorLogDisplay.qml index a1b96d0..1f72847 100644 --- a/src/ui/qml/TorLogDisplay.qml +++ b/src/libtego_ui/ui/qml/TorLogDisplay.qml @@ -11,7 +11,7 @@ TextArea { Connections { target: torInstance.process - onLogMessage: { + function onLogMessage(message) { logDisplay.append(message) } } diff --git a/src/ui/qml/TorPreferences.qml b/src/libtego_ui/ui/qml/TorPreferences.qml similarity index 100% rename from src/ui/qml/TorPreferences.qml rename to src/libtego_ui/ui/qml/TorPreferences.qml diff --git a/src/ui/qml/TorStateWidget.qml b/src/libtego_ui/ui/qml/TorStateWidget.qml similarity index 100% rename from src/ui/qml/TorStateWidget.qml rename to src/libtego_ui/ui/qml/TorStateWidget.qml diff --git a/src/ui/qml/UnreadCountBadge.qml b/src/libtego_ui/ui/qml/UnreadCountBadge.qml similarity index 100% rename from src/ui/qml/UnreadCountBadge.qml rename to src/libtego_ui/ui/qml/UnreadCountBadge.qml diff --git a/src/ui/qml/dummy.qml b/src/libtego_ui/ui/qml/dummy.qml similarity index 100% rename from src/ui/qml/dummy.qml rename to src/libtego_ui/ui/qml/dummy.qml diff --git a/src/ui/qml/main.qml b/src/libtego_ui/ui/qml/main.qml similarity index 98% rename from src/ui/qml/main.qml rename to src/libtego_ui/ui/qml/main.qml index 7168330..17c42bb 100644 --- a/src/ui/qml/main.qml +++ b/src/libtego_ui/ui/qml/main.qml @@ -78,7 +78,7 @@ QtObject { property list data: [ Connections { target: userIdentity.contacts.incomingRequests - onRequestAdded: { + function onRequestAdded(request) { var object = createDialog("ContactRequestDialog.qml", { 'request': request }) object.visible = true } @@ -86,7 +86,7 @@ QtObject { Connections { target: torInstance - onConfigurationNeededChanged: { + function onConfigurationNeededChanged() { if (torInstance.configurationNeeded) { var object = createDialog("NetworkSetupWizard.qml", { 'modality': Qt.ApplicationModal }, mainWindow) object.networkReady.connect(function() { object.visible = false }) diff --git a/src/ui/qml/qml.qrc b/src/libtego_ui/ui/qml/qml.qrc similarity index 100% rename from src/ui/qml/qml.qrc rename to src/libtego_ui/ui/qml/qml.qrc diff --git a/src/ui/qml/utils.js b/src/libtego_ui/ui/qml/utils.js similarity index 100% rename from src/ui/qml/utils.js rename to src/libtego_ui/ui/qml/utils.js diff --git a/src/libtego_ui/utils/CryptoKey.cpp b/src/libtego_ui/utils/CryptoKey.cpp new file mode 100644 index 0000000..c5dde55 --- /dev/null +++ b/src/libtego_ui/utils/CryptoKey.cpp @@ -0,0 +1,194 @@ +/* Ricochet - https://ricochet.im/ + * Copyright (C) 2014, John Brooks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the names of the copyright owners 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 + * OWNER 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 "CryptoKey.h" +#include "SecureRNG.h" +#include "Useful.h" +#include "utils/StringUtil.h" + +bool CryptoKey::loadFromServiceId(const QByteArray& data) +{ + this->clear(); + // convert string to service id + std::unique_ptr serviceId; + tego_v3_onion_service_id_from_string( + tego::out(serviceId), + data.data(), + data.size(), + tego::throw_on_error()); + + // extract public key from service id + std::unique_ptr publicKey; + tego_ed25519_public_key_from_v3_onion_service_id( + tego::out(publicKey), + serviceId.get(), + tego::throw_on_error()); + this->publicKey_ = std::move(publicKey); + + return true; +} + +bool CryptoKey::loadFromKeyBlob(const QByteArray& keyBlob) +{ + this->clear(); + + // convert keyblob to private key + std::unique_ptr privateKey; + tego_ed25519_private_key_from_ed25519_keyblob( + tego::out(privateKey), + keyBlob.data(), + keyBlob.size(), + tego::throw_on_error()); + this->privateKey_ = std::move(privateKey); + + // claculate public key from private + std::unique_ptr publicKey; + tego_ed25519_public_key_from_ed25519_private_key( + tego::out(publicKey), + this->privateKey_.get(), + tego::throw_on_error()); + this->publicKey_ = std::move(publicKey); + + return true; +} + +void CryptoKey::clear() +{ + privateKey_ = {}; + publicKey_ = {}; +} + +bool CryptoKey::isPrivate() const +{ + return privateKey_.get() != nullptr; +} + +QByteArray CryptoKey::encodedKeyBlob() const +{ + // encode private key to KeyBlob + char keyBlob[TEGO_ED25519_KEYBLOB_SIZE] = {0}; + tego_ed25519_keyblob_from_ed25519_private_key(keyBlob, sizeof(keyBlob), this->privateKey_.get(), tego::throw_on_error()); + + QByteArray retval = {keyBlob, TEGO_ED25519_KEYBLOB_LENGTH}; + return retval; +} + +QString CryptoKey::torServiceID() const +{ + // convert public key to service id + std::unique_ptr serviceId; + tego_v3_onion_service_id_from_ed25519_public_key( + tego::out(serviceId), + this->publicKey_.get(), + tego::throw_on_error()); + + // service id to string + char serviceIdString[TEGO_V3_ONION_SERVICE_ID_SIZE] = {0}; + tego_v3_onion_service_id_to_string( + serviceId.get(), + serviceIdString, + sizeof(serviceIdString), + tego::throw_on_error()); + + QString retval = {serviceIdString}; + return retval; +} + +QByteArray CryptoKey::signData(const QByteArray &msg) const +{ + // calculate signature + std::unique_ptr signature; + tego_message_ed25519_sign( + reinterpret_cast(msg.data()), + msg.size(), + this->privateKey_.get(), + this->publicKey_.get(), + tego::out(signature), + tego::throw_on_error()); + + // signature to byte blob + QByteArray retval(TEGO_ED25519_SIGNATURE_SIZE, 0x00); + tego_ed25519_signature_to_bytes( + signature.get(), + reinterpret_cast(retval.data()), + retval.size(), + tego::throw_on_error()); + + return retval; +} + +bool CryptoKey::verifyData(const QByteArray &msg, QByteArray signatureBytes) const +{ + // load signature from buffer + std::unique_ptr signature; + tego_ed25519_signature_from_bytes( + tego::out(signature), + reinterpret_cast(signatureBytes.data()), + signatureBytes.size(), + tego::throw_on_error()); + + // verify it against msg and our public key + return tego_ed25519_signature_verify( + signature.get(), + reinterpret_cast(msg.data()), + msg.size(), + this->publicKey_.get(), + tego::throw_on_error()); +} + +/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */ +QByteArray torControlHashedPassword(const QByteArray &password) +{ + QByteArray salt = SecureRNG::random(8); + if (salt.isNull()) + return QByteArray(); + + int count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6); + + SHA_CTX hash; + SHA1_Init(&hash); + + QByteArray tmp = salt + password; + while (count) + { + int c = qMin(count, tmp.size()); + SHA1_Update(&hash, reinterpret_cast(tmp.constData()), c); + count -= c; + } + + unsigned char md[20]; + SHA1_Final(md, &hash); + + /* 60 is the hex-encoded value of 96, which is a constant used by Tor's algorithm. */ + return QByteArray("16:") + salt.toHex().toUpper() + QByteArray("60") + + QByteArray::fromRawData(reinterpret_cast(md), 20).toHex().toUpper(); +} diff --git a/src/utils/CryptoKey.h b/src/libtego_ui/utils/CryptoKey.h similarity index 61% rename from src/utils/CryptoKey.h rename to src/libtego_ui/utils/CryptoKey.h index 70ada19..61e185c 100644 --- a/src/utils/CryptoKey.h +++ b/src/libtego_ui/utils/CryptoKey.h @@ -33,61 +33,32 @@ #ifndef CRYPTOKEY_H #define CRYPTOKEY_H -#include -#include -#include - class CryptoKey { public: - enum KeyType { - PrivateKey, - PublicKey - }; - - enum KeyFormat { - PEM, - DER - }; - - CryptoKey(); - CryptoKey(const CryptoKey &other) : d(other.d) { } - ~CryptoKey(); + // loads public key from service id + bool loadFromServiceId(const QByteArray &data); + // load private key from ed25519 KeyBlob format + bool loadFromKeyBlob(const QByteArray& keyBlob); + // load from Service Id - bool loadFromData(const QByteArray &data, KeyType type, KeyFormat format = PEM); - bool loadFromFile(const QString &path, KeyType type, KeyFormat format = PEM); void clear(); - bool isLoaded() const { return d.data() && d->key != 0; } + bool isLoaded() const { return privateKey_ != nullptr || publicKey_ != nullptr; } bool isPrivate() const; - QByteArray publicKeyDigest() const; - QByteArray encodedPublicKey(KeyFormat format) const; - QByteArray encodedPrivateKey(KeyFormat format) const; + // write to tor's 'KeyBlob' format + QByteArray encodedKeyBlob() const; QString torServiceID() const; - int bits() const; - // Calculate and sign SHA-256 digest of data using this key and PKCS #1 v2.0 padding + // sign data with our private key QByteArray signData(const QByteArray &data) const; - // Verify a signature as per signData + // verify data signature against public key bool verifyData(const QByteArray &data, QByteArray signature) const; - // Sign the input SHA-256 digest using this key and PKCS #1 v2.0 padding - QByteArray signSHA256(const QByteArray &digest) const; - // Verify a signature as per signSHA256 - bool verifySHA256(const QByteArray &digest, QByteArray signature) const; - private: - struct Data : public QSharedData - { - typedef struct rsa_st RSA; - RSA *key; - - Data(RSA *k = 0) : key(k) { } - ~Data(); - }; - - QExplicitlySharedDataPointer d; + std::shared_ptr privateKey_; + std::shared_ptr publicKey_; }; QByteArray torControlHashedPassword(const QByteArray &password); diff --git a/src/utils/PendingOperation.cpp b/src/libtego_ui/utils/PendingOperation.cpp similarity index 100% rename from src/utils/PendingOperation.cpp rename to src/libtego_ui/utils/PendingOperation.cpp diff --git a/src/utils/PendingOperation.h b/src/libtego_ui/utils/PendingOperation.h similarity index 99% rename from src/utils/PendingOperation.h rename to src/libtego_ui/utils/PendingOperation.h index 8f776a8..064b3dc 100644 --- a/src/utils/PendingOperation.h +++ b/src/libtego_ui/utils/PendingOperation.h @@ -33,8 +33,6 @@ #ifndef PENDINGOPERATION_H #define PENDINGOPERATION_H -#include - /* Represents an asynchronous operation for reporting status * * This class is used for asynchronous operations that report a diff --git a/src/utils/SecureRNG.cpp b/src/libtego_ui/utils/SecureRNG.cpp similarity index 95% rename from src/utils/SecureRNG.cpp rename to src/libtego_ui/utils/SecureRNG.cpp index 3a6eacd..2e0dafe 100644 --- a/src/utils/SecureRNG.cpp +++ b/src/libtego_ui/utils/SecureRNG.cpp @@ -31,18 +31,6 @@ */ #include "SecureRNG.h" -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include -#endif - -#if QT_VERSION >= 0x040700 -#include -#endif bool SecureRNG::seed() { diff --git a/src/utils/SecureRNG.h b/src/libtego_ui/utils/SecureRNG.h similarity index 98% rename from src/utils/SecureRNG.h rename to src/libtego_ui/utils/SecureRNG.h index f3b2a4b..e504391 100644 --- a/src/utils/SecureRNG.h +++ b/src/libtego_ui/utils/SecureRNG.h @@ -33,8 +33,6 @@ #ifndef SECURERNG_H #define SECURERNG_H -#include - class SecureRNG { public: diff --git a/src/utils/Settings.cpp b/src/libtego_ui/utils/Settings.cpp similarity index 98% rename from src/utils/Settings.cpp rename to src/libtego_ui/utils/Settings.cpp index b20d330..5558b7c 100644 --- a/src/utils/Settings.cpp +++ b/src/libtego_ui/utils/Settings.cpp @@ -31,16 +31,6 @@ */ #include "Settings.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include class SettingsFilePrivate : public QObject { diff --git a/src/utils/Settings.h b/src/libtego_ui/utils/Settings.h similarity index 98% rename from src/utils/Settings.h rename to src/libtego_ui/utils/Settings.h index 79ad032..2f2dd86 100644 --- a/src/utils/Settings.h +++ b/src/libtego_ui/utils/Settings.h @@ -33,13 +33,6 @@ #ifndef SETTINGS_H #define SETTINGS_H -#include -#include -#include -#include -#include -#include - class SettingsObject; class SettingsFilePrivate; class SettingsObjectPrivate; diff --git a/src/utils/StringUtil.cpp b/src/libtego_ui/utils/StringUtil.cpp similarity index 100% rename from src/utils/StringUtil.cpp rename to src/libtego_ui/utils/StringUtil.cpp diff --git a/src/utils/StringUtil.h b/src/libtego_ui/utils/StringUtil.h similarity index 94% rename from src/utils/StringUtil.h rename to src/libtego_ui/utils/StringUtil.h index c86d2c6..ebff5e8 100644 --- a/src/utils/StringUtil.h +++ b/src/libtego_ui/utils/StringUtil.h @@ -33,9 +33,6 @@ #ifndef STRINGUTIL_H #define STRINGUTIL_H -#include -#include - QByteArray quotedString(const QByteArray &string); /* Return the unquoted contents of a string, either until an end quote or an unescaped separator character. */ @@ -43,4 +40,11 @@ QByteArray unquotedString(const QByteArray &string); QList splitQuotedStrings(const QByteArray &input, char separator); +template +constexpr size_t static_strlen(const char (&str)[N]) +{ + Q_ASSERT(str[N-1] == 0); + return N - 1; +} + #endif // STRINGUTIL_H diff --git a/src/utils/Useful.h b/src/libtego_ui/utils/Useful.h similarity index 98% rename from src/utils/Useful.h rename to src/libtego_ui/utils/Useful.h index 6bb6e44..1040235 100644 --- a/src/utils/Useful.h +++ b/src/libtego_ui/utils/Useful.h @@ -33,9 +33,6 @@ #ifndef UTILS_USEFUL_H #define UTILS_USEFUL_H -#include -#include - /* Print a warning for bug conditions, and assert on a debug build. * * This should be used in place of Q_ASSERT for bug conditions, along diff --git a/src/qmake_includes/artifacts.pri b/src/qmake_includes/artifacts.pri new file mode 100644 index 0000000..0d96448 --- /dev/null +++ b/src/qmake_includes/artifacts.pri @@ -0,0 +1,16 @@ +# specify the DESTDIR for final binary and intermediate build files + +CONFIG += debug_and_release + +CONFIG(release, release|debug) { + DESTDIR = $${PWD}/../../build/release/$${TARGET} +} +CONFIG(debug, release|debug) { + DESTDIR = $${PWD}/../../build/debug/$${TARGET} +} + +# artifacts go under hidden dirs in DESTDIR +OBJECTS_DIR = $${DESTDIR}/.obj +MOC_DIR = $${DESTDIR}/.moc +RCC_DIR = $${DESTDIR}/.rcc +UI_DIR = $${DESTDIR}/.ui diff --git a/src/qmake_includes/compiler_flags.pri b/src/qmake_includes/compiler_flags.pri new file mode 100644 index 0000000..7365bb4 --- /dev/null +++ b/src/qmake_includes/compiler_flags.pri @@ -0,0 +1,5 @@ +# get us onto the latest c++ +QMAKE_CXXFLAGS += --std=c++2a +# enable link time optimization +QMAKE_CFLAGS += -flto +QMAKE_CXXFLAGS += -flto \ No newline at end of file diff --git a/src/qmake_includes/hardened.pri b/src/qmake_includes/hardened.pri new file mode 100644 index 0000000..4332207 --- /dev/null +++ b/src/qmake_includes/hardened.pri @@ -0,0 +1,47 @@ +load(configure) +# Define common variables; these are used by config tests _and_ the actual build + +# Supported in gcc 4.8+ +HARDENED_SANITIZE_FLAGS = -fsanitize=address +# Supported in gcc 4.9+ +HARDENED_SANITIZE_UBSAN_FLAGS = -fsanitize=undefined -fsanitize=integer-divide-by-zero -fsanitize=bounds -fsanitize=alignment -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize-recover +# Supported in gcc 5.0+ +HARDENED_SANITIZE_UBSAN_MORE_FLAGS = -fsanitize=vptr -fsanitize=object-size +# vtable-verify requires some OS support; see https://bugzilla.novell.com/show_bug.cgi?id=877239 +HARDENED_VTABLE_VERIFY_FLAGS = -fvtable-verify=std + +HARDENED_STACK_PROTECTOR_STRONG_FLAGS = -fstack-protector-strong +HARDENED_STACK_PROTECTOR_FLAGS = -fstack-protector --param=ssp-buffer-size=4 + +HARDENED_MINGW_64ASLR_FLAGS = -Wl,--dynamicbase -Wl,--high-entropy-va + + +# Run tests and apply options where possible +# CONFIG(hardened) { +# # mingw is always PIC, and complains about the flag +# !mingw:HARDEN_FLAGS = -fPIC + +# CONFIG(debug,debug|release): qtCompileTest(sanitize):HARDEN_FLAGS += $$HARDENED_SANITIZE_FLAGS +# qtCompileTest(sanitize-ubsan):HARDEN_FLAGS += $$HARDENED_SANITIZE_UBSAN_FLAGS +# qtCompileTest(sanitize-ubsan-more):HARDEN_FLAGS += $$HARDENED_SANITIZE_UBSAN_MORE_FLAGS +# qtCompileTest(vtable-verify):HARDEN_FLAGS += $$HARDENED_VTABLE_VERIFY_FLAGS + +# qtCompileTest(stack-protector-strong) { +# HARDEN_FLAGS += $$HARDENED_STACK_PROTECTOR_STRONG_FLAGS +# } else { +# qtCompileTest(stack-protector):HARDEN_FLAGS += $$HARDENED_STACK_PROTECTOR_FLAGS +# } + +# mingw { +# qtCompileTest(mingw-64aslr):QMAKE_LFLAGS *= $$HARDENED_MINGW_64ASLR_FLAGS +# QMAKE_LFLAGS *= -Wl,--nxcompat -Wl,--dynamicbase +# } + +# QMAKE_CXXFLAGS *= $$HARDEN_FLAGS +# QMAKE_LFLAGS *= $$HARDEN_FLAGS + +# # _FORTIFY_SOURCE requires -O, so only use on release builds +# CONFIG(release,debug|release):QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2 +# # Linux specific +# unix:!macx:QMAKE_LFLAGS *= -pie -Wl,-z,relro,-z,now +# } diff --git a/src/qmake_includes/linker_flags.pri b/src/qmake_includes/linker_flags.pri new file mode 100644 index 0000000..7ebf4d1 --- /dev/null +++ b/src/qmake_includes/linker_flags.pri @@ -0,0 +1,13 @@ +win32-g++ { + QMAKE_LFLAGS += -static + QMAKE_LFLAGS += -static-libgcc + QMAKE_LFLAGS += -static-libstdc++ + # work around issue with link time optimization bug in mingw + # https://sourceware.org/bugzilla/show_bug.cgi?id=12762 + QMAKE_LFLAGS += -Wl,-allow-multiple-definition +} + +CONFIG(debug,debug|release) { + QMAKE_LFLAGS += -Wl,-O1 +} +QMAKE_LFLAGS += -flto diff --git a/src/qmake_includes/openssl.pri b/src/qmake_includes/openssl.pri new file mode 100644 index 0000000..6200a0c --- /dev/null +++ b/src/qmake_includes/openssl.pri @@ -0,0 +1,21 @@ +unix { + !isEmpty(OPENSSLDIR) { + LIBS += -L$${OPENSSLDIR}/lib -lcrypto + INCLUDEPATH += $${OPENSSLDIR}/include + } else { + CONFIG += link_pkgconfig + PKGCONFIG += libcrypto + } +} +win32 { + win32-g++ { + LIBS += -L$${OPENSSLDIR}/lib -lcrypto + LIBS += -lcrypt32 + INCLUDEPATH += $${OPENSSLDIR}/include + } else { + LIBS += -L$${OPENSSLDIR}/lib -llibeay32 + } + + # required by openssl + LIBS += -luser32 -lgdi32 -ladvapi32 +} \ No newline at end of file diff --git a/src/qmake_includes/protobuf.pri b/src/qmake_includes/protobuf.pri new file mode 100644 index 0000000..9a72aa8 --- /dev/null +++ b/src/qmake_includes/protobuf.pri @@ -0,0 +1,76 @@ +# Qt qmake integration with Google Protocol Buffers compiler protoc +# +# To compile protocol buffers with qt qmake, specify PROTOS variable and +# include this file +# +# Based on: +# https://vilimpoc.org/blog/2013/06/09/using-google-protocol-buffers-with-qmake/ + +PROTOC = protoc + +# unix { +# PKG_CONFIG = $$pkgConfigExecutable() + +# # All our dependency resolution depends on pkg-config. If it isn't +# # available, the errors we will get subsequently are a lot more cryptic than +# # this. +# !system($$PKG_CONFIG --version 2>&1 > /dev/null) { +# error("pkg-config executable is not available. please install it so I can find dependencies.") +# } + +# !contains(QT_CONFIG, no-pkg-config) { +# CONFIG += link_pkgconfig +# PKGCONFIG += protobuf +# } else { +# # Some SDK builds (e.g. OS X 5.4.1) are no-pkg-config, so try to hack the linker flags in. +# QMAKE_LFLAGS += $$system($$PKG_CONFIG --libs protobuf) +# } + +# gcc|clang { +# # Add -isystem for protobuf includes to suppress some loud compiler warnings in their headers +# PROTOBUF_CFLAGS = $$system($$PKG_CONFIG --cflags protobuf) +# PROTOBUF_CFLAGS ~= s/^(?!-I).*//g +# PROTOBUF_CFLAGS ~= s/^-I(.*)/-isystem \\1/g +# QMAKE_CXXFLAGS += $$PROTOBUF_CFLAGS +# } +# } + +# win32 { +# isEmpty(PROTOBUFDIR):error(You must pass PROTOBUFDIR=path/to/protobuf to qmake on this platform) +# INCLUDEPATH += $${PROTOBUFDIR}/include +# LIBS += -L$${PROTOBUFDIR}/lib -lprotobuf +# contains(QMAKE_HOST.os,Windows):PROTOC = $${PROTOBUFDIR}/bin/protoc.exe +# } + +isEmpty(PROTOBUFDIR) { + error(You must pass PROTOBUFDIR=path/to/protobuf to qmake on this platform) + win32 { + + } + unix:!macx { + + } + macx { + + } +} +else { + INCLUDEPATH += $${PROTOBUFDIR}/include + LIBS += -L$${PROTOBUFDIR}/lib -lprotobuf + contains(QMAKE_HOST.os,Windows):PROTOC = $${PROTOBUFDIR}/bin/protoc.exe +} + +protobuf_decl.name = protobuf headers +protobuf_decl.input = PROTOS +protobuf_decl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h +protobuf_decl.commands = $$PROTOC --cpp_out=${QMAKE_FILE_IN_PATH} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME} +protobuf_decl.variable_out = HEADERS +QMAKE_EXTRA_COMPILERS += protobuf_decl + +protobuf_impl.name = protobuf sources +protobuf_impl.input = PROTOS +protobuf_impl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.cc +protobuf_impl.depends = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h +protobuf_impl.commands = $$escape_expand(\n) +protobuf_impl.variable_out = SOURCES +QMAKE_EXTRA_COMPILERS += protobuf_impl diff --git a/src/tego.pro b/src/tego.pro new file mode 100644 index 0000000..28e3784 --- /dev/null +++ b/src/tego.pro @@ -0,0 +1,14 @@ +include($${PWD}/qmake_includes/artifacts.pri) + +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = \ + libtego \ + libtego_ui \ + tego_ui \ + +# macx can't build tests for somereason, stub out for now +!macx { + SUBDIRS += tests \ +} + diff --git a/src/Info.plist b/src/tego_ui/Info.plist similarity index 94% rename from src/Info.plist rename to src/tego_ui/Info.plist index 1e90fbd..802c9ad 100644 --- a/src/Info.plist +++ b/src/tego_ui/Info.plist @@ -13,7 +13,7 @@ CFBundleExecutable ricochet-refresh CFBundleIdentifier - im.ricochet + net.ricochetrefresh CFBundleName Ricochet-Refresh NSSupportsAutomaticGraphicsSwitching diff --git a/icons/LICENSE b/src/tego_ui/icons/LICENSE similarity index 100% rename from icons/LICENSE rename to src/tego_ui/icons/LICENSE diff --git a/icons/icons.qrc b/src/tego_ui/icons/icons.qrc similarity index 100% rename from icons/icons.qrc rename to src/tego_ui/icons/icons.qrc diff --git a/icons/ricochet_icons.json b/src/tego_ui/icons/ricochet_icons.json similarity index 100% rename from icons/ricochet_icons.json rename to src/tego_ui/icons/ricochet_icons.json diff --git a/icons/ricochet_icons.ttf b/src/tego_ui/icons/ricochet_icons.ttf similarity index 100% rename from icons/ricochet_icons.ttf rename to src/tego_ui/icons/ricochet_icons.ttf diff --git a/icons/ricochet_refresh.icns b/src/tego_ui/icons/ricochet_refresh.icns similarity index 100% rename from icons/ricochet_refresh.icns rename to src/tego_ui/icons/ricochet_refresh.icns diff --git a/icons/ricochet_refresh.ico b/src/tego_ui/icons/ricochet_refresh.ico similarity index 100% rename from icons/ricochet_refresh.ico rename to src/tego_ui/icons/ricochet_refresh.ico diff --git a/icons/ricochet_refresh.jpg b/src/tego_ui/icons/ricochet_refresh.jpg similarity index 100% rename from icons/ricochet_refresh.jpg rename to src/tego_ui/icons/ricochet_refresh.jpg diff --git a/icons/ricochet_refresh.png b/src/tego_ui/icons/ricochet_refresh.png similarity index 100% rename from icons/ricochet_refresh.png rename to src/tego_ui/icons/ricochet_refresh.png diff --git a/icons/ricochet_refresh.svg b/src/tego_ui/icons/ricochet_refresh.svg similarity index 100% rename from icons/ricochet_refresh.svg rename to src/tego_ui/icons/ricochet_refresh.svg diff --git a/src/main.cpp b/src/tego_ui/main.cpp similarity index 92% rename from src/main.cpp rename to src/tego_ui/main.cpp index 45a1bb5..f43643a 100644 --- a/src/main.cpp +++ b/src/tego_ui/main.cpp @@ -38,26 +38,19 @@ #include "utils/CryptoKey.h" #include "utils/SecureRNG.h" #include "utils/Settings.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include static bool initSettings(SettingsFile *settings, QLockFile **lockFile, QString &errorMessage); static bool importLegacySettings(SettingsFile *settings, const QString &oldPath); static void initTranslation(); -int main(int argc, char *argv[]) +int main(int argc, char *argv[]) try { - /* Disable rwx memory. + tego_initialize(tego::throw_on_error()); + auto tego_cleanup = tego::make_scope_exit([]() -> void { + tego_uninitialize(tego::throw_on_error()); + }); + + /* Disable rwx memory. This will also ensure full PAX/Grsecurity protections. */ qputenv("QV4_FORCE_INTERPRETER", "1"); qputenv("QT_ENABLE_REGEXP_JIT", "0"); @@ -65,8 +58,24 @@ int main(int argc, char *argv[]) if (qEnvironmentVariableIsEmpty("QMLSCENE_DEVICE")) qputenv("QMLSCENE_DEVICE", "softwarecontext"); + /* https://doc.qt.io/qt-5/highdpi.html#high-dpi-support-in-qt */ + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + if (!qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") + && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") + && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") + && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + } + QApplication a(argc, argv); - a.setApplicationVersion(QLatin1String("1.1.4")); +#ifdef TEGO_VERSION +# define XSTR(X) STR(X) +# define STR(X) #X +# define TEGO_VERSION_STR XSTR(TEGO_VERSION) +#else +# define TEGO_VERSION_STR "devbuild" +#endif + a.setApplicationVersion(QLatin1String(TEGO_VERSION_STR)); a.setOrganizationName(QStringLiteral("Ricochet")); #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) @@ -96,7 +105,6 @@ int main(int argc, char *argv[]) /* Seed the OpenSSL RNG */ if (!SecureRNG::seed()) qFatal("Failed to initialize RNG"); - qsrand(SecureRNG::randomInt(UINT_MAX)); /* Tor control manager */ Tor::TorManager *torManager = Tor::TorManager::instance(); @@ -115,6 +123,11 @@ int main(int argc, char *argv[]) return a.exec(); } +catch(std::exception& re) +{ + qDebug() << "Caught Exception: " << re.what(); +} + static QString userConfigPath() { diff --git a/src/tego_ui/precomp.hpp b/src/tego_ui/precomp.hpp new file mode 100644 index 0000000..e54a4e7 --- /dev/null +++ b/src/tego_ui/precomp.hpp @@ -0,0 +1,33 @@ +// C headers + +// openssl +#include + +// C++ headers +#ifdef __cplusplus + +// Qt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// tego +#include + +#endif // __cplusplus + + diff --git a/src/ricochet-refresh.desktop b/src/tego_ui/ricochet-refresh.desktop similarity index 89% rename from src/ricochet-refresh.desktop rename to src/tego_ui/ricochet-refresh.desktop index 55b3890..98e0802 100644 --- a/src/ricochet-refresh.desktop +++ b/src/tego_ui/ricochet-refresh.desktop @@ -5,4 +5,4 @@ Name=Ricochet Refresh Categories=Network;InstantMessaging;Chat;FileTransfer;Qt Comment=Anonymous instant messaging Icon=ricochet_refresh -Exec=ricochet +Exec=ricochet-refresh diff --git a/sounds/LICENSE b/src/tego_ui/sounds/LICENSE similarity index 100% rename from sounds/LICENSE rename to src/tego_ui/sounds/LICENSE diff --git a/sounds/message.wav b/src/tego_ui/sounds/message.wav similarity index 100% rename from sounds/message.wav rename to src/tego_ui/sounds/message.wav diff --git a/sounds/online.wav b/src/tego_ui/sounds/online.wav similarity index 100% rename from sounds/online.wav rename to src/tego_ui/sounds/online.wav diff --git a/sounds/sounds.qrc b/src/tego_ui/sounds/sounds.qrc similarity index 100% rename from sounds/sounds.qrc rename to src/tego_ui/sounds/sounds.qrc diff --git a/ricochet.pro b/src/tego_ui/tego_ui.pro similarity index 57% rename from ricochet.pro rename to src/tego_ui/tego_ui.pro index 381dcef..07e1ebb 100644 --- a/ricochet.pro +++ b/src/tego_ui/tego_ui.pro @@ -29,21 +29,29 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,1) { - error("Qt 5.1 or greater is required. You can build your own, or get the SDK at https://qt-project.org/downloads") +lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,15) { + error("Qt 5.15 or greater is required. You can build your own, or get the SDK at https://qt-project.org/downloads") } +QMAKE_INCLUDES = $${PWD}/../qmake_includes + +include($${QMAKE_INCLUDES}/artifacts.pri) +include($${QMAKE_INCLUDES}/compiler_flags.pri) +include($${QMAKE_INCLUDES}/linker_flags.pri) + TARGET = ricochet-refresh TEMPLATE = app + QT += core gui network quick widgets -CONFIG += c++11 -VERSION = 1.1.4 +VERSION = 3.0.0a + +DEFINES += "TEGO_VERSION=$${VERSION}" # Use CONFIG+=no-hardened to disable compiler hardening options !CONFIG(no-hardened) { CONFIG += hardened - include(hardened.pri) + include($${QMAKE_INCLUDES}/hardened.pri) } # Pass DEFINES+=RICOCHET_NO_PORTABLE for a system-wide installation @@ -54,7 +62,7 @@ contains(DEFINES, RICOCHET_NO_PORTABLE) { unix:!macx { target.path = /usr/bin shortcut.path = /usr/share/applications - shortcut.files = src/ricochet.desktop + shortcut.files = ricochet.desktop icon.path = /usr/share/icons/hicolor/48x48/apps/ icon.files = icons/ricochet_refresh.png scalable_icon.path = /usr/share/icons/hicolor/scalable/apps/ @@ -90,12 +98,12 @@ macx { # Qt 5.4 introduces a bug that breaks QMAKE_INFO_PLIST when qmake has a relative path. # Work around by copying Info.plist directly. greaterThan(QT_MAJOR_VERSION,5)|greaterThan(QT_MINOR_VERSION,4) { - QMAKE_INFO_PLIST = src/Info.plist + QMAKE_INFO_PLIST = Info.plist } else:equals(QT_MAJOR_VERSION,5):lessThan(QT_MINOR_VERSION,4) { - QMAKE_INFO_PLIST = src/Info.plist + QMAKE_INFO_PLIST = Info.plist } else { CONFIG += no_plist - QMAKE_POST_LINK += cp $${_PRO_FILE_PWD_}/src/Info.plist $${OUT_PWD}/$${TARGET}.app/Contents/; + QMAKE_POST_LINK += cp $${_PRO_FILE_PWD_}/Info.plist $${OUT_PWD}/$${TARGET}.app/Contents/; } exists(tor) { @@ -108,47 +116,12 @@ macx { QMAKE_BUNDLE_DATA += icons } -CONFIG += debug_and_release - # Create a pdb for release builds as well, to enable debugging win32-msvc2008|win32-msvc2010 { QMAKE_CXXFLAGS_RELEASE += /Zi QMAKE_LFLAGS_RELEASE += /DEBUG /OPT:REF,ICF } -INCLUDEPATH += src - -win32|mac { - # For mac, this is necessary because homebrew does not link openssl .pc to - # /usr/local/lib/pkgconfig (presumably because it used to be a system - # package). - # - # Unfortunately, it is no longer really a system package, and we really - # need to know where it is. - isEmpty(OPENSSLDIR): error(You must pass OPENSSLDIR=path/to/openssl to qmake on this platform) -} - -unix { - !isEmpty(OPENSSLDIR) { - INCLUDEPATH += $${OPENSSLDIR}/include - LIBS += -L$${OPENSSLDIR}/lib -lcrypto - } else { - CONFIG += link_pkgconfig - PKGCONFIG += libcrypto - } -} -win32 { - INCLUDEPATH += $${OPENSSLDIR}/include - - win32-g++ { - LIBS += -L$${OPENSSLDIR}/lib -lcrypto - } else { - LIBS += -L$${OPENSSLDIR}/lib -llibeay32 - } - - # required by openssl - LIBS += -luser32 -lgdi32 -ladvapi32 -} # Exclude unneeded plugins from static builds QTPLUGIN.playlistformats = - @@ -158,103 +131,18 @@ QTPLUGIN.mediaservice = - # Include Linux input plugins, which are missing by default, to provide complex input support. See issue #60. unix:!macx:QTPLUGIN.platforminputcontexts = composeplatforminputcontextplugin ibusplatforminputcontextplugin -DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII - -SOURCES += src/main.cpp \ - src/ui/MainWindow.cpp \ - src/ui/ContactsModel.cpp \ - src/tor/TorControl.cpp \ - src/tor/TorControlSocket.cpp \ - src/tor/TorControlCommand.cpp \ - src/tor/ProtocolInfoCommand.cpp \ - src/tor/AuthenticateCommand.cpp \ - src/tor/SetConfCommand.cpp \ - src/tor/AddOnionCommand.cpp \ - src/utils/StringUtil.cpp \ - src/core/ContactsManager.cpp \ - src/core/ContactUser.cpp \ - src/tor/GetConfCommand.cpp \ - src/tor/HiddenService.cpp \ - src/utils/CryptoKey.cpp \ - src/utils/SecureRNG.cpp \ - src/core/OutgoingContactRequest.cpp \ - src/core/IncomingRequestManager.cpp \ - src/core/ContactIDValidator.cpp \ - src/core/UserIdentity.cpp \ - src/core/IdentityManager.cpp \ - src/core/ConversationModel.cpp \ - src/tor/TorProcess.cpp \ - src/tor/TorManager.cpp \ - src/tor/TorSocket.cpp \ - src/ui/LinkedText.cpp \ - src/utils/Settings.cpp \ - src/utils/PendingOperation.cpp \ - src/ui/LanguagesModel.cpp - -HEADERS += src/ui/MainWindow.h \ - src/ui/ContactsModel.h \ - src/tor/TorControl.h \ - src/tor/TorControlSocket.h \ - src/tor/TorControlCommand.h \ - src/tor/ProtocolInfoCommand.h \ - src/tor/AuthenticateCommand.h \ - src/tor/SetConfCommand.h \ - src/tor/AddOnionCommand.h \ - src/utils/StringUtil.h \ - src/core/ContactsManager.h \ - src/core/ContactUser.h \ - src/tor/GetConfCommand.h \ - src/tor/HiddenService.h \ - src/utils/CryptoKey.h \ - src/utils/SecureRNG.h \ - src/core/OutgoingContactRequest.h \ - src/core/IncomingRequestManager.h \ - src/core/ContactIDValidator.h \ - src/core/UserIdentity.h \ - src/core/IdentityManager.h \ - src/core/ConversationModel.h \ - src/tor/TorProcess.h \ - src/tor/TorProcess_p.h \ - src/tor/TorManager.h \ - src/tor/TorSocket.h \ - src/ui/LinkedText.h \ - src/utils/Settings.h \ - src/utils/PendingOperation.h \ - src/ui/LanguagesModel.h - -SOURCES += src/protocol/Channel.cpp \ - src/protocol/ControlChannel.cpp \ - src/protocol/Connection.cpp \ - src/protocol/OutboundConnector.cpp \ - src/protocol/AuthHiddenServiceChannel.cpp \ - src/protocol/ChatChannel.cpp \ - src/protocol/ContactRequestChannel.cpp - -HEADERS += src/protocol/Channel.h \ - src/protocol/Channel_p.h \ - src/protocol/ControlChannel.h \ - src/protocol/Connection.h \ - src/protocol/Connection_p.h \ - src/protocol/OutboundConnector.h \ - src/protocol/AuthHiddenServiceChannel.h \ - src/protocol/ChatChannel.h \ - src/protocol/ContactRequestChannel.h - -include(protobuf.pri) -PROTOS += src/protocol/ControlChannel.proto \ - src/protocol/AuthHiddenService.proto \ - src/protocol/ChatChannel.proto \ - src/protocol/ContactRequestChannel.proto +DEFINES += QT_NO_CAST_TO_ASCII # QML -RESOURCES += src/ui/qml/qml.qrc \ +RESOURCES +=\ + $${PWD}/../libtego_ui/ui/qml/qml.qrc \ icons/icons.qrc \ sounds/sounds.qrc win32:RC_ICONS = icons/ricochet_refresh.ico -OTHER_FILES += src/ui/qml/* +OTHER_FILES += $${PWD}/../libtego_ui/ui/qml/* lupdate_only { - SOURCES += src/ui/qml/*.qml + SOURCES += $${PWD}/../libtego_ui/ui/qml/*.qml } # Translations @@ -297,3 +185,11 @@ TRANSLATIONS += \ } RESOURCES += translation/embedded.qrc + +CONFIG += precompile_header +PRECOMPILED_HEADER = precomp.hpp + +SOURCES += main.cpp + +include($${PWD}/../libtego_ui/libtego_ui.pri) +include($${PWD}/../libtego/libtego.pri) diff --git a/translation/embedded.qrc b/src/tego_ui/translation/embedded.qrc similarity index 100% rename from translation/embedded.qrc rename to src/tego_ui/translation/embedded.qrc diff --git a/translation/inno/Albanian.isl b/src/tego_ui/translation/inno/Albanian.isl similarity index 100% rename from translation/inno/Albanian.isl rename to src/tego_ui/translation/inno/Albanian.isl diff --git a/translation/inno/Bulgarian.isl b/src/tego_ui/translation/inno/Bulgarian.isl similarity index 100% rename from translation/inno/Bulgarian.isl rename to src/tego_ui/translation/inno/Bulgarian.isl diff --git a/translation/inno/ChineseSimplified.isl b/src/tego_ui/translation/inno/ChineseSimplified.isl similarity index 100% rename from translation/inno/ChineseSimplified.isl rename to src/tego_ui/translation/inno/ChineseSimplified.isl diff --git a/translation/inno/Estonian.isl b/src/tego_ui/translation/inno/Estonian.isl similarity index 100% rename from translation/inno/Estonian.isl rename to src/tego_ui/translation/inno/Estonian.isl diff --git a/translation/inno/Swedish.isl b/src/tego_ui/translation/inno/Swedish.isl similarity index 100% rename from translation/inno/Swedish.isl rename to src/tego_ui/translation/inno/Swedish.isl diff --git a/translation/installer_bg.isl b/src/tego_ui/translation/installer_bg.isl similarity index 100% rename from translation/installer_bg.isl rename to src/tego_ui/translation/installer_bg.isl diff --git a/translation/installer_cs.isl b/src/tego_ui/translation/installer_cs.isl similarity index 100% rename from translation/installer_cs.isl rename to src/tego_ui/translation/installer_cs.isl diff --git a/translation/installer_da.isl b/src/tego_ui/translation/installer_da.isl similarity index 100% rename from translation/installer_da.isl rename to src/tego_ui/translation/installer_da.isl diff --git a/translation/installer_de.isl b/src/tego_ui/translation/installer_de.isl similarity index 100% rename from translation/installer_de.isl rename to src/tego_ui/translation/installer_de.isl diff --git a/translation/installer_en.isl b/src/tego_ui/translation/installer_en.isl similarity index 100% rename from translation/installer_en.isl rename to src/tego_ui/translation/installer_en.isl diff --git a/translation/installer_es.isl b/src/tego_ui/translation/installer_es.isl similarity index 100% rename from translation/installer_es.isl rename to src/tego_ui/translation/installer_es.isl diff --git a/translation/installer_et_EE.isl b/src/tego_ui/translation/installer_et_EE.isl similarity index 100% rename from translation/installer_et_EE.isl rename to src/tego_ui/translation/installer_et_EE.isl diff --git a/translation/installer_fi.isl b/src/tego_ui/translation/installer_fi.isl similarity index 100% rename from translation/installer_fi.isl rename to src/tego_ui/translation/installer_fi.isl diff --git a/translation/installer_fr.isl b/src/tego_ui/translation/installer_fr.isl similarity index 100% rename from translation/installer_fr.isl rename to src/tego_ui/translation/installer_fr.isl diff --git a/translation/installer_it.isl b/src/tego_ui/translation/installer_it.isl similarity index 100% rename from translation/installer_it.isl rename to src/tego_ui/translation/installer_it.isl diff --git a/translation/installer_it_IT.isl b/src/tego_ui/translation/installer_it_IT.isl similarity index 100% rename from translation/installer_it_IT.isl rename to src/tego_ui/translation/installer_it_IT.isl diff --git a/translation/installer_ja.isl b/src/tego_ui/translation/installer_ja.isl similarity index 100% rename from translation/installer_ja.isl rename to src/tego_ui/translation/installer_ja.isl diff --git a/translation/installer_nb.isl b/src/tego_ui/translation/installer_nb.isl similarity index 100% rename from translation/installer_nb.isl rename to src/tego_ui/translation/installer_nb.isl diff --git a/translation/installer_nl_NL.isl b/src/tego_ui/translation/installer_nl_NL.isl similarity index 100% rename from translation/installer_nl_NL.isl rename to src/tego_ui/translation/installer_nl_NL.isl diff --git a/translation/installer_pl.isl b/src/tego_ui/translation/installer_pl.isl similarity index 100% rename from translation/installer_pl.isl rename to src/tego_ui/translation/installer_pl.isl diff --git a/translation/installer_pt_BR.isl b/src/tego_ui/translation/installer_pt_BR.isl similarity index 100% rename from translation/installer_pt_BR.isl rename to src/tego_ui/translation/installer_pt_BR.isl diff --git a/translation/installer_pt_PT.isl b/src/tego_ui/translation/installer_pt_PT.isl similarity index 100% rename from translation/installer_pt_PT.isl rename to src/tego_ui/translation/installer_pt_PT.isl diff --git a/translation/installer_ru.isl b/src/tego_ui/translation/installer_ru.isl similarity index 100% rename from translation/installer_ru.isl rename to src/tego_ui/translation/installer_ru.isl diff --git a/translation/installer_sl.isl b/src/tego_ui/translation/installer_sl.isl similarity index 100% rename from translation/installer_sl.isl rename to src/tego_ui/translation/installer_sl.isl diff --git a/translation/installer_sq.isl b/src/tego_ui/translation/installer_sq.isl similarity index 100% rename from translation/installer_sq.isl rename to src/tego_ui/translation/installer_sq.isl diff --git a/translation/installer_sv.isl b/src/tego_ui/translation/installer_sv.isl similarity index 100% rename from translation/installer_sv.isl rename to src/tego_ui/translation/installer_sv.isl diff --git a/translation/installer_tr.isl b/src/tego_ui/translation/installer_tr.isl similarity index 100% rename from translation/installer_tr.isl rename to src/tego_ui/translation/installer_tr.isl diff --git a/translation/installer_uk.isl b/src/tego_ui/translation/installer_uk.isl similarity index 100% rename from translation/installer_uk.isl rename to src/tego_ui/translation/installer_uk.isl diff --git a/translation/installer_zh.isl b/src/tego_ui/translation/installer_zh.isl similarity index 100% rename from translation/installer_zh.isl rename to src/tego_ui/translation/installer_zh.isl diff --git a/translation/installer_zh_HK.isl b/src/tego_ui/translation/installer_zh_HK.isl similarity index 100% rename from translation/installer_zh_HK.isl rename to src/tego_ui/translation/installer_zh_HK.isl diff --git a/translation/ricochet_bg.ts b/src/tego_ui/translation/ricochet_bg.ts similarity index 100% rename from translation/ricochet_bg.ts rename to src/tego_ui/translation/ricochet_bg.ts diff --git a/translation/ricochet_cs.ts b/src/tego_ui/translation/ricochet_cs.ts similarity index 100% rename from translation/ricochet_cs.ts rename to src/tego_ui/translation/ricochet_cs.ts diff --git a/translation/ricochet_da.ts b/src/tego_ui/translation/ricochet_da.ts similarity index 100% rename from translation/ricochet_da.ts rename to src/tego_ui/translation/ricochet_da.ts diff --git a/translation/ricochet_de.ts b/src/tego_ui/translation/ricochet_de.ts similarity index 100% rename from translation/ricochet_de.ts rename to src/tego_ui/translation/ricochet_de.ts diff --git a/translation/ricochet_en.ts b/src/tego_ui/translation/ricochet_en.ts similarity index 100% rename from translation/ricochet_en.ts rename to src/tego_ui/translation/ricochet_en.ts diff --git a/translation/ricochet_es.ts b/src/tego_ui/translation/ricochet_es.ts similarity index 100% rename from translation/ricochet_es.ts rename to src/tego_ui/translation/ricochet_es.ts diff --git a/translation/ricochet_et_EE.ts b/src/tego_ui/translation/ricochet_et_EE.ts similarity index 100% rename from translation/ricochet_et_EE.ts rename to src/tego_ui/translation/ricochet_et_EE.ts diff --git a/translation/ricochet_fi.ts b/src/tego_ui/translation/ricochet_fi.ts similarity index 100% rename from translation/ricochet_fi.ts rename to src/tego_ui/translation/ricochet_fi.ts diff --git a/translation/ricochet_fil_PH.ts b/src/tego_ui/translation/ricochet_fil_PH.ts similarity index 100% rename from translation/ricochet_fil_PH.ts rename to src/tego_ui/translation/ricochet_fil_PH.ts diff --git a/translation/ricochet_fr.ts b/src/tego_ui/translation/ricochet_fr.ts similarity index 100% rename from translation/ricochet_fr.ts rename to src/tego_ui/translation/ricochet_fr.ts diff --git a/translation/ricochet_he.ts b/src/tego_ui/translation/ricochet_he.ts similarity index 100% rename from translation/ricochet_he.ts rename to src/tego_ui/translation/ricochet_he.ts diff --git a/translation/ricochet_it.ts b/src/tego_ui/translation/ricochet_it.ts similarity index 100% rename from translation/ricochet_it.ts rename to src/tego_ui/translation/ricochet_it.ts diff --git a/translation/ricochet_it_IT.ts b/src/tego_ui/translation/ricochet_it_IT.ts similarity index 100% rename from translation/ricochet_it_IT.ts rename to src/tego_ui/translation/ricochet_it_IT.ts diff --git a/translation/ricochet_ja.ts b/src/tego_ui/translation/ricochet_ja.ts similarity index 100% rename from translation/ricochet_ja.ts rename to src/tego_ui/translation/ricochet_ja.ts diff --git a/translation/ricochet_nb.ts b/src/tego_ui/translation/ricochet_nb.ts similarity index 100% rename from translation/ricochet_nb.ts rename to src/tego_ui/translation/ricochet_nb.ts diff --git a/translation/ricochet_nl_NL.ts b/src/tego_ui/translation/ricochet_nl_NL.ts similarity index 100% rename from translation/ricochet_nl_NL.ts rename to src/tego_ui/translation/ricochet_nl_NL.ts diff --git a/translation/ricochet_pl.ts b/src/tego_ui/translation/ricochet_pl.ts similarity index 100% rename from translation/ricochet_pl.ts rename to src/tego_ui/translation/ricochet_pl.ts diff --git a/translation/ricochet_pt_BR.ts b/src/tego_ui/translation/ricochet_pt_BR.ts similarity index 100% rename from translation/ricochet_pt_BR.ts rename to src/tego_ui/translation/ricochet_pt_BR.ts diff --git a/translation/ricochet_pt_PT.ts b/src/tego_ui/translation/ricochet_pt_PT.ts similarity index 100% rename from translation/ricochet_pt_PT.ts rename to src/tego_ui/translation/ricochet_pt_PT.ts diff --git a/translation/ricochet_ru.ts b/src/tego_ui/translation/ricochet_ru.ts similarity index 100% rename from translation/ricochet_ru.ts rename to src/tego_ui/translation/ricochet_ru.ts diff --git a/translation/ricochet_sl.ts b/src/tego_ui/translation/ricochet_sl.ts similarity index 100% rename from translation/ricochet_sl.ts rename to src/tego_ui/translation/ricochet_sl.ts diff --git a/translation/ricochet_sq.ts b/src/tego_ui/translation/ricochet_sq.ts similarity index 100% rename from translation/ricochet_sq.ts rename to src/tego_ui/translation/ricochet_sq.ts diff --git a/translation/ricochet_sv.ts b/src/tego_ui/translation/ricochet_sv.ts similarity index 100% rename from translation/ricochet_sv.ts rename to src/tego_ui/translation/ricochet_sv.ts diff --git a/translation/ricochet_tr.ts b/src/tego_ui/translation/ricochet_tr.ts similarity index 100% rename from translation/ricochet_tr.ts rename to src/tego_ui/translation/ricochet_tr.ts diff --git a/translation/ricochet_uk.ts b/src/tego_ui/translation/ricochet_uk.ts similarity index 100% rename from translation/ricochet_uk.ts rename to src/tego_ui/translation/ricochet_uk.ts diff --git a/translation/ricochet_zh.ts b/src/tego_ui/translation/ricochet_zh.ts similarity index 100% rename from translation/ricochet_zh.ts rename to src/tego_ui/translation/ricochet_zh.ts diff --git a/translation/ricochet_zh_HK.ts b/src/tego_ui/translation/ricochet_zh_HK.ts similarity index 100% rename from translation/ricochet_zh_HK.ts rename to src/tego_ui/translation/ricochet_zh_HK.ts diff --git a/src/tests/tests.pri b/src/tests/tests.pri new file mode 100644 index 0000000..41c0762 --- /dev/null +++ b/src/tests/tests.pri @@ -0,0 +1,13 @@ +TEMPLATE = app +QT += testlib core network quick +CONFIG -= app_bundle +CONFIG += testcase + +QMAKE_INCLUDES = $${PWD}/../qmake_includes + +include($${QMAKE_INCLUDES}/artifacts.pri) +include($${QMAKE_INCLUDES}/compiler_flags.pri) +include($${QMAKE_INCLUDES}/linker_flags.pri) + +include($${PWD}/../libtego_ui/libtego_ui.pri) +include($${PWD}/../libtego/libtego.pri) diff --git a/src/tests/tests.pro b/src/tests/tests.pro new file mode 100644 index 0000000..3286411 --- /dev/null +++ b/src/tests/tests.pro @@ -0,0 +1,8 @@ +include($${PWD}/../qmake_includes/artifacts.pri) + +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = \ + tst_cryptokey \ + tst_contactidvalidator \ diff --git a/tests/tst_contactidvalidator/tst_contactidvalidator.cpp b/src/tests/tst_contactidvalidator/tst_contactidvalidator.cpp similarity index 84% rename from tests/tst_contactidvalidator/tst_contactidvalidator.cpp rename to src/tests/tst_contactidvalidator/tst_contactidvalidator.cpp index 0843606..bb1b5a3 100644 --- a/tests/tst_contactidvalidator/tst_contactidvalidator.cpp +++ b/src/tests/tst_contactidvalidator/tst_contactidvalidator.cpp @@ -1,5 +1,7 @@ #include #include +#include + #include "core/ContactIDValidator.h" class TestContactIDValidator : public QObject @@ -18,7 +20,7 @@ void TestContactIDValidator::test_validate() int pos = 0; QCOMPARE(validator.validate(text, pos), QValidator::Invalid); - text = "ricochet:iou53ffunpweuzy5"; + text = "ricochet:kmhee7bfsixluoummhu7rkjx6vlxksneflromksrdhhi7n5ks3ckygqd"; pos = 0; QCOMPARE(validator.validate(text, pos), QValidator::Acceptable); } diff --git a/tests/tst_contactidvalidator/tst_contactidvalidator.pro b/src/tests/tst_contactidvalidator/tst_contactidvalidator.pro similarity index 50% rename from tests/tst_contactidvalidator/tst_contactidvalidator.pro rename to src/tests/tst_contactidvalidator/tst_contactidvalidator.pro index 9894728..615ea3a 100644 --- a/tests/tst_contactidvalidator/tst_contactidvalidator.pro +++ b/src/tests/tst_contactidvalidator/tst_contactidvalidator.pro @@ -1,5 +1,4 @@ include(../tests.pri) -include(../app_common.pri) -include($${SRC}/../protobuf.pri) SOURCES += tst_contactidvalidator.cpp + diff --git a/src/tests/tst_cryptokey/tst_cryptokey.cpp b/src/tests/tst_cryptokey/tst_cryptokey.cpp new file mode 100644 index 0000000..fd2c2db --- /dev/null +++ b/src/tests/tst_cryptokey/tst_cryptokey.cpp @@ -0,0 +1,233 @@ +/* Ricochet - https://ricochet.im/ + * Copyright (C) 2014, John Brooks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the names of the copyright owners 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 + * OWNER 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. + */ + +// C +#include +#include +// C++ +#include + +// libtego +#include + +// libtego_ui +#include +#include + +class TestCryptoKey : public QObject +{ + Q_OBJECT + +private slots: + void loadFromServiceId(); + void loadFromKeyBlob(); + void encodedKeyBlob(); + void torServiceId(); + void signData(); + void verifYData(); +}; + +constexpr char keyBlob[] = "ED25519-V3:CAeUhUcyrjvk95WmTaexNRY5+0wFvd7P2zDMhhBZM2TwnD2I9YgK3yMO/jOk0LVc39xnULCR02ZBghiyFdNR3w=="; + +constexpr char serviceId[] = "ockeilzymnguehc4brf4dpcsc634wtei75wa5edslx6yuwfaw3pje6id"; + +constexpr char message[] = "Hello, How are you?"; + +constexpr uint8_t signature[] = { + 0xf2, 0x88, 0x9a, 0x40, 0x35, 0xa6, 0xc5, 0xca, + 0x7c, 0x11, 0xcf, 0xd3, 0x3a, 0x5e, 0x75, 0xea, + 0xac, 0x53, 0x6f, 0x31, 0xf0, 0x78, 0x8a, 0x8f, + 0x0e, 0x55, 0x86, 0x60, 0x18, 0x96, 0x3a, 0x8a, + 0x44, 0x15, 0xef, 0xe6, 0x03, 0x67, 0x6d, 0xb2, + 0x6f, 0x90, 0x81, 0x22, 0x76, 0x77, 0xa2, 0xcb, + 0x39, 0xcc, 0xef, 0x67, 0xb7, 0x33, 0x73, 0x21, + 0xc0, 0x10, 0xe9, 0x37, 0x14, 0x93, 0x37, 0x05, +}; + +void TestCryptoKey::loadFromServiceId() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // give loadFromServiceId bad data + + // nullptr + QVERIFY_EXCEPTION_THROWN(ck.loadFromServiceId(nullptr), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // empty string + QVERIFY_EXCEPTION_THROWN(ck.loadFromServiceId(""), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // a random string + QVERIFY_EXCEPTION_THROWN(ck.loadFromServiceId("garbage string"), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // correct length but invalid service id + QVERIFY_EXCEPTION_THROWN(ck.loadFromServiceId("fakeserviceidfakeserviceidfakeserviceidfakeserviceidfake"), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // load a valid service id + QVERIFY(ck.loadFromServiceId(serviceId)); + QVERIFY(ck.isLoaded()); + QVERIFY(!ck.isPrivate()); +} + +void TestCryptoKey::loadFromKeyBlob() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // giving loadFromKeyBlob bad data + + // nullptr + QVERIFY_EXCEPTION_THROWN(ck.loadFromKeyBlob(nullptr), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // empty string + QVERIFY_EXCEPTION_THROWN(ck.loadFromKeyBlob(""), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // a random string + QVERIFY_EXCEPTION_THROWN(ck.loadFromKeyBlob("garbage string"), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // correct prefix not enough data + QVERIFY_EXCEPTION_THROWN(ck.loadFromKeyBlob("ED25519-V3:looksLikeBase64"), std:: + runtime_error); + QVERIFY(!ck.isLoaded()); + // right size, bad prefix + QVERIFY_EXCEPTION_THROWN(ck.loadFromKeyBlob("BAD-PREFIX:/RU9USuBKBRmPRkLBXbN/cVbDUoz7+Ay/aCIX4jTyQ9GM5UBaMwDvfzt21DEv5NhUxt61GpZf06z6iN0WElwgA=="), std::runtime_error); + QVERIFY(!ck.isLoaded()); + + // load a valid KeyBlob + QVERIFY(ck.loadFromKeyBlob(keyBlob)); + QVERIFY(ck.isLoaded()); + QVERIFY(ck.isPrivate()); +} + +void TestCryptoKey::encodedKeyBlob() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // try to encode when no key loaded + QVERIFY_EXCEPTION_THROWN(ck.encodedKeyBlob(), std::runtime_error); + + // load private key from KeyBlob + QVERIFY(ck.loadFromKeyBlob(keyBlob)); + QVERIFY(ck.isLoaded()); + + // verify it round trips + QCOMPARE(ck.encodedKeyBlob(), keyBlob); +} + +void TestCryptoKey::torServiceId() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // try to get service id when no key loaded + QVERIFY_EXCEPTION_THROWN(ck.torServiceID(), std::runtime_error); + + // load private key from KeyBlob + QVERIFY(ck.loadFromKeyBlob(keyBlob)); + QCOMPARE(ck.isLoaded(), true); + QCOMPARE(ck.isPrivate(), true); + + // compare calculated service id to truth + QCOMPARE(ck.torServiceID(), serviceId); + + // clear out key + ck.clear(); + QVERIFY(!ck.isLoaded()); + + // load public key from service id + QVERIFY(ck.loadFromServiceId(serviceId)); + QCOMPARE(ck.isLoaded(), true); + QVERIFY(!ck.isPrivate()); + + // compare calculated service id to truth + QCOMPARE(ck.torServiceID(), serviceId); +} + +void TestCryptoKey::signData() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // fail to sign with no key + QVERIFY_EXCEPTION_THROWN(ck.signData(message), std::runtime_error); + + // fail to sign with a public key + QVERIFY(ck.loadFromServiceId(serviceId)); + QVERIFY(ck.isLoaded()); + QVERIFY(!ck.isPrivate()); + QVERIFY_EXCEPTION_THROWN(ck.signData(message), std::runtime_error); + + ck.clear(); + QVERIFY(!ck.isLoaded()); + + // load our private key + QVERIFY(ck.loadFromKeyBlob(keyBlob)); + QVERIFY(ck.isLoaded()); + QVERIFY(ck.isPrivate()); + + // fail to sign empty message + QVERIFY_EXCEPTION_THROWN(ck.signData({}), std::runtime_error); + + // succed to sign our message + QCOMPARE(ck.signData(message), QByteArray(reinterpret_cast(signature), sizeof(signature))); +} +void TestCryptoKey::verifYData() +{ + CryptoKey ck; + QVERIFY(!ck.isLoaded()); + + // load public key from service id + QVERIFY(ck.loadFromServiceId(serviceId)); + QVERIFY(ck.isLoaded()); + QVERIFY(!ck.isPrivate()); + + // try and verify an empty signature + QVERIFY_EXCEPTION_THROWN(ck.verifyData(message, {}), std::runtime_error); + // try and verify signature with not enough bytes (32 rather than 64) + QVERIFY_EXCEPTION_THROWN(ck.verifyData(message, QByteArray{32, 0}), std::runtime_error); + // try and verify incorrect sig (64 0s) + QVERIFY(!ck.verifyData(message, QByteArray{64, 0})); + + // verify correct signature + QVERIFY(ck.verifyData(message, QByteArray(reinterpret_cast(signature), sizeof(signature)))); +} + +QTEST_MAIN(TestCryptoKey) +#include "tst_cryptokey.moc" diff --git a/src/tests/tst_cryptokey/tst_cryptokey.pro b/src/tests/tst_cryptokey/tst_cryptokey.pro new file mode 100644 index 0000000..8daeb92 --- /dev/null +++ b/src/tests/tst_cryptokey/tst_cryptokey.pro @@ -0,0 +1,3 @@ +include(../tests.pri) + +SOURCES += tst_cryptokey.cpp diff --git a/tests/tst_template/tst_template.cpp b/src/tests/tst_template/tst_template.cpp similarity index 100% rename from tests/tst_template/tst_template.cpp rename to src/tests/tst_template/tst_template.cpp diff --git a/tests/tst_template/tst_template.pro b/src/tests/tst_template/tst_template.pro similarity index 100% rename from tests/tst_template/tst_template.pro rename to src/tests/tst_template/tst_template.pro diff --git a/src/utils/CryptoKey.cpp b/src/utils/CryptoKey.cpp deleted file mode 100644 index 8aa0357..0000000 --- a/src/utils/CryptoKey.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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. - * - * * Neither the names of the copyright owners 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 - * OWNER 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 "CryptoKey.h" -#include "SecureRNG.h" -#include "Useful.h" -#include -#include -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) -void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -{ - *p = r->p; - *q = r->q; -} -#define RSA_bits(o) (BN_num_bits((o)->n)) -#endif - -void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen); -bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen); - -CryptoKey::CryptoKey() -{ -} - -CryptoKey::~CryptoKey() -{ - clear(); -} - -CryptoKey::Data::~Data() -{ - if (key) - { - RSA_free(key); - key = 0; - } -} - -void CryptoKey::clear() -{ - d = 0; -} - -bool CryptoKey::loadFromData(const QByteArray &data, KeyType type, KeyFormat format) -{ - RSA *key = NULL; - clear(); - - if (data.isEmpty()) - return false; - - if (format == PEM) { - BIO *b = BIO_new_mem_buf((void*)data.constData(), -1); - - if (type == PrivateKey) - key = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL); - else - key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL); - - BIO_free(b); - } else if (format == DER) { - const uchar *dp = reinterpret_cast(data.constData()); - - if (type == PrivateKey) - key = d2i_RSAPrivateKey(NULL, &dp, data.size()); - else - key = d2i_RSAPublicKey(NULL, &dp, data.size()); - } else { - Q_UNREACHABLE(); - } - - if (!key) { - qWarning() << "Failed to parse" << (type == PrivateKey ? "private" : "public") << "key from data"; - return false; - } - - d = new Data(key); - return true; -} - -bool CryptoKey::loadFromFile(const QString &path, KeyType type, KeyFormat format) -{ - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Failed to open" << (type == PrivateKey ? "private" : "public") << "key from" - << path << "-" << file.errorString(); - return false; - } - - QByteArray data = file.readAll(); - file.close(); - - return loadFromData(data, type, format); -} - -bool CryptoKey::isPrivate() const -{ - if (!isLoaded()) { - return false; - } else { - const BIGNUM *p, *q; - RSA_get0_factors(d->key, &p, &q); - return (p != 0); - } -} - -int CryptoKey::bits() const -{ - return isLoaded() ? RSA_bits(d->key) : 0; -} - -QByteArray CryptoKey::publicKeyDigest() const -{ - if (!isLoaded()) - return QByteArray(); - - QByteArray buf = encodedPublicKey(DER); - - QByteArray re(20, 0); - bool ok = SHA1(reinterpret_cast(buf.constData()), buf.size(), - reinterpret_cast(re.data())) != NULL; - - if (!ok) - { - qWarning() << "Failed to hash public key data for digest"; - return QByteArray(); - } - - return re; -} - -QByteArray CryptoKey::encodedPublicKey(KeyFormat format) const -{ - if (!isLoaded()) - return QByteArray(); - - if (format == PEM) { - BIO *b = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSAPublicKey(b, d->key)) { - BUG() << "Failed to encode public key in PEM format"; - BIO_free(b); - return QByteArray(); - } - - BUF_MEM *buf; - BIO_get_mem_ptr(b, &buf); - - /* Close BIO, but don't free buf. */ - (void)BIO_set_close(b, BIO_NOCLOSE); - BIO_free(b); - - QByteArray re((const char *)buf->data, (int)buf->length); - BUF_MEM_free(buf); - return re; - } else if (format == DER) { - uchar *buf = NULL; - int len = i2d_RSAPublicKey(d->key, &buf); - if (len <= 0 || !buf) { - BUG() << "Failed to encode public key in DER format"; - return QByteArray(); - } - - QByteArray re((const char*)buf, len); - OPENSSL_free(buf); - return re; - } else { - Q_UNREACHABLE(); - } - - return QByteArray(); -} - -QByteArray CryptoKey::encodedPrivateKey(KeyFormat format) const -{ - if (!isLoaded() || !isPrivate()) - return QByteArray(); - - if (format == PEM) { - BIO *b = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSAPrivateKey(b, d->key, NULL, NULL, 0, NULL, NULL)) { - BUG() << "Failed to encode private key in PEM format"; - BIO_free(b); - return QByteArray(); - } - - BUF_MEM *buf; - BIO_get_mem_ptr(b, &buf); - - /* Close BIO, but don't free buf. */ - (void)BIO_set_close(b, BIO_NOCLOSE); - BIO_free(b); - - QByteArray re((const char *)buf->data, (int)buf->length); - BUF_MEM_free(buf); - return re; - } else if (format == DER) { - uchar *buf = NULL; - int len = i2d_RSAPrivateKey(d->key, &buf); - if (len <= 0 || !buf) { - BUG() << "Failed to encode private key in DER format"; - return QByteArray(); - } - - QByteArray re((const char*)buf, len); - OPENSSL_free(buf); - return re; - } else { - Q_UNREACHABLE(); - } - - return QByteArray(); -} - -QString CryptoKey::torServiceID() const -{ - if (!isLoaded()) - return QString(); - - QByteArray digest = publicKeyDigest(); - if (digest.isNull()) - return QString(); - - static const int hostnameDigestSize = 10; - static const int hostnameEncodedSize = 16; - - QByteArray re(hostnameEncodedSize+1, 0); - base32_encode(re.data(), re.size(), digest.constData(), hostnameDigestSize); - - // Chop extra null byte - re.chop(1); - - return QString::fromLatin1(re); -} - -QByteArray CryptoKey::signData(const QByteArray &data) const -{ - QByteArray digest(32, 0); - bool ok = SHA256(reinterpret_cast(data.constData()), data.size(), - reinterpret_cast(digest.data())) != NULL; - if (!ok) { - qWarning() << "Digest for RSA signature failed"; - return QByteArray(); - } - - return signSHA256(digest); -} - -QByteArray CryptoKey::signSHA256(const QByteArray &digest) const -{ - if (!isPrivate()) - return QByteArray(); - - QByteArray re(RSA_size(d->key), 0); - unsigned sigsize = 0; - int r = RSA_sign(NID_sha256, reinterpret_cast(digest.constData()), digest.size(), - reinterpret_cast(re.data()), &sigsize, d->key); - - if (r != 1) { - qWarning() << "RSA encryption failed when generating signature"; - return QByteArray(); - } - - re.truncate(sigsize); - return re; -} - -bool CryptoKey::verifyData(const QByteArray &data, QByteArray signature) const -{ - QByteArray digest(32, 0); - bool ok = SHA256(reinterpret_cast(data.constData()), data.size(), - reinterpret_cast(digest.data())) != NULL; - - if (!ok) { - qWarning() << "Digest for RSA verify failed"; - return false; - } - - return verifySHA256(digest, signature); -} - -bool CryptoKey::verifySHA256(const QByteArray &digest, QByteArray signature) const -{ - if (!isLoaded()) - return false; - - int r = RSA_verify(NID_sha256, reinterpret_cast(digest.constData()), digest.size(), - reinterpret_cast(signature.data()), signature.size(), d->key); - if (r != 1) - return false; - return true; -} - -/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */ -QByteArray torControlHashedPassword(const QByteArray &password) -{ - QByteArray salt = SecureRNG::random(8); - if (salt.isNull()) - return QByteArray(); - - int count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6); - - SHA_CTX hash; - SHA1_Init(&hash); - - QByteArray tmp = salt + password; - while (count) - { - int c = qMin(count, tmp.size()); - SHA1_Update(&hash, reinterpret_cast(tmp.constData()), c); - count -= c; - } - - unsigned char md[20]; - SHA1_Final(md, &hash); - - /* 60 is the hex-encoded value of 96, which is a constant used by Tor's algorithm. */ - return QByteArray("16:") + salt.toHex().toUpper() + QByteArray("60") + - QByteArray::fromRawData(reinterpret_cast(md), 20).toHex().toUpper(); -} - -/* Copyright (c) 2001-2004, Roger Dingledine - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson - * Copyright (c) 2007-2010, The Tor Project, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 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. - * - * Neither the names of the copyright owners 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 - * OWNER 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. - */ - -#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567" - -/* Implements base32 encoding as in rfc3548. Requires that srclen*8 is a multiple of 5. */ -void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen) -{ - unsigned i, bit, v, u; - unsigned nbits = srclen * 8; - - /* We need an even multiple of 5 bits, and enough space */ - if ((nbits%5) != 0 || destlen > (nbits/5)+1) { - Q_ASSERT(false); - memset(dest, 0, destlen); - return; - } - - for (i = 0, bit = 0; bit < nbits; ++i, bit += 5) - { - /* set v to the 16-bit value starting at src[bits/8], 0-padded. */ - v = ((quint8) src[bit / 8]) << 8; - if (bit + 5 < nbits) - v += (quint8) src[(bit/8)+1]; - - /* set u to the 5-bit value at the bit'th bit of src. */ - u = (v >> (11 - (bit % 8))) & 0x1F; - dest[i] = BASE32_CHARS[u]; - } - - dest[i] = '\0'; -} - -/* Implements base32 decoding as in rfc3548. Requires that srclen*5 is a multiple of 8. */ -bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen) -{ - unsigned int i, j, bit; - unsigned nbits = srclen * 5; - - /* We need an even multiple of 8 bits, and enough space */ - if ((nbits%8) != 0 || (nbits/8)+1 > destlen) { - Q_ASSERT(false); - return false; - } - - char *tmp = new char[srclen]; - - /* Convert base32 encoded chars to the 5-bit values that they represent. */ - for (j = 0; j < srclen; ++j) - { - if (src[j] > 0x60 && src[j] < 0x7B) - tmp[j] = src[j] - 0x61; - else if (src[j] > 0x31 && src[j] < 0x38) - tmp[j] = src[j] - 0x18; - else if (src[j] > 0x40 && src[j] < 0x5B) - tmp[j] = src[j] - 0x41; - else - { - delete[] tmp; - return false; - } - } - - /* Assemble result byte-wise by applying five possible cases. */ - for (i = 0, bit = 0; bit < nbits; ++i, bit += 8) - { - switch (bit % 40) - { - case 0: - dest[i] = (((quint8)tmp[(bit/5)]) << 3) + (((quint8)tmp[(bit/5)+1]) >> 2); - break; - case 8: - dest[i] = (((quint8)tmp[(bit/5)]) << 6) + (((quint8)tmp[(bit/5)+1]) << 1) - + (((quint8)tmp[(bit/5)+2]) >> 4); - break; - case 16: - dest[i] = (((quint8)tmp[(bit/5)]) << 4) + (((quint8)tmp[(bit/5)+1]) >> 1); - break; - case 24: - dest[i] = (((quint8)tmp[(bit/5)]) << 7) + (((quint8)tmp[(bit/5)+1]) << 2) - + (((quint8)tmp[(bit/5)+2]) >> 3); - break; - case 32: - dest[i] = (((quint8)tmp[(bit/5)]) << 5) + ((quint8)tmp[(bit/5)+1]); - break; - } - } - - delete[] tmp; - return true; -} diff --git a/tests/app_common.pri b/tests/app_common.pri deleted file mode 100644 index ce0ce0e..0000000 --- a/tests/app_common.pri +++ /dev/null @@ -1,124 +0,0 @@ -QT += core gui network quick widgets - -CONFIG += c++11 - -macx { - QT += macextras -} - -win32|mac { - # For mac, this is necessary because homebrew does not link openssl .pc to - # /usr/local/lib/pkgconfig (presumably because it used to be a system - # package). - # - # Unfortunately, it is no longer really a system package, and we really - # need to know where it is. - isEmpty(OPENSSLDIR): error(You must pass OPENSSLDIR=path/to/openssl to qmake on this platform) -} - -unix { - !isEmpty(OPENSSLDIR) { - INCLUDEPATH += $${OPENSSLDIR}/include - LIBS += -L$${OPENSSLDIR}/lib -lcrypto - } else { - CONFIG += link_pkgconfig - PKGCONFIG += libcrypto - } -} -win32 { - INCLUDEPATH += $${OPENSSLDIR}/include - - win32-g++ { - LIBS += -L$${OPENSSLDIR}/lib -lcrypto - } else { - LIBS += -L$${OPENSSLDIR}/lib -llibeay32 - } - - # required by openssl - LIBS += -luser32 -lgdi32 -ladvapi32 -} - -SOURCES += \ - $${SRC}/tor/TorControl.cpp \ - $${SRC}/tor/TorControlSocket.cpp \ - $${SRC}/tor/TorControlCommand.cpp \ - $${SRC}/tor/ProtocolInfoCommand.cpp \ - $${SRC}/tor/AuthenticateCommand.cpp \ - $${SRC}/tor/SetConfCommand.cpp \ - $${SRC}/tor/AddOnionCommand.cpp \ - $${SRC}/tor/GetConfCommand.cpp \ - $${SRC}/tor/HiddenService.cpp \ - $${SRC}/tor/TorProcess.cpp \ - $${SRC}/tor/TorManager.cpp \ - $${SRC}/tor/TorSocket.cpp \ - $${SRC}/core/ContactIDValidator.cpp \ - $${SRC}/core/ContactsManager.cpp \ - $${SRC}/core/ContactUser.cpp \ - $${SRC}/core/OutgoingContactRequest.cpp \ - $${SRC}/core/IncomingRequestManager.cpp \ - $${SRC}/core/UserIdentity.cpp \ - $${SRC}/core/IdentityManager.cpp \ - $${SRC}/core/ConversationModel.cpp \ - $${SRC}/utils/StringUtil.cpp \ - $${SRC}/utils/CryptoKey.cpp \ - $${SRC}/utils/SecureRNG.cpp \ - $${SRC}/utils/Settings.cpp \ - $${SRC}/utils/PendingOperation.cpp \ - $${SRC}/ui/ContactsModel.cpp \ - $${SRC}/ui/MainWindow.cpp \ - $${SRC}/ui/LinkedText.cpp \ - $${SRC}/ui/LanguagesModel.cpp - -HEADERS += $${SRC}/ui/MainWindow.h \ - $${SRC}/ui/ContactsModel.h \ - $${SRC}/tor/TorControl.h \ - $${SRC}/tor/TorControlSocket.h \ - $${SRC}/tor/TorControlCommand.h \ - $${SRC}/tor/ProtocolInfoCommand.h \ - $${SRC}/tor/AuthenticateCommand.h \ - $${SRC}/tor/SetConfCommand.h \ - $${SRC}/tor/AddOnionCommand.h \ - $${SRC}/utils/StringUtil.h \ - $${SRC}/core/ContactsManager.h \ - $${SRC}/core/ContactUser.h \ - $${SRC}/tor/GetConfCommand.h \ - $${SRC}/tor/HiddenService.h \ - $${SRC}/utils/CryptoKey.h \ - $${SRC}/utils/SecureRNG.h \ - $${SRC}/core/OutgoingContactRequest.h \ - $${SRC}/core/IncomingRequestManager.h \ - $${SRC}/core/ContactIDValidator.h \ - $${SRC}/core/UserIdentity.h \ - $${SRC}/core/IdentityManager.h \ - $${SRC}/core/ConversationModel.h \ - $${SRC}/tor/TorProcess.h \ - $${SRC}/tor/TorProcess_p.h \ - $${SRC}/tor/TorManager.h \ - $${SRC}/tor/TorSocket.h \ - $${SRC}/utils/Settings.h \ - $${SRC}/utils/PendingOperation.h \ - $${SRC}/ui/LinkedText.h \ - $${SRC}/ui/LanguagesModel.h - -SOURCES += $${SRC}/protocol/Channel.cpp \ - $${SRC}/protocol/ControlChannel.cpp \ - $${SRC}/protocol/Connection.cpp \ - $${SRC}/protocol/OutboundConnector.cpp \ - $${SRC}/protocol/AuthHiddenServiceChannel.cpp \ - $${SRC}/protocol/ChatChannel.cpp \ - $${SRC}/protocol/ContactRequestChannel.cpp - -HEADERS += $${SRC}/protocol/Channel.h \ - $${SRC}/protocol/Channel_p.h \ - $${SRC}/protocol/ControlChannel.h \ - $${SRC}/protocol/Connection.h \ - $${SRC}/protocol/Connection_p.h \ - $${SRC}/protocol/OutboundConnector.h \ - $${SRC}/protocol/AuthHiddenServiceChannel.h \ - $${SRC}/protocol/ChatChannel.h \ - $${SRC}/protocol/ContactRequestChannel.h - -PROTOS += $${SRC}/protocol/ControlChannel.proto \ - $${SRC}/protocol/AuthHiddenService.proto \ - $${SRC}/protocol/ChatChannel.proto \ - $${SRC}/protocol/ContactRequestChannel.proto diff --git a/tests/tests.pri b/tests/tests.pri deleted file mode 100644 index 7ee54c6..0000000 --- a/tests/tests.pri +++ /dev/null @@ -1,8 +0,0 @@ -TEMPLATE = app -QT += testlib -CONFIG -= app_bundle -CONFIG += testcase - -SRC = ../../src/ -INCLUDEPATH += $${SRC} - diff --git a/tests/tests.pro b/tests/tests.pro deleted file mode 100644 index 31fbc40..0000000 --- a/tests/tests.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS += tst_cryptokey diff --git a/tests/tst_cryptokey/tst_cryptokey.cpp b/tests/tst_cryptokey/tst_cryptokey.cpp deleted file mode 100644 index 1b2f070..0000000 --- a/tests/tst_cryptokey/tst_cryptokey.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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. - * - * * Neither the names of the copyright owners 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 - * OWNER 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 "utils/CryptoKey.h" - -class TestCryptoKey : public QObject -{ - Q_OBJECT - -private slots: - void load(); - void publicKeyDigest(); - void encodedPublicKey(); - void encodedPrivateKey(); - void torServiceID(); - void sign(); -}; - -const char *alice = - "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXQIBAAKBgQDAS9nLWyK0jWZ8yduqVEhSyZRplTaeUpGWYRi14n1C4sjO6nqm\n" - "ES31UCGDH4nIor2R/XMJCJkJwK+t2XrtiH+jUEHwUGhnMkm3hW5NHt5g39s9YK7l\n" - "xD39O8N2tHUycVq8guhrb1WBQ2/bmZ85nOIuBDZxIuVQZA1U1L6rWGvm+wIDAQAB\n" - "AoGAewYL6JX9thVgpCVga7BQNObSFFpp/xBEJDkqXfLwwIHmhrpsjSIgjPke94yN\n" - "0daMAYJsvjLJ9ftYaZjhlGXngbBJiAU95gcZoTAsn2hNJP22ndGuhi6WEKhYwRxK\n" - "U5d+3Khzy/ysuoay7DSVtpSmpiacWPSiiptEkxNbcbGba8ECQQDeEGoPASmxZoh4\n" - "I2JNQkqSwMKsOZpp/SJhnmLCPoA1oDwlGtu4HF7t9hBXeyIXgLvbfJudFEa+LqR7\n" - "wrKQPn0fAkEA3a7cR7eSRNu1ak7gVfQfnP4tFl3+7UC2hUqVHLA5ks4pLl7/ITa+\n" - "3P04SOs3WpvZJHYJ+hi/anqEPYrD/3B+pQJBAKmjnnHh8IjODDjCxyjAGJntWYoZ\n" - "4yVOtEIgrc830delley+jNUkDzz3+dnqfcu4k0oD8hjYUYaduRe2T5Szt/8CQQDC\n" - "EVt8WUNujp0R9P1FohKu4IFeLGmJD/b5V2KUm927HEpG8xkM3Z1XX0KP64MpCnid\n" - "B80SKeog8CKmsb2F+NiVAkBT1CEAdiFYtf72hnZCLBw5HrqpN+zjw00GjtlrmmNV\n" - "+ILb/YRp5flCY5Se95ExzQqRKzvK5iJg0yEOVF0OcbO+\n" - "-----END RSA PRIVATE KEY-----"; -const char *aliceDigest = "623a1ffc94d8f8edcd5e47fbd45e08deb911d1bc"; -const char *aliceTorID = "mi5b77eu3d4o3tk6"; -const char *aliceSignedTestData = "23fdcd5c7d40b44a7e49619d9048c81931166a0adb80c8981cc8f9a9e02c3923d5fba6d92ea03dc672d009a5fe1be2b582fb935076f880d9aa55511c33620d2aa23336b579dd7ccd1dbf4c845e4100a114d8ac20dd47229e876444f79d5152456a8e26fefa67a12436b3c33728a2ff7cb12250c486f786647574e48bb9208f64"; - -const char *bob = - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBAMP8GyAg/kzwXizpUWjWIMw/lvDffXjsxcq1qmZWZxXJQH/oE8bX+WAf\n" - "VS8iUHVqTykubR0W3QNL6aWSZKBqDQUTN0QBJUF4qdkg3x56C0kwcWa+seDMAvJw\n" - "pcHK9wN7mtWHIhFwhikP//NylrY1MaUxcPjvOKcdJ90k988nnmpZAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n"; -const char *bobDigest = "b4780cabdfc3593004431644977cf73bf8475848"; -const char *bobTorID = "wr4azk67ynmtabcd"; - -void TestCryptoKey::load() -{ - CryptoKey key; - QVERIFY(!key.isLoaded()); - - // Private key - QVERIFY(key.loadFromData(alice, CryptoKey::PrivateKey)); - QVERIFY(key.isLoaded()); - QVERIFY(key.isPrivate()); - QCOMPARE(key.bits(), 1024); - key.clear(); - QVERIFY(!key.isLoaded()); - - // Public key - QVERIFY(key.loadFromData(bob, CryptoKey::PublicKey)); - QVERIFY(key.isLoaded()); - QVERIFY(!key.isPrivate()); - QCOMPARE(key.bits(), 1024); - - // DER public key - QByteArray derEncoded = key.encodedPublicKey(CryptoKey::DER); - key.clear(); - QVERIFY(key.loadFromData(derEncoded, CryptoKey::PublicKey, CryptoKey::DER)); - QCOMPARE(key.encodedPublicKey(CryptoKey::DER), derEncoded); - key.clear(); - - // Invalid key - QVERIFY(!key.loadFromData(QByteArray(alice).mid(0, 150), CryptoKey::PrivateKey)); - QVERIFY(!key.isLoaded()); - - // Invalid DER key - QVERIFY(!key.loadFromData(derEncoded.mid(0, derEncoded.size()-2), CryptoKey::PublicKey, CryptoKey::DER)); - QVERIFY(!key.isLoaded()); - - // Empty key - QVERIFY(!key.loadFromData("", CryptoKey::PublicKey)); - QVERIFY(!key.isLoaded()); -} - -void TestCryptoKey::publicKeyDigest() -{ - CryptoKey key; - QVERIFY(key.loadFromData(bob, CryptoKey::PublicKey)); - QCOMPARE(key.publicKeyDigest().toHex(), QByteArray(bobDigest)); - - key.clear(); - QVERIFY(key.loadFromData(alice, CryptoKey::PrivateKey)); - QCOMPARE(key.publicKeyDigest().toHex(), QByteArray(aliceDigest)); -} - -void TestCryptoKey::encodedPublicKey() -{ - CryptoKey key; - QVERIFY(key.loadFromData(bob, CryptoKey::PublicKey)); - - QByteArray pemEncoded = key.encodedPublicKey(CryptoKey::PEM); - QVERIFY(pemEncoded.contains("BEGIN RSA PUBLIC KEY")); - - QByteArray derEncoded = key.encodedPublicKey(CryptoKey::DER); - QCOMPARE(derEncoded.size(), 140); - - CryptoKey key2; - QVERIFY(key2.loadFromData(pemEncoded, CryptoKey::PublicKey)); - QCOMPARE(key.encodedPublicKey(CryptoKey::PEM), key2.encodedPublicKey(CryptoKey::PEM)); - QCOMPARE(key.publicKeyDigest(), key2.publicKeyDigest()); - - CryptoKey key3; - QVERIFY(key3.loadFromData(derEncoded, CryptoKey::PublicKey, CryptoKey::DER)); - QCOMPARE(key.encodedPublicKey(CryptoKey::DER), key3.encodedPublicKey(CryptoKey::DER)); - QCOMPARE(key.publicKeyDigest(), key3.publicKeyDigest()); - - // Doesn't contain a private key - CryptoKey key4; - QVERIFY(!key4.loadFromData(pemEncoded, CryptoKey::PrivateKey)); -} - -void TestCryptoKey::encodedPrivateKey() -{ - CryptoKey key; - QVERIFY(key.loadFromData(alice, CryptoKey::PrivateKey)); - - QByteArray pemEncoded = key.encodedPrivateKey(CryptoKey::PEM); - QVERIFY(pemEncoded.contains("BEGIN RSA PRIVATE KEY")); - - QByteArray derEncoded = key.encodedPrivateKey(CryptoKey::DER); - QVERIFY(!derEncoded.isEmpty()); - - CryptoKey key2; - QVERIFY(key2.loadFromData(pemEncoded, CryptoKey::PrivateKey)); - QCOMPARE(key.encodedPrivateKey(CryptoKey::PEM), key2.encodedPrivateKey(CryptoKey::PEM)); - QCOMPARE(key.publicKeyDigest(), key2.publicKeyDigest()); - - CryptoKey key3; - QVERIFY(key3.loadFromData(derEncoded, CryptoKey::PrivateKey, CryptoKey::DER)); - QCOMPARE(key.encodedPrivateKey(CryptoKey::DER), key3.encodedPrivateKey(CryptoKey::DER)); - QCOMPARE(key.publicKeyDigest(), key3.publicKeyDigest()); -} - -void TestCryptoKey::torServiceID() -{ - CryptoKey key; - QVERIFY(key.loadFromData(bob, CryptoKey::PublicKey)); - - QString id = key.torServiceID(); - QCOMPARE(id.size(), 16); - QCOMPARE(id, QLatin1String(bobTorID)); -} - -void TestCryptoKey::sign() -{ - CryptoKey key; - QVERIFY(key.loadFromData(alice, CryptoKey::PrivateKey)); - - QByteArray data = "test data"; - QByteArray data2 = "different"; - - // Good signature - QByteArray signature = key.signData(data); - QVERIFY(!signature.isEmpty()); - QVERIFY(key.verifyData(data, signature)); - - // Bad signature - QVERIFY(!key.verifyData(data2, signature)); - - // Corrupt signature - QVERIFY(!key.verifyData(data, signature.mid(0, signature.size() - 10))); - - // Wrong public key - CryptoKey key2; - QVERIFY(key2.loadFromData(bob, CryptoKey::PublicKey)); - QVERIFY(!key2.verifyData(data, signature)); - - // Compare to signSHA256 - QByteArray dataDigest = QCryptographicHash::hash(data, QCryptographicHash::Sha256); - QByteArray signature2 = key.signSHA256(dataDigest); - QVERIFY(!signature2.isEmpty()); - // signSHA256 and verifySHA256 - QVERIFY(key.verifySHA256(dataDigest, signature2)); - // signSHA256 and verifyData - QVERIFY(key.verifyData(data, signature2)); - // signData and verifySHA256 - QVERIFY(key.verifySHA256(dataDigest, signature)); - - // Compare to precomputed signature - QByteArray signaturep = QByteArray::fromHex(aliceSignedTestData); - QVERIFY(key.verifyData(data, signaturep)); - QVERIFY(key.verifySHA256(dataDigest, signaturep)); -} - -QTEST_MAIN(TestCryptoKey) -#include "tst_cryptokey.moc" diff --git a/tests/tst_cryptokey/tst_cryptokey.pro b/tests/tst_cryptokey/tst_cryptokey.pro deleted file mode 100644 index 0bdde39..0000000 --- a/tests/tst_cryptokey/tst_cryptokey.pro +++ /dev/null @@ -1,24 +0,0 @@ -include(../tests.pri) - -SOURCES += tst_cryptokey.cpp \ - $${SRC}/utils/CryptoKey.cpp \ - $${SRC}/utils/SecureRNG.cpp - -unix { - !isEmpty(OPENSSLDIR) { - INCLUDEPATH += $${OPENSSLDIR}/include - LIBS += -L$${OPENSSLDIR}/lib -lcrypto - } else { - CONFIG += link_pkgconfig - PKGCONFIG += libcrypto - } -} -win32 { - isEmpty(OPENSSLDIR):error(You must pass OPENSSLDIR=path/to/openssl to qmake on this platform) - INCLUDEPATH += $${OPENSSLDIR}/include - LIBS += -L$${OPENSSLDIR}/lib -llibeay32 - - # required by openssl - LIBS += -lUser32 -lGdi32 -ladvapi32 -} -macx:LIBS += -lcrypto