This commit is contained in:
Tim Blume 2021-03-19 17:40:33 +01:00
parent a0ce50b7cd
commit f99ee2abde
11 changed files with 100 additions and 72 deletions

View file

@ -1,55 +1,3 @@
#pragma once #pragma once
#include <includes.h> #include <includes.h>
namespace http {
inline void to_json(json& j, const Flow& flow) {}
inline void from_json(const json& j, Flow& flow) {
//std::cout << std::setw(4) << j << "\n\n";
json j_flow;
if(!json_get(j, j_flow, "flow")) {
return;
}
json_get(j_flow, flow.uid, "id");
if(json j_request; json_get(j_flow, j_request, "request")) {
json_get(j_request, flow.request.tls, "server_conn", "tls_established");
json_get(j_request, flow.request.port, "port");
json_get(j_request, flow.request.host, "host");
json_get(j_request, flow.request.scheme, "scheme");
json_get(j_request, flow.request.path, "path");
json_get(j_request, flow.request.content, "content");
json_get(j_request, flow.request.method, "method");
json_get(j_request, flow.request.http_version, "http_version");
json_get(j_request, flow.request.timestamp_start, "timestamp_start");
json_get(j_request, flow.request.timestamp_end, "timestamp_end");
json j_headers;
if(json_get(j_request, j_headers, "headers")) {
for(auto& [k,v] : j_headers.items()) {
flow.request.headers.push_back(std::make_tuple(v.at(0), v.at(1)));
}
}
}
if(json j_response; json_get(j_flow, j_response, "response")) {
json_get(j_response, flow.response.status_code, "status_code");
json_get(j_response, flow.response.http_version, "http_version");
json_get(j_response, flow.response.reason, "reason");
json_get(j_response, flow.response.content, "content");
json_get(j_response, flow.response.timestamp_start, "timestamp_start");
json_get(j_response, flow.response.timestamp_end, "timestamp_end");
json j_headers;
if(json_get(j_response, j_headers, "headers")) {
for(auto& [k,v] : j_headers.items()) {
flow.response.headers.push_back(std::make_tuple(v.at(0), v.at(1)));
}
}
}
}
}
Q_DECLARE_METATYPE(http::Flow)

View file

@ -105,4 +105,53 @@ struct Flow {
Response response; Response response;
}; };
inline void to_json(json& j, const Flow& flow) {}
inline void from_json(const json& j, Flow& flow) {
//std::cout << std::setw(4) << j << "\n\n";
json j_flow;
if(!json_get(j, j_flow, "flow")) {
return;
}
json_get(j_flow, flow.uid, "id");
if(json j_request; json_get(j_flow, j_request, "request")) {
json_get(j_request, flow.request.tls, "server_conn", "tls_established");
json_get(j_request, flow.request.port, "port");
json_get(j_request, flow.request.host, "host");
json_get(j_request, flow.request.scheme, "scheme");
json_get(j_request, flow.request.path, "path");
json_get(j_request, flow.request.content, "content");
json_get(j_request, flow.request.method, "method");
json_get(j_request, flow.request.http_version, "http_version");
json_get(j_request, flow.request.timestamp_start, "timestamp_start");
json_get(j_request, flow.request.timestamp_end, "timestamp_end");
json j_headers;
if(json_get(j_request, j_headers, "headers")) {
for(auto& [k,v] : j_headers.items()) {
flow.request.headers.push_back(std::make_tuple(v.at(0), v.at(1)));
}
}
}
if(json j_response; json_get(j_flow, j_response, "response")) {
json_get(j_response, flow.response.status_code, "status_code");
json_get(j_response, flow.response.http_version, "http_version");
json_get(j_response, flow.response.reason, "reason");
json_get(j_response, flow.response.content, "content");
json_get(j_response, flow.response.timestamp_start, "timestamp_start");
json_get(j_response, flow.response.timestamp_end, "timestamp_end");
json j_headers;
if(json_get(j_response, j_headers, "headers")) {
for(auto& [k,v] : j_headers.items()) {
flow.response.headers.push_back(std::make_tuple(v.at(0), v.at(1)));
}
}
}
} }
}
Q_DECLARE_METATYPE(http::Flow)

View file

@ -10,9 +10,11 @@ namespace http {
//! Interface for implementing proxies //! Interface for implementing proxies
/*! /*!
Interface for implementing proxies Interface for implementing proxies
There are no signals, because apparently Qt Plugins do not support interfaces, which inherit from QObject.
(it will fail upon loading the plugin)
*/ */
class ProxyInterface : public QObject { class ProxyInterface {
Q_OBJECT
public: public:
virtual ~ProxyInterface() = default; virtual ~ProxyInterface() = default;
//! called in a custom thread, may block. //! called in a custom thread, may block.
@ -22,10 +24,9 @@ public:
//! disconnects the handle //! disconnects the handle
virtual void disconnect() = 0; virtual void disconnect() = 0;
// options/settings // options/settings
signals: std::function<void()> finished;
virtual void finished(); std::function<void(QString)> error;
virtual void error(QString err); std::function<void(http::Flow flow)> message;
virtual void message(http::Flow flow);
}; };
} }

View file

@ -12,6 +12,9 @@ MainWindow::MainWindow(QWidget *parent)
current_session = new Session(); current_session = new Session();
current_session->load("/tmp/littlesnitch.session"); current_session->load("/tmp/littlesnitch.session");
plugin_handler.loadPlugins(QDir("/home/end/projects/bigsnitch/build/plugins/"));
/*
thread = new QThread; thread = new QThread;
NetworkThread* worker = new NetworkThread(); NetworkThread* worker = new NetworkThread();
worker->moveToThread(thread); worker->moveToThread(thread);
@ -20,7 +23,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(worker, SIGNAL (httpMessage(http::Flow)), current_session, SLOT (saveFlow(http::Flow)), Qt::QueuedConnection); 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); connect(worker, SIGNAL (httpMessage(http::Flow)), this, SLOT (updateHistory()), Qt::QueuedConnection);
thread->start(); thread->start();
*/
history_model.update(current_session->getHistoryItems()); history_model.update(current_session->getHistoryItems());
history_proxy.setSourceModel(&history_model); history_proxy.setSourceModel(&history_model);

View file

@ -7,6 +7,8 @@
#include <httpflow.h> #include <httpflow.h>
#include <editandresend.h> #include <editandresend.h>
#include <pluginhandler.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
QT_END_NAMESPACE QT_END_NAMESPACE
@ -23,6 +25,8 @@ private:
HistoryModel history_model; HistoryModel history_model;
HistoryProxyModel history_proxy; HistoryProxyModel history_proxy;
PluginHandler plugin_handler;
QAction* editAndResendMenu; QAction* editAndResendMenu;
QAction* hideHistoryColumn; QAction* hideHistoryColumn;
QAction* showHistoryColumn; QAction* showHistoryColumn;

View file

@ -3,7 +3,7 @@
/* /*
const auto staticInstances = QPluginLoader::staticInstances(); const auto staticInstances = QPluginLoader::staticInstances();
for (QObject *plugin : staticInstances) for (QObject *plugin : staticInstances)
populateMenus(plugin); populateMenus(plugin);
*/ */
@ -12,17 +12,22 @@ bool PluginHandler::load(QString path)
QPluginLoader loader(path); QPluginLoader loader(path);
QObject *plugin = loader.instance(); QObject *plugin = loader.instance();
if (plugin) { if (plugin) {
qDebug() << "loading plugin " << plugin;
proxyhandler.loadPlugin(plugin); proxyhandler.loadPlugin(plugin);
loaded_plugins += path; loaded_plugins += path;
return true; return true;
} else {
qDebug() << "fo " << loader.errorString();
} }
return false; return false;
} }
void PluginHandler::loadPlugins(QDir path) void PluginHandler::loadPlugins(QDir path)
{ {
qDebug() << "loading plugins from " << path;
const auto entryList = path.entryList(QDir::Files); const auto entryList = path.entryList(QDir::Files);
for (const QString &fileName : entryList) { for (const QString &fileName : entryList) {
qDebug() << "loading " << fileName;
load(path.absoluteFilePath(fileName)); load(path.absoluteFilePath(fileName));
} }
} }

View file

@ -1,4 +1,5 @@
add_library(mitmproxy_plugin MODULE mitmproxy_network.cpp mitmproxy_network.h) SET(CMAKE_AUTOMOC ON)
add_library(mitmproxy_plugin MODULE mitmproxy_network.cpp mitmproxy_network.h mitmproxy.json)
target_include_directories(mitmproxy_plugin PRIVATE ../../include/) target_include_directories(mitmproxy_plugin PRIVATE ../../include/)
target_link_libraries(mitmproxy_plugin PRIVATE Qt5::Core cppzmq) target_link_libraries(mitmproxy_plugin PRIVATE Qt5::Core cppzmq)
set_target_properties(mitmproxy_plugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_DIR}) set_target_properties(mitmproxy_plugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_DIR})

View file

@ -9,7 +9,7 @@ void mitmproxyPlugin::connect()
socket->bind(this->path); socket->bind(this->path);
} catch (zmq::error_t err) { } catch (zmq::error_t err) {
qDebug() << "failed binding socket" << err.what(); qDebug() << "failed binding socket" << err.what();
emit error(err.what()); error(err.what());
throw; throw;
}; };
is_connected = true; is_connected = true;
@ -47,7 +47,7 @@ void mitmproxyPlugin::process(std::string path)
qDebug() << "received " << msg_type.c_str(); qDebug() << "received " << msg_type.c_str();
} else if(msg_type == "response") { } else if(msg_type == "response") {
qDebug() << "received " << msg_type.c_str(); qDebug() << "received " << msg_type.c_str();
//emit httpMessage(j); message(j);
} else if(msg_type == "requestheaders") { } else if(msg_type == "requestheaders") {
qDebug() << "received " << msg_type.c_str(); qDebug() << "received " << msg_type.c_str();
} else if(msg_type == "request") { } else if(msg_type == "request") {
@ -78,6 +78,11 @@ void mitmproxyPlugin::process(std::string path)
} }
} }
bool mitmproxyPlugin::connected()
{
return is_connected;
}
void mitmproxyPlugin::disconnect() void mitmproxyPlugin::disconnect()
{ {
delete socket; delete socket;

View file

@ -3,14 +3,20 @@
#include "api.h" #include "api.h"
#include "proxyinterface.h" #include "proxyinterface.h"
#include <QObject> #include <QObject>
#include <QtPlugin>
#include <set> #include <set>
#include <zmq.hpp> #include <zmq.hpp>
class mitmproxyPlugin : public http::ProxyInterface /*
mitmproxy base plugin
This plugin implements the interface for the basic mitmproxy plugin.
*/
class mitmproxyPlugin : public QObject, http::ProxyInterface
{ {
Q_OBJECT Q_OBJECT
Q_PLUGIN_METADATA(IID "bigsnitch.api.HTTPProxyInterface/100" FILE "mitmproxy.json") Q_PLUGIN_METADATA(IID HTTPProxyInterfaceIID FILE "mitmproxy.json")
Q_INTERFACES(http::ProxyInterface) Q_INTERFACES(http::ProxyInterface)
private: private:
std::set<std::string> received; std::set<std::string> received;
@ -29,9 +35,4 @@ public:
//! disconnects the handle //! disconnects the handle
void disconnect() override; void disconnect() override;
// options/settings // options/settings
signals:
//void finished();
//void error(QString err);
//void message(http::Flow flow);
}; };

View file

@ -1,4 +1,5 @@
#include "proxyhandler.h" #include "proxyhandler.h"
#include <QThread>
bool http::ProxyHandler::loadPlugin(QObject *proxy) bool http::ProxyHandler::loadPlugin(QObject *proxy)
{ {
@ -8,7 +9,17 @@ bool http::ProxyHandler::loadPlugin(QObject *proxy)
} }
qDebug("loading proxy"); qDebug("loading proxy");
proxies.insert({"foo", inst});
auto thread = new QThread;
proxy->moveToThread(thread);
QObject::connect(thread, SIGNAL (started()), proxy, SLOT (process()));
//connect(worker, SIGNAL (error(QString)), this, SLOT (errorString(QString)));
QObject::connect(worker, SIGNAL (httpMessage(http::Flow)), current_session, SLOT (saveFlow(http::Flow)), Qt::QueuedConnection);
QObject::connect(worker, SIGNAL (httpMessage(http::Flow)), this, SLOT (updateHistory()), Qt::QueuedConnection);
thread->start();
proxies.insert({"foo", inst, thread});
return true; return true;
} }

View file

@ -9,7 +9,7 @@ namespace http {
class ProxyHandler class ProxyHandler
{ {
private: private:
std::map<std::string, ProxyInterface*> proxies; std::map<std::string, ProxyInterface*, QThread*> proxies;
public: public:
bool loadPlugin(QObject *proxy); bool loadPlugin(QObject *proxy);
QStringList getProxies(); QStringList getProxies();