diff --git a/.gitignore b/.gitignore index 84ec039..bff8bc7 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,5 @@ Thumbs.db # Clion .idea/ +.tox +*.egg-info diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ad12c7..0c22052 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(PLUGIN_DIR ${CMAKE_BINARY_DIR}/plugins) find_package(Qt5 COMPONENTS Widgets REQUIRED) -find_package(cppzmq REQUIRED) find_package(nlohmann_json REQUIRED) find_package(SQLite3 REQUIRED) find_package(Catch2 REQUIRED) @@ -27,7 +26,6 @@ find_package(Catch2 REQUIRED) add_executable(bigsnitch main.cpp mainwindow.cpp - networkthread.cpp session.cpp httpflow.cpp pluginhandler.cpp @@ -38,7 +36,6 @@ add_executable(bigsnitch mainwindow.h httpflow.h - networkthread.h session.h includes.h proxyhandler.h @@ -55,18 +52,18 @@ add_executable(bigsnitch mainwindow.ui editandresend.ui settings.ui + pluginlist.ui ) target_include_directories(bigsnitch PRIVATE /usr/local/include) -target_link_libraries(bigsnitch PRIVATE Qt5::Widgets cppzmq sqlite3) +target_link_libraries(bigsnitch PRIVATE Qt5::Widgets sqlite3) add_executable(bigsnitch_tests tests/generic_tests.cpp - networkthread.cpp ) target_include_directories(bigsnitch_tests PRIVATE /usr/local/include) -target_link_libraries(bigsnitch_tests PRIVATE Qt5::Widgets cppzmq sqlite3 Catch2::Catch2) +target_link_libraries(bigsnitch_tests PRIVATE Qt5::Widgets sqlite3 Catch2::Catch2) add_subdirectory(plugins/mitmproxy/) diff --git a/editandresend.h b/editandresend.h index 4c9db07..c9109a4 100644 --- a/editandresend.h +++ b/editandresend.h @@ -6,11 +6,13 @@ namespace Ui { class EditAndResend; } +//! EditAndResend Dialog class EditAndResend : public QDialog { Q_OBJECT public: + //! EditAndResend constructor explicit EditAndResend(std::tuple initial, QWidget *parent = nullptr); ~EditAndResend(); diff --git a/historymodel.h b/historymodel.h index 47a5c1a..0e4fc73 100644 --- a/historymodel.h +++ b/historymodel.h @@ -6,6 +6,7 @@ #include #include +//! The HistoryModel implements the AbstractTableModel for interacting with the view. class HistoryModel : public QAbstractTableModel { Q_OBJECT @@ -15,19 +16,28 @@ private: std::string getRequestHeader(const HistoryItem& item) const; std::string getResponseHeader(const HistoryItem& item) const; public: + //! HistoryModel constructor HistoryModel(QObject *parent = nullptr); + //! rowCount int rowCount(const QModelIndex &parent = QModelIndex()) const override; + //! columnCount int columnCount(const QModelIndex &parent = QModelIndex()) const override; + //! data QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + //! headerData QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + //! update void update(std::vector* items); }; +//! HistoryProxyModel implements a SortFilterProxyModel for interacting with the view class HistoryProxyModel : public QSortFilterProxyModel { Q_OBJECT private: public: + //! lessThan bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; + //! filterAcceptsRow bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; }; diff --git a/include/api.h b/include/api.h index c7797d3..ed7b25c 100644 --- a/include/api.h +++ b/include/api.h @@ -3,14 +3,6 @@ //major minor patch #define LITTLESNITCH_VERSION 100 -#include - -#if defined(IS_PROXY_LIBRARY) -# define MYSHAREDLIB_EXPORT Q_DECL_EXPORT -#else -# define MYSHAREDLIB_EXPORT Q_DECL_IMPORT -#endif - #include #include #include diff --git a/include/proxyinterface.h b/include/proxyinterface.h index 3f144c2..21d1e26 100644 --- a/include/proxyinterface.h +++ b/include/proxyinterface.h @@ -21,8 +21,11 @@ namespace http { */ class ProxyInterface { public: + // the path the proxy listens on std::string path; virtual ~ProxyInterface() = default; + //! returns name of the plugin + virtual QString getName() = 0; //! returns, whether the proxy is currently connected virtual bool connected() = 0; //! disconnects the handle diff --git a/mainwindow.cpp b/mainwindow.cpp index 6fb294a..bc2d745 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2,7 +2,6 @@ #include #include "./ui_mainwindow.h" #include -#include "networkthread.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -10,20 +9,17 @@ MainWindow::MainWindow(QWidget *parent) { qRegisterMetaType("httpflow"); current_session = new Session(); + // TODO: make configurable current_session->load("/tmp/littlesnitch.session"); + // TODO: use relative paths plugin_handler.loadPlugins(QDir("/home/end/projects/bigsnitch/build/plugins/")); - /* - thread = new QThread; - NetworkThread* worker = new NetworkThread(); - worker->moveToThread(thread); - connect(thread, SIGNAL (started()), worker, SLOT (process())); - //connect(worker, SIGNAL (error(QString)), this, SLOT (errorString(QString))); - connect(worker, SIGNAL (httpMessage(http::Flow)), current_session, SLOT (saveFlow(http::Flow)), Qt::QueuedConnection); - connect(worker, SIGNAL (httpMessage(http::Flow)), this, SLOT (updateHistory()), Qt::QueuedConnection); - thread->start(); -*/ + // TODO: fix error string + //QObject::connect(plugin_handler, SIGNAL (proxy_error(QString)), this, SLOT ( errorString(QString)), Qt::QueuedConnection); + QObject::connect(&plugin_handler, SIGNAL (proxy_message(http::Flow)), this, SLOT (updateHistory()), Qt::QueuedConnection); + QObject::connect(&plugin_handler, SIGNAL (proxy_message(http::Flow)), current_session, SLOT (saveFlow(http::Flow)), Qt::QueuedConnection); + history_model.update(current_session->getHistoryItems()); history_proxy.setSourceModel(&history_model); diff --git a/mainwindow.h b/mainwindow.h index ad10856..4460ccc 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -13,6 +13,7 @@ QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE +//! MainWindow class MainWindow : public QMainWindow { Q_OBJECT @@ -34,15 +35,23 @@ private: // hack for supplying the initial data to edit&resend std::tuple current_selection; public: + //! MainWindow constructor MainWindow(QWidget *parent = nullptr); ~MainWindow(); + //! opens the EditAndResend window void openEditAndResend(); public slots: + //! triggers a history update void updateHistory(); + //! right click menu void editMenuRequested(QPoint pos); + //! right click menu void edit2MenuRequested(QPoint pos); + //! right click menu void edit3MenuRequested(QPoint pos); + //! right click menu void edit4MenuRequested(QPoint pos); + //! right click menu void historyMenuRequested(QPoint pos); private slots: void on_selectionChange(const QItemSelection& selection); diff --git a/mitmaddon/requirements.txt b/mitmaddon/requirements.txt new file mode 100644 index 0000000..e61f104 --- /dev/null +++ b/mitmaddon/requirements.txt @@ -0,0 +1,3 @@ +mitmproxy +mitmdump +pyzmq diff --git a/mitmaddon/setup.py b/mitmaddon/setup.py new file mode 100644 index 0000000..5ab7ee8 --- /dev/null +++ b/mitmaddon/setup.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +from setuptools import setup, find_packages + +setup(name='bigsnitch-mitmaddon', + version='1.0', + packages=find_packages()) diff --git a/mitmaddon/tox.ini b/mitmaddon/tox.ini new file mode 100644 index 0000000..d37dabf --- /dev/null +++ b/mitmaddon/tox.ini @@ -0,0 +1,15 @@ +[tox] +skipsdist = true +envlist = py3 + +# Add environment to use the default python3 installation +[testenv:py3] +basepython = python3 + +[testenv] +usedevelop = true +deps = -r{toxinidir}/requirements.txt +setenv = + PYTHONDONTWRITEBYTECODE=1 +commands = + {envpython} sh ../test.sh diff --git a/pluginhandler.cpp b/pluginhandler.cpp index 0f0f5fd..4979246 100644 --- a/pluginhandler.cpp +++ b/pluginhandler.cpp @@ -15,6 +15,10 @@ bool PluginHandler::load(QString path) qDebug() << "loading plugin " << plugin; proxyhandler.loadPlugin(plugin); loaded_plugins += path; + + QObject::connect(plugin, SIGNAL (error(QString)), this, SIGNAL (proxy_error(QString)), Qt::QueuedConnection); + QObject::connect(plugin, SIGNAL (message(http::Flow)), this, SIGNAL (proxy_message(http::Flow)), Qt::QueuedConnection); + return true; } else { qDebug() << "fo " << loader.errorString(); diff --git a/pluginhandler.h b/pluginhandler.h index 498a482..f29e855 100644 --- a/pluginhandler.h +++ b/pluginhandler.h @@ -7,12 +7,25 @@ #include #include -class PluginHandler +//! PluginHandler controls all plugins. +//! Every different plugin interface, that got signals has to reference them here +//! Other parts of bigsnitch connect to them here. +class PluginHandler : public QObject { + Q_OBJECT private: QStringList loaded_plugins; http::ProxyHandler proxyhandler; public: + //! Loads a single plugin. bool load(QString path); + //! loads all plugins in a directory. void loadPlugins(QDir path); + +signals: + + //! error signal from ProxyInterface + void proxy_error(QString err); + //! message signal from ProxyInterface + void proxy_message(http::Flow flow); }; diff --git a/pluginlist.ui b/pluginlist.ui new file mode 100644 index 0000000..c6c71fc --- /dev/null +++ b/pluginlist.ui @@ -0,0 +1,70 @@ + + + Form + + + + 0 + 0 + 701 + 626 + + + + Form + + + + + + + 300 + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 300 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 10 + 10 + 281 + 21 + + + + + + + + + + diff --git a/plugins/mitmproxy/CMakeLists.txt b/plugins/mitmproxy/CMakeLists.txt index 25aa9c8..3d6fdd4 100644 --- a/plugins/mitmproxy/CMakeLists.txt +++ b/plugins/mitmproxy/CMakeLists.txt @@ -1,4 +1,7 @@ SET(CMAKE_AUTOMOC ON) + +find_package(cppzmq REQUIRED) + add_compile_definitions(IS_HTTP_PROXY_INTERFACE) add_library(mitmproxy_plugin SHARED mitmproxy_network.cpp mitmproxy_network.h mitmproxy.json) target_include_directories(mitmproxy_plugin PRIVATE ../../include/) diff --git a/plugins/mitmproxy/mitmproxy_network.cpp b/plugins/mitmproxy/mitmproxy_network.cpp index 49cbd73..232ceed 100644 --- a/plugins/mitmproxy/mitmproxy_network.cpp +++ b/plugins/mitmproxy/mitmproxy_network.cpp @@ -22,6 +22,11 @@ void mitmproxyPlugin::reconnect() this->connect(); } +QString mitmproxyPlugin::getName() +{ + return QString("mitmproxy bridge"); +} + void mitmproxyPlugin::process() { connect(); @@ -46,7 +51,7 @@ void mitmproxyPlugin::process() qDebug() << "received " << msg_type.c_str(); } else if(msg_type == "response") { qDebug() << "received " << msg_type.c_str(); - message(j); + emit message(j); } else if(msg_type == "requestheaders") { qDebug() << "received " << msg_type.c_str(); } else if(msg_type == "request") { @@ -55,8 +60,8 @@ void mitmproxyPlugin::process() qDebug() << "received " << msg_type.c_str(); } else if(msg_type == "error") { qDebug() << "received " << msg_type.c_str(); - // websocket events + emit error("error received"); } else if(msg_type == "websocket_handshake") { qDebug() << "received " << msg_type.c_str(); } else if(msg_type == "websocket_start") { diff --git a/plugins/mitmproxy/mitmproxy_network.h b/plugins/mitmproxy/mitmproxy_network.h index 16fd361..3b5b171 100644 --- a/plugins/mitmproxy/mitmproxy_network.h +++ b/plugins/mitmproxy/mitmproxy_network.h @@ -28,6 +28,8 @@ private: void reconnect(); public: + //! name of the plugin + QString getName() override; //! returns, whether the proxy is currently connected bool connected() override; //! disconnects the handle diff --git a/proxyhandler.cpp b/proxyhandler.cpp index 1d67792..3864cc7 100644 --- a/proxyhandler.cpp +++ b/proxyhandler.cpp @@ -15,13 +15,13 @@ bool http::ProxyHandler::loadPlugin(QObject *proxy) // TODO: get path from config or something inst->path = "tcp://127.0.0.1:12345"; QObject::connect(thread, SIGNAL (started()), proxy, SLOT (process())); - //QObject::connect(proxy, SIGNAL (error(QString)), this, SLOT (errorString(QString))); - //QObject::connect(proxy, SIGNAL (message(http::Flow)), current_session, SLOT (saveFlow(http::Flow)), Qt::QueuedConnection); - //QObject::connect(proxy, SIGNAL (message(http::Flow)), this, SLOT (updateHistory()), Qt::QueuedConnection); + QObject::connect(proxy, SIGNAL (error(QString)), this, SIGNAL (error(QString)), Qt::QueuedConnection); + QObject::connect(proxy, SIGNAL (message(http::Flow)), this, SIGNAL (message(http::Flow)), Qt::QueuedConnection); thread->start(); - //proxies.insert({"foo", inst, thread}); + auto name = inst->getName(); + proxies.insert({name, {inst, thread}}); return true; } diff --git a/proxyhandler.h b/proxyhandler.h index 846f442..d36890a 100644 --- a/proxyhandler.h +++ b/proxyhandler.h @@ -6,13 +6,19 @@ namespace http { -class ProxyHandler +class ProxyHandler : public QObject { + Q_OBJECT private: - std::map proxies; + std::map> proxies; + public: bool loadPlugin(QObject *proxy); QStringList getProxies(); + +signals: + void error(QString err); + void message(http::Flow flow); }; } diff --git a/test.sh b/test.sh index bba25dc..fd444c9 100755 --- a/test.sh +++ b/test.sh @@ -1,8 +1,8 @@ #!/bin/sh -mitmdump -k -p 1878 -s mitmaddon/littlesnitch.py & +mitmdump -k -p 1878 -s ./mitmaddon/bigsnitch.py & export mitmpid=$! -./build/littlesnitch & +./build/bin/bigsnitch & sleep 5 curl -s -x http://localhost:1878 -k https://yolo.jetzt > /dev/null diff --git a/tests/generic_tests.cpp b/tests/generic_tests.cpp index 1a05ebb..4548e11 100644 --- a/tests/generic_tests.cpp +++ b/tests/generic_tests.cpp @@ -1,8 +1,6 @@ #define CATCH_CONFIG_MAIN #include -#include "networkthread.h" - TEST_CASE( "1 eq 1", "[test]" ) { REQUIRE( 1 == 1 ); -} \ No newline at end of file +}