This commit is contained in:
Tim Blume 2020-08-26 20:58:36 +02:00
parent 6a650ef1e8
commit ea0a5e74f2
11 changed files with 224 additions and 152 deletions

View file

@ -36,11 +36,13 @@ add_executable(littlesnitch
networkthread.cpp networkthread.cpp
session.cpp session.cpp
httpflow.cpp httpflow.cpp
historymodel.cpp
mainwindow.h mainwindow.h
httpflow.h httpflow.h
networkthread.h networkthread.h
session.h session.h
includes.h includes.h
historymodel.h
mainwindow.ui mainwindow.ui
) )

78
historymodel.cpp Normal file
View file

@ -0,0 +1,78 @@
#include "historymodel.h"
#include <QDateTime>
HistoryModel::HistoryModel(QObject *parent)
{
Q_UNUSED(parent);
}
int HistoryModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if(current_items) {
return current_items->size();
}
return 0;
}
int HistoryModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 7;
}
QVariant HistoryModel::data(const QModelIndex &index, int role) const
{
if(role != Qt::DisplayRole) {
return QVariant();
}
if(!current_items) {
return QVariant();
}
int row = index.row();
int col = index.column();
try {
auto item = current_items->at(row);
switch(col) {
case 0: {
return QString::number(item.id);
}
case 1: {
QDateTime timestamp;
timestamp.setTime_t(item.timestamp);
return timestamp.toString(Qt::SystemLocaleShortDate);
}
case 2: {
std::string url = item.scheme + "://" + item.host + ":" + std::to_string(item.port) + item.path;
return QString::fromStdString(url);
}
case 3: {
return item.status_code;
}
case 4: {
return QString::fromStdString(item.reason);
}
case 5: {
return item.rtt;
}
case 6:{
return QString::number(item.size);
}
}
} catch (std::out_of_range const& exc) {
qDebug() << "historymodel data " << exc.what();
}
return QVariant();
}
void HistoryModel::update(std::vector<HistoryItem> *items)
{
if(current_items) {
delete current_items;
}
current_items = items;
}

31
historymodel.h Normal file
View file

@ -0,0 +1,31 @@
#pragma once
#include <includes.h>
#include <QAbstractTableModel>
struct HistoryItem {
int id = -1;
double timestamp = 0;
std::string method;
std::string scheme;
std::string host;
unsigned short port = 0;
std::string path;
int status_code = 0;
std::string reason;
double rtt = 0.0;
size_t size = 0;
};
class HistoryModel : public QAbstractTableModel
{
Q_OBJECT
private:
std::vector<HistoryItem>* current_items = nullptr;
public:
HistoryModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void update(std::vector<HistoryItem>* items);
};

View file

@ -131,20 +131,6 @@ struct Flow {
Response response; Response response;
}; };
struct HistoryItem {
int id;
double timestamp;
std::string method;
std::string scheme;
std::string host;
unsigned short port;
std::string path;
int status_code;
std::string reason;
double rtt;
int size;
};
inline void to_json(json& j, const Flow& flow) {} inline void to_json(json& j, const Flow& flow) {}
inline void from_json(const json& j, Flow& flow) { inline void from_json(const json& j, Flow& flow) {

View file

@ -1,5 +1,5 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <historymodel.h>
#include "./ui_mainwindow.h" #include "./ui_mainwindow.h"
#include <QtGui> #include <QtGui>
#include "networkthread.h" #include "networkthread.h"
@ -21,19 +21,12 @@ MainWindow::MainWindow(QWidget *parent)
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());
ui->setupUi(this); ui->setupUi(this);
ui->historyHTTPTable->setShowGrid(true); ui->historyHTTPTable->setShowGrid(true);
ui->historyHTTPTable->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->historyHTTPTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->historyHTTPTable->setColumnCount(7); ui->historyHTTPTable->setModel(&history_model);
ui->historyHTTPTable->setRowCount(1);
/*
ui->historyHTTPTable->setItem(0,0,new QTableWidgetItem(QString::number(data.index)));
ui->historyHTTPTable->setItem(0,1,new QTableWidgetItem(QString::fromStdString(data.method)));
ui->historyHTTPTable->setItem(0,2,new QTableWidgetItem(QString::fromStdString(data.url)));
ui->historyHTTPTable->setItem(0,3,new QTableWidgetItem(QString::number(data.ttl)));
ui->historyHTTPTable->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
*/
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -42,28 +35,7 @@ MainWindow::~MainWindow()
} }
void MainWindow::updateHistory() { void MainWindow::updateHistory() {
int i = 0; history_model.update(current_session->getHistoryItems());
auto items = current_session->getHistoryItems();
for(auto& item : *items) {
ui->historyHTTPTable->setRowCount(i+1);
int j = 0;
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::number(item.id)));
QDateTime timestamp;
timestamp.setTime_t(item.timestamp);
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(timestamp.toString(Qt::SystemLocaleShortDate)));
std::string url = item.scheme + "://" + item.host + ":" + std::to_string(item.port) + item.path;
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::fromStdString(url)));
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.status_code));
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::fromStdString(item.reason)));
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.rtt));
ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.size));
i++;
}
delete items;
//ui->historyHTTPTable->setItem(0,0,new QTableWidgetItem(QString::fromStdString(flow.request.server_conn_id)));
//ui->historyHTTPTable->setItem(0,1,new QTableWidgetItem(QString::fromStdString(flow.request.method)));
//ui->historyHTTPTable->setItem(0,2,new QTableWidgetItem(QString::fromStdString(flow.request.host)));
//ui->historyHTTPTable->setItem(0,3,new QTableWidgetItem(QString::number(data.ttl)));
ui->historyHTTPTable->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); ui->historyHTTPTable->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
} }
@ -71,3 +43,7 @@ void MainWindow::on_searchEdit_textEdited(const QString &arg1)
{ {
emit updateHistory(); emit updateHistory();
} }
void MainWindow::on_historyHTTPTable_cellClicked(int row, int column)
{
}

View file

@ -18,6 +18,7 @@ private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
QThread* thread; QThread* thread;
Session* current_session; Session* current_session;
HistoryModel history_model;
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
@ -25,4 +26,5 @@ public slots:
void updateHistory(); void updateHistory();
private slots: private slots:
void on_searchEdit_textEdited(const QString &arg1); void on_searchEdit_textEdited(const QString &arg1);
void on_historyHTTPTable_cellClicked(int row, int column);
}; };

View file

@ -73,7 +73,7 @@
<height>100</height> <height>100</height>
</size> </size>
</property> </property>
<widget class="QWidget" name="tabWidget_2Page1" native="true"> <widget class="QWidget" name="tabWidget_2Page1">
<attribute name="title"> <attribute name="title">
<string/> <string/>
</attribute> </attribute>
@ -110,7 +110,7 @@
<height>200</height> <height>200</height>
</size> </size>
</property> </property>
<widget class="QWidget" name="tabWidgetPage1_2" native="true"> <widget class="QWidget" name="tabWidgetPage1_2">
<attribute name="title"> <attribute name="title">
<string/> <string/>
</attribute> </attribute>
@ -163,7 +163,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>800</width> <width>800</width>
<height>100</height> <height>200</height>
</size> </size>
</property> </property>
<property name="layoutDirection"> <property name="layoutDirection">
@ -179,97 +179,93 @@
<attribute name="title"> <attribute name="title">
<string/> <string/>
</attribute> </attribute>
<widget class="QTableWidget" name="historyHTTPTable"> <layout class="QFormLayout" name="formLayout">
<property name="geometry"> <item row="1" column="0">
<rect> <widget class="QComboBox" name="searchBox">
<x>9</x> <property name="sizePolicy">
<y>40</y> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<width>769</width> <horstretch>0</horstretch>
<height>109</height> <verstretch>0</verstretch>
</rect> </sizepolicy>
</property> </property>
<property name="alternatingRowColors"> <item>
<bool>true</bool> <property name="text">
</property> <string>all</string>
<property name="selectionBehavior"> </property>
<enum>QAbstractItemView::SelectRows</enum> </item>
</property> <item>
<property name="gridStyle"> <property name="text">
<enum>Qt::SolidLine</enum> <string>ID</string>
</property> </property>
<property name="sortingEnabled"> </item>
<bool>true</bool> <item>
</property> <property name="text">
<attribute name="verticalHeaderVisible"> <string>Method</string>
<bool>false</bool> </property>
</attribute> </item>
</widget> <item>
<widget class="QLineEdit" name="searchEdit"> <property name="text">
<property name="geometry"> <string>URL</string>
<rect> </property>
<x>101</x> </item>
<y>9</y> <item>
<width>142</width> <property name="text">
<height>25</height> <string>Code</string>
</rect> </property>
</property> </item>
</widget> <item>
<widget class="QComboBox" name="searchBox"> <property name="text">
<property name="geometry"> <string>Tags</string>
<rect> </property>
<x>9</x> </item>
<y>9</y> </widget>
<width>86</width>
<height>25</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>all</string>
</property>
</item> </item>
<item> <item row="1" column="1">
<property name="text"> <widget class="QLineEdit" name="searchEdit"/>
<string>ID</string>
</property>
</item> </item>
<item> <item row="2" column="0" colspan="2">
<property name="text"> <widget class="QTableView" name="historyHTTPTable">
<string>Method</string> <property name="sizePolicy">
</property> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="verticalHeaderDefaultSectionSize">
<number>19</number>
</attribute>
</widget>
</item> </item>
<item> </layout>
<property name="text">
<string>URL</string>
</property>
</item>
<item>
<property name="text">
<string>Code</string>
</property>
</item>
<item>
<property name="text">
<string>Tags</string>
</property>
</item>
</widget>
</widget> </widget>
</widget> </widget>
</widget> </widget>
</item> </item>
</layout> </layout>
<zorder>tabWidget</zorder>
<zorder>widget_2</zorder>
<zorder>splitter_2</zorder>
<zorder>widget</zorder>
<zorder>splitter</zorder>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">
@ -277,7 +273,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>818</width> <width>818</width>
<height>22</height> <height>20</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">

View file

@ -9,6 +9,7 @@ class NetworkThread : public QObject
{ {
Q_OBJECT Q_OBJECT
private: private:
std::set<std::string> received;
zmq::context_t context; zmq::context_t context;
zmq::socket_t *socket; zmq::socket_t *socket;
std::set<std::string> accepted_flows; std::set<std::string> accepted_flows;

View file

@ -133,15 +133,16 @@ std::optional<std::string> Session::getSetting(std::string key) {
return std::nullopt; return std::nullopt;
} }
std::vector<http::HistoryItem>* Session::getHistoryItems() { std::vector<HistoryItem>* Session::getHistoryItems() {
// todo check reset return code
sqlite3_reset(stmt_get_all_history); sqlite3_reset(stmt_get_all_history);
std::vector<http::HistoryItem>* result = new std::vector<http::HistoryItem>(); std::vector<HistoryItem>* result = new std::vector<HistoryItem>();
auto rc = sqlite3_step(stmt_get_all_history); auto rc = sqlite3_step(stmt_get_all_history);
while(rc == SQLITE_ROW) { while(rc == SQLITE_ROW) {
int j = 0; int j = 0;
http::HistoryItem i; HistoryItem i;
i.id = sqlite3_column_int(stmt_get_all_history, j++); i.id = sqlite3_column_int(stmt_get_all_history, j++);
i.timestamp = sqlite3_column_double(stmt_get_all_history, j++); i.timestamp = sqlite3_column_double(stmt_get_all_history, j++);
i.method = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); i.method = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++));

View file

@ -3,6 +3,7 @@
#include <QObject> #include <QObject>
#include <includes.h> #include <includes.h>
#include <httpflow.h> #include <httpflow.h>
#include <historymodel.h>
#include <optional> #include <optional>
class Session : public QObject class Session : public QObject
@ -103,7 +104,7 @@ public:
void unload(); void unload();
bool isLoaded(); bool isLoaded();
std::optional<std::string> getSetting(std::string key); std::optional<std::string> getSetting(std::string key);
std::vector<http::HistoryItem>* getHistoryItems(); std::vector<HistoryItem>* getHistoryItems();
public slots: public slots:
int saveRequest(http::Flow flow); int saveRequest(http::Flow flow);
int saveRequestHeader(std::string key, std::string value, int id); int saveRequestHeader(std::string key, std::string value, int id);

26
test.sh
View file

@ -1,19 +1,17 @@
#!/bin/sh #!/bin/sh
mitmdump -k -p 8888 -s mitmaddon/littlesnitch.py & mitmdump -k -p 1878 -s mitmaddon/littlesnitch.py &
export mitmpid=$!
./build/littlesnitch & ./build/littlesnitch &
sleep 1 sleep 5
echo "sending requests" curl -x http://localhost:1878 -k https://yolo.jetzt
curl -x http://localhost:8888 -k https://blog.fefe.de
curl -x http://localhost:8888 -k https://blog.fefe.de
curl -x http://localhost:8888 -k https://blog.fefe.de
killall mitmdump
sleep 1
killall mitmdump
sleep 2 sleep 2
killall mitmdump curl -x http://localhost:1878 -k https://get.yolo.jetzt
sleep 3
killall mitmdump sleep 2
killall mitmdump kill -9 $mitmpid
kill -9 $mitmpid
sleep 2
kill -9 $mitmpid
kill -9 $mitmpid