added addon stubs

This commit is contained in:
Tim Blume 2020-09-10 21:26:41 +02:00
parent 5eacc49a62
commit 739a6b7e06
12 changed files with 368 additions and 167 deletions

View file

@ -12,19 +12,6 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
# They need to be set before the find_package(Qt5 ...) call.
#if(ANDROID)
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
# set(ANDROID_EXTRA_LIBS
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
# endif()
#endif()
find_package(Qt5 COMPONENTS Widgets REQUIRED)
find_package(cppzmq REQUIRED)
find_package(nlohmann_json REQUIRED)
@ -39,6 +26,7 @@ add_executable(littlesnitch
httpflow.cpp
historymodel.cpp
editandresend.cpp
addonhandler.cpp
mainwindow.h
httpflow.h
networkthread.h
@ -46,6 +34,8 @@ add_executable(littlesnitch
includes.h
historymodel.h
editandresend.h
addonhandler.h
include/api.h
mainwindow.ui
editandresend.ui
)
@ -61,6 +51,11 @@ add_executable(littlesnitch_tests
target_include_directories(littlesnitch_tests PRIVATE /usr/local/include)
target_link_libraries(littlesnitch_tests PRIVATE Qt5::Widgets cppzmq sqlite3 Catch2::Catch2)
file(GLOB_RECURSE addonfiles addons/CMakeLists.txt)
foreach(loopvar IN ITEMS ${addonfiles})
include(${loopvar})
endforeach(loopvar)
include(CTest)
include(Catch)
catch_discover_tests(littlesnitch_tests)

66
addonhandler.cpp Normal file
View file

@ -0,0 +1,66 @@
#include "addonhandler.h"
#include <dlfcn.h>
AddonHandler::AddonHandler()
{
}
std::optional<std::string> AddonHandler::load(std::filesystem::path path)
{
// load library
void* lib = dlopen(path.c_str(), RTLD_LAZY);
if(!lib) {
qDebug() << "addon " << path.c_str() << " not loaded!";
return std::nullopt;
}
auto get_name = reinterpret_cast<const char*(*)()>(dlsym(lib, "get_name"));
std::string name;
try {
get_name();
} catch (...) {
return std::nullopt;
}
auto initialize = reinterpret_cast<const char*(*)()>(dlsym(lib, "initialize"));
try {
if(initialize) {
initialize();
}
} catch (...) {
return std::nullopt;
}
on_request.append(name, dlsym(lib, "on_request"));
on_response.append(name, dlsym(lib, "on_response"));
loaded_addon_paths.insert(std::make_pair(name, path));
loaded_addon_libs.insert(std::make_pair(name, lib));
return name;
}
void AddonHandler::unload(std::string name)
{
on_request.remove(name);
on_response.remove(name);
void* lib = loaded_addon_libs.find(name)->second;
auto deinitialize = reinterpret_cast<const char*(*)()>(dlsym(lib, "initialize"));
try {
if(deinitialize) {
deinitialize();
}
} catch (...) {
qDebug() << "deinitialize failed";
}
}
bool AddonHandler::isLoaded(std::string name)
{
return loaded_addon_libs.count(name);
}
std::map<std::string, std::filesystem::path> AddonHandler::loadedAddons()
{
return std::map<std::string, std::filesystem::path>();
}

61
addonhandler.h Normal file
View file

@ -0,0 +1,61 @@
#pragma once
#include <includes.h>
#include <dlfcn.h>
#include <functional>
template <typename T>
class DLWrapper {
private:
std::map<std::string, void*> funcs;
public:
void append(std::string name, void* ptr) {
if(ptr) {
funcs.insert({name, ptr});
}
}
void remove(std::string name) {
for(auto it = funcs.begin(); it != funcs.end(); ) {
if(it->first == name) {
it = funcs.erase(it);
return;
} else {
++it;
}
}
}
template<typename ...Args>
void operator()(Args... args) const {
for(auto fun : funcs) {
(T)(fun)(args...);
}
}
};
/*
the addon handler loads addon shared library objects and calls
in every loaded addon the implemented events, when they're implemented.
*/
class AddonHandler
{
private:
//list of loaded addons with library pointer
std::map<std::string, std::filesystem::path> loaded_addon_paths;
std::map<std::string, void*> loaded_addon_libs;
public:
AddonHandler();
// loads an addon and returns it's name, if successfully loaded
std::optional<std::string> load(std::filesystem::path path);
// unload an addon
void unload(std::string name);
// returns whether an addon with name is loaded
bool isLoaded(std::string name);
// returns the list of loaded addons (name, path)
std::map<std::string, std::filesystem::path> loadedAddons();
DLWrapper<void(*)(int)> on_request;
DLWrapper<void(*)(int)> on_response;
};

View file

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.9)
project(yararules VERSION 1.0.0 DESCRIPTION "addon for tagging using yara rules")
add_library(yararules SHARED ${CMAKE_CURRENT_LIST_DIR}/yararules.cpp)
set_target_properties(yararules PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1)
target_include_directories(yararules PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include/)

View file

@ -0,0 +1,5 @@
#pragma once
extern "C" const char* get_name() {
return "yararules";
}

View file

@ -1,5 +1,4 @@
#ifndef EDITANDRESEND_H
#define EDITANDRESEND_H
#pragma once
#include <QDialog>
@ -18,5 +17,3 @@ public:
private:
Ui::EditAndResend *ui;
};
#endif // EDITANDRESEND_H

View file

@ -6,13 +6,157 @@
<rect>
<x>0</x>
<y>0</y>
<width>459</width>
<height>354</height>
<width>897</width>
<height>570</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QFrame" name="frame">
<property name="geometry">
<rect>
<x>9</x>
<y>9</y>
<width>871</width>
<height>100</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Minimum">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>100</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>730</x>
<y>20</y>
<width>80</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>640</x>
<y>20</y>
<width>80</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QFrame" name="frame_2">
<property name="geometry">
<rect>
<x>10</x>
<y>120</y>
<width>781</width>
<height>404</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>400</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>1</width>
<height>1</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item row="0" column="0">
<widget class="QSplitter" name="splitter_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="sizeIncrement">
<size>
<width>1</width>
<height>1</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="plainTextEdit"/>
<widget class="QPlainTextEdit" name="plainTextEdit_3"/>
</widget>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="plainTextEdit_2"/>
<widget class="QPlainTextEdit" name="plainTextEdit_4"/>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>

View file

@ -5,26 +5,6 @@
#include <QSortFilterProxyModel>
#include <mutex>
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;
std::string request_http_version;
std::map<std::string, std::string> request_headers;
std::string request_content;
std::string response_http_version;
std::map<std::string, std::string> response_headers;
std::string response_content;
};
class HistoryModel : public QAbstractTableModel
{
Q_OBJECT

View file

@ -2,135 +2,8 @@
#include <includes.h>
/*
{
"flow": {
"client_conn": {
"address": [
"::1",
37570,
0,
0
],
"alpn_proto_negotiated": "http/1.1",
"cipher_name": "TLS_AES_256_GCM_SHA384",
"clientcert": null,
"id": "a1e82917-2d58-4b99-be9e-2b962bc499b2",
"mitmcert": "mitmcertstring",
"sni": "yolo.jetzt",
"timestamp_end": null,
"timestamp_start": 1597284668.6260498,
"timestamp_tls_setup": 1597284669.8449724,
"tls_established": true,
"tls_extensions": [...],
"tls_version": "TLSv1.3"
},
"error": null,
"id": "a6aa4e6e-ca31-4f58-bf47-2da7bfcf0000",
"intercepted": false,
"marked": false,
"metadata": {},
"mode": "transparent",
"request": {
"content": "",
"first_line_format": "relative",
"headers": [
[
"Host",
"yolo.jetzt"
],
[
"User-Agent",
"curl/7.68.0"
],
[
"Accept",
]
],
"host": "yolo.jetzt",
"http_version": "HTTP/1.1",
"is_replay": false,
"method": "GET",
"path": "/",
"port": 443,
"scheme": "https",
"timestamp_end": 1597284669.92817,
"timestamp_start": 1597284669.8761458
},
"response": null,
"server_conn": {
"address": [
"yolo.jetzt",
443
],
"alpn_proto_negotiated": "http/1.1",
"cert": "certstring",
"id": "50a3b79d-2912-45f3-991b-c03406a1018f",
"ip_address": [
"95.156.226.69",
443
],
"sni": "yolo.jetzt",
"source_address": [
"192.168.42.102",
44949
],
"timestamp_end": null,
"timestamp_start": 1597284669.2133315,
"timestamp_tcp_setup": 1597284669.2892282,
"timestamp_tls_setup": 1597284669.584602,
"tls_established": true,
"tls_version": "TLSv1.2",
"via": null
},
"type": "http",
"version": 7
},
"msg": "request"
}
*/
namespace http {
struct Request
{
std::string server_ip_address;
bool tls;
std::string content;
std::string scheme;
std::string method;
std::string host;
unsigned short port;
std::string http_version;
std::string path;
double timestamp_start;
double timestamp_end;
std::vector<std::tuple<std::string,std::string>> headers;
std::string error;
};
struct Response {
int status_code;
std::string http_version;
std::string reason;
std::string content;
double timestamp_start;
double timestamp_end;
std::vector<std::tuple<std::string,std::string>> headers;
};
struct Flow {
std::string uid;
Request request;
Response response;
};
inline void to_json(json& j, const Flow& flow) {}
inline void from_json(const json& j, Flow& flow) {

68
include/api.h Normal file
View file

@ -0,0 +1,68 @@
#pragma once
#include <iostream>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
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;
std::string request_http_version;
std::map<std::string, std::string> request_headers;
std::string request_content;
std::string response_http_version;
std::map<std::string, std::string> response_headers;
std::string response_content;
};
namespace http {
struct Request
{
std::string server_ip_address;
bool tls;
std::string content;
std::string scheme;
std::string method;
std::string host;
unsigned short port;
std::string http_version;
std::string path;
double timestamp_start;
double timestamp_end;
std::vector<std::tuple<std::string,std::string>> headers;
std::string error;
};
struct Response {
int status_code;
std::string http_version;
std::string reason;
std::string content;
double timestamp_start;
double timestamp_end;
std::vector<std::tuple<std::string,std::string>> headers;
};
struct Flow {
std::string uid;
Request request;
Response response;
};
}

View file

@ -1,5 +1,6 @@
#pragma once
#include <include/api.h>
#include <zmq.hpp>
#include <nlohmann/json.hpp>
#include <sqlite3.h>
@ -12,7 +13,7 @@
using json = nlohmann::json;
//major minor patch
#define LITTLESNITCH_VERSION 010
#define LITTLESNITCH_VERSION 100
template<typename T, typename K>
bool json_get(json j, T& value, K key) noexcept {

View file

@ -5,6 +5,7 @@
#include <session.h>
#include <includes.h>
#include <httpflow.h>
#include <editandresend.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@ -16,6 +17,7 @@ class MainWindow : public QMainWindow
private:
Ui::MainWindow *ui;
Ui::EditAndResend *ui_editandresend;
QThread* thread;
Session* current_session;
HistoryModel history_model;