progress
This commit is contained in:
677
src/main.c
677
src/main.c
@@ -17,10 +17,11 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dirent.h> // library für Interaktion mit Ordnerstrukturen
|
#include <dirent.h> // library für Interaktion mit Ordnerstrukturen
|
||||||
#include <sys/stat.h> // library für is_directory: Unterscheidung zwischen Dateien und Ordnern
|
#include <sys/stat.h> // library für is_directory: Unterscheidung zwischen Dateien und Ordnern
|
||||||
|
#include <time.h> // um aktuelle Zeit zu generieren
|
||||||
|
|
||||||
#define MAX_LINE_LENGTH_BUF 2048
|
#define MAX_LINE_LENGTH_BUF 2048
|
||||||
#define INITIAL_ENTRIES 1000 // globale Variable zur initialen Speicherallokation in allocate_initial_memory(). Wird falls nötig um GROWTH_FACTOR erweitert
|
#define INITIAL_ENTRIES 1000 // globale Variable zur initialen Speicherallokation in allocate_initial_memory(). Wird falls nötig um GROWTH_FACTOR erweitert
|
||||||
#define GROWTH_FACTOR 2 // wird in mem_expand_dynamically() genutzt, um den Speicher zu vergrößern
|
#define GROWTH_FACTOR 1.1 // wird in mem_expand_dynamically() genutzt, um den Speicher zu vergrößern
|
||||||
#define MAX_FILTERS 100
|
#define MAX_FILTERS 100
|
||||||
#define MAX_REQUEST_LENGTH 1024 // das hohe Limit ist erforderlich, da teilweise ausufernde JSON-Requests in nginx auflaufen können.
|
#define MAX_REQUEST_LENGTH 1024 // das hohe Limit ist erforderlich, da teilweise ausufernde JSON-Requests in nginx auflaufen können.
|
||||||
#define TOP_X 20 // definiert die Anzahl der Einträge, die in den Top-Listen angezeigt werden sollen
|
#define TOP_X 20 // definiert die Anzahl der Einträge, die in den Top-Listen angezeigt werden sollen
|
||||||
@@ -51,6 +52,8 @@ struct log_entry {
|
|||||||
struct simple_time time;
|
struct simple_time time;
|
||||||
char referrer[128];
|
char referrer[128];
|
||||||
char user_agent[256];
|
char user_agent[256];
|
||||||
|
char source_file[256];
|
||||||
|
char parsing_timestamp[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Struktur für einen Status-Filtereintrag mit Inhalt & Modus
|
// Struktur für einen Status-Filtereintrag mit Inhalt & Modus
|
||||||
@@ -222,7 +225,7 @@ void mem_expand_dynamically() {
|
|||||||
int old_max = max_entries;
|
int old_max = max_entries;
|
||||||
max_entries = max_entries * GROWTH_FACTOR;
|
max_entries = max_entries * GROWTH_FACTOR;
|
||||||
|
|
||||||
printf("Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %d\n", old_max, max_entries, GROWTH_FACTOR);
|
printf("Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
|
||||||
|
|
||||||
struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry));
|
struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry));
|
||||||
|
|
||||||
@@ -250,6 +253,20 @@ void allocate_initial_memory() {
|
|||||||
printf("Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
printf("Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_current_timestamp(char* buffer, int buffer_size) {
|
||||||
|
time_t raw_time;
|
||||||
|
struct tm *time_info;
|
||||||
|
|
||||||
|
time(&raw_time);
|
||||||
|
time_info = localtime(&raw_time);
|
||||||
|
|
||||||
|
if (time_info != NULL) {
|
||||||
|
strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", time_info);
|
||||||
|
} else {
|
||||||
|
snprintf(buffer, buffer_size, "UNKNOWN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hilfsfunktion zum Prüfen, ob es sich beim Pfad um ein Directory handelt - für rekursives Parsen
|
// Hilfsfunktion zum Prüfen, ob es sich beim Pfad um ein Directory handelt - für rekursives Parsen
|
||||||
int is_directory(char* path) {
|
int is_directory(char* path) {
|
||||||
struct stat path_stat;
|
struct stat path_stat;
|
||||||
@@ -293,7 +310,7 @@ Fehleranfällig, wenn das Logformat nicht dem Standard entspricht - das gilt abe
|
|||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
*/
|
*/
|
||||||
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
||||||
int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer auf die Zeile und einen Index entgegen - dieser ist anfangs 0 (globale Variable) und wird pro Eintrag inkrementiert
|
int parse_simple_log_line(char* line, int entry_index, char* source_file) { // Nimmt den Pointer auf die Zeile und einen Index entgegen - dieser ist anfangs 0 (globale Variable) und wird pro Eintrag inkrementiert
|
||||||
char* current_pos = line;
|
char* current_pos = line;
|
||||||
// leere Zeichen am Anfang überspringen
|
// leere Zeichen am Anfang überspringen
|
||||||
current_pos = skip_spaces(current_pos);
|
current_pos = skip_spaces(current_pos);
|
||||||
@@ -386,7 +403,6 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au
|
|||||||
|
|
||||||
current_pos = skip_spaces(current_pos);
|
current_pos = skip_spaces(current_pos);
|
||||||
// Weiter mit dem String innerhalb "", aus dem die HTTP-Methode und der URL-Pfad zu entnehmen ist
|
// Weiter mit dem String innerhalb "", aus dem die HTTP-Methode und der URL-Pfad zu entnehmen ist
|
||||||
// Enhanced parsing to handle malformed binary requests gracefully
|
|
||||||
if (*current_pos == '"') {
|
if (*current_pos == '"') {
|
||||||
current_pos++;
|
current_pos++;
|
||||||
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
||||||
@@ -433,8 +449,8 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in NGINX treten gelegentlich fehlerhafte Requests auf, die binäre Daten übersenden, sodass normales parsen nicht möglich ist.
|
// in NGINX treten gelegentlich fehlerhafte Requests auf, die binäre Daten übersenden, sodass normales parsen nicht möglich ist.
|
||||||
// der entsprechende Eintrag wird daher mit dem String "MALFORMED" repräsentiert
|
// der entsprechende Eintrag wird daher mit dem String "ATYPICAL" repräsentiert
|
||||||
strcpy(all_entries[entry_index].request_method, "MALFORMED");
|
strcpy(all_entries[entry_index].request_method, "ATYPICAL");
|
||||||
|
|
||||||
// Read entire quoted content into url_path for forensic analysis
|
// Read entire quoted content into url_path for forensic analysis
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -452,8 +468,6 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*current_pos == '"') current_pos++;
|
if (*current_pos == '"') current_pos++;
|
||||||
|
|
||||||
printf("INFO: Fehlerhaften Logeintrag entdeckt, speichere mit MALFORMED-Eintrag.\n");
|
|
||||||
}
|
}
|
||||||
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-"
|
||||||
// ^
|
// ^
|
||||||
@@ -512,30 +526,29 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au
|
|||||||
printf("ERROR: Unerwartetes Log-Format. Lediglich mit standard-nginx-accesslog kompatibel.\nDer Fehler ist beim Prüfen des User-Agent aufgetreten. Dieser steht innerhalb eines Strings:\n\"Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);\"\n\n");
|
printf("ERROR: Unerwartetes Log-Format. Lediglich mit standard-nginx-accesslog kompatibel.\nDer Fehler ist beim Prüfen des User-Agent aufgetreten. Dieser steht innerhalb eines Strings:\n\"Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);\"\n\n");
|
||||||
cleanup_and_exit();
|
cleanup_and_exit();
|
||||||
}
|
}
|
||||||
return 1;
|
get_current_timestamp(all_entries[entry_index].parsing_timestamp, sizeof(all_entries[entry_index].parsing_timestamp));
|
||||||
|
// Dateinamen in das Feld schreiben - strncpy um Buffer overflow zu verhindern
|
||||||
|
strncpy(all_entries[entry_index].source_file, source_file, sizeof(all_entries[entry_index].source_file) - 1);
|
||||||
|
// strncpy setzt keinen Nullterminator, dieser muss am Ende eingefügt werden
|
||||||
|
all_entries[entry_index].source_file[sizeof(all_entries[entry_index].source_file) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
void load_regular_file(char* filename) {
|
void load_regular_file(char* filename) {
|
||||||
FILE* file = fopen(filename, "r");
|
FILE* file = fopen(filename, "r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
|
printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Lade Datei: %s\n", filename);
|
printf("Lade Datei: %s\n", filename);
|
||||||
char line[MAX_LINE_LENGTH_BUF];
|
char line[MAX_LINE_LENGTH_BUF];
|
||||||
int loaded_from_this_file = 0;
|
int loaded_from_this_file = 0;
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), file) != NULL) {
|
while (fgets(line, sizeof(line), file) != NULL) {
|
||||||
mem_expand_dynamically();
|
mem_expand_dynamically();
|
||||||
|
if (parse_simple_log_line(line, total_entries, filename)) {
|
||||||
if (parse_simple_log_line(line, total_entries)) {
|
|
||||||
total_entries++;
|
total_entries++;
|
||||||
loaded_from_this_file++;
|
loaded_from_this_file++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
printf(" -> %d Einträge aus dieser Datei geladen.\n", loaded_from_this_file);
|
printf(" -> %d Einträge aus dieser Datei geladen.\n", loaded_from_this_file);
|
||||||
}
|
}
|
||||||
@@ -960,276 +973,24 @@ int count_filtered_entries() {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_status() {
|
// notwendig, um konformes Timestamp-Format aus simple_time struct zu generieren. Unterstützt derzeit nur UTC
|
||||||
printf("\n========== SYSTEM STATUS ==========\n");
|
|
||||||
|
|
||||||
if (total_entries > 0) {
|
|
||||||
printf("✅ Log-Daten: %d Einträge geladen\n", total_entries);
|
|
||||||
printf(" Speicherverbrauch: %lu Bytes (%d Einträge Kapazität)\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
|
|
||||||
} else {
|
|
||||||
printf("❌ Keine Log-Daten geladen\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n🔍 Aktive Filter-Logik:\n");
|
|
||||||
int total_filters = filters.status_count + filters.method_count + filters.ip_count + filters.time_count + filters.user_agent_count + filters.url_count;
|
|
||||||
|
|
||||||
if (total_filters == 0) {
|
|
||||||
printf(" Keine Filter gesetzt → alle Einträge werden angezeigt\n");
|
|
||||||
} else {
|
|
||||||
printf(" Modus: %s\n", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf(" Regel: Ausschlussfilter (!) haben Vorrang, dann Einschlussfilter\n");
|
|
||||||
printf("\n Filter-Ausdruck:\n");
|
|
||||||
|
|
||||||
if (filters.status_count > 0) {
|
|
||||||
printf(" Status: ");
|
|
||||||
|
|
||||||
int excludes = 0, includes = 0;
|
|
||||||
for (int i = 0; i < filters.status_count; i++) {
|
|
||||||
if (filters.status_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
|
||||||
else includes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ausschlussfilter (immer im ODER-Modus)
|
|
||||||
if (excludes > 0) {
|
|
||||||
printf("!(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.status_count; i++) {
|
|
||||||
if (filters.status_filters[i].mode == FILTER_EXCLUDE) {
|
|
||||||
if (!first) printf(" OR ");
|
|
||||||
printf("%d", filters.status_filters[i].code);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
if (includes > 0) printf(" AND ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Einschlussfilter (folgen dem gesetzten Modus)
|
|
||||||
if (includes > 0) {
|
|
||||||
if (includes > 1) printf("(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.status_count; i++) {
|
|
||||||
if (filters.status_filters[i].mode == FILTER_INCLUDE) {
|
|
||||||
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf("%d", filters.status_filters[i].code);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includes > 1) printf(")");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.method_count > 0) {
|
|
||||||
printf(" Method: ");
|
|
||||||
|
|
||||||
int excludes = 0, includes = 0;
|
|
||||||
for (int i = 0; i < filters.method_count; i++) {
|
|
||||||
if (filters.method_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
|
||||||
else includes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes > 0) {
|
|
||||||
printf("!(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.method_count; i++) {
|
|
||||||
if (filters.method_filters[i].mode == FILTER_EXCLUDE) {
|
|
||||||
if (!first) printf(" OR ");
|
|
||||||
printf("%s", filters.method_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
if (includes > 0) printf(" AND ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes > 0) {
|
|
||||||
if (includes > 1) printf("(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.method_count; i++) {
|
|
||||||
if (filters.method_filters[i].mode == FILTER_INCLUDE) {
|
|
||||||
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf("%s", filters.method_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includes > 1) printf(")");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.ip_count > 0) {
|
|
||||||
printf(" IP: ");
|
|
||||||
|
|
||||||
int excludes = 0, includes = 0;
|
|
||||||
for (int i = 0; i < filters.ip_count; i++) {
|
|
||||||
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
|
||||||
else includes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes > 0) {
|
|
||||||
printf("!(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.ip_count; i++) {
|
|
||||||
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) {
|
|
||||||
if (!first) printf(" OR ");
|
|
||||||
printf("%s", filters.ip_filters[i].ip_address);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
if (includes > 0) printf(" AND ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes > 0) {
|
|
||||||
if (includes > 1) printf("(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.ip_count; i++) {
|
|
||||||
if (filters.ip_filters[i].mode == FILTER_INCLUDE) {
|
|
||||||
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf("%s", filters.ip_filters[i].ip_address);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includes > 1) printf(")");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.user_agent_count > 0) {
|
|
||||||
printf(" UserAgent: ");
|
|
||||||
|
|
||||||
int excludes = 0, includes = 0;
|
|
||||||
for (int i = 0; i < filters.user_agent_count; i++) {
|
|
||||||
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
|
||||||
else includes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes > 0) {
|
|
||||||
printf("!(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.user_agent_count; i++) {
|
|
||||||
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) {
|
|
||||||
if (!first) printf(" OR ");
|
|
||||||
printf("\"%s\"", filters.user_agent_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
if (includes > 0) printf(" AND ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes > 0) {
|
|
||||||
if (includes > 1) printf("(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.user_agent_count; i++) {
|
|
||||||
if (filters.user_agent_filters[i].mode == FILTER_INCLUDE) {
|
|
||||||
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf("\"%s\"", filters.user_agent_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includes > 1) printf(")");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.url_count > 0) {
|
|
||||||
printf(" URL: ");
|
|
||||||
|
|
||||||
int excludes = 0, includes = 0;
|
|
||||||
for (int i = 0; i < filters.url_count; i++) {
|
|
||||||
if (filters.url_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
|
||||||
else includes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes > 0) {
|
|
||||||
printf("!(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.url_count; i++) {
|
|
||||||
if (filters.url_filters[i].mode == FILTER_EXCLUDE) {
|
|
||||||
if (!first) printf(" OR ");
|
|
||||||
printf("\"%s\"", filters.url_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf(")");
|
|
||||||
if (includes > 0) printf(" AND ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes > 0) {
|
|
||||||
if (includes > 1) printf("(");
|
|
||||||
int first = 1;
|
|
||||||
for (int i = 0; i < filters.url_count; i++) {
|
|
||||||
if (filters.url_filters[i].mode == FILTER_INCLUDE) {
|
|
||||||
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
|
||||||
printf("\"%s\"", filters.url_filters[i].pattern);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (includes > 1) printf(")");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.time_count > 0) {
|
|
||||||
printf(" Time: %d Filter(s) gesetzt\n", filters.time_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zeigt aktuellen Modus
|
|
||||||
int active_types = (filters.status_count > 0) + (filters.method_count > 0 ) + (filters.ip_count > 0) +
|
|
||||||
(filters.user_agent_count > 0) + (filters.time_count > 0) + (filters.url_count > 0);
|
|
||||||
if (active_types > 1) {
|
|
||||||
printf("\n %s-Verknüpfung - Ausschlussfilter vorrangig\n",
|
|
||||||
filters.combination_mode == 0 ? "UND" : "ODER");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total_entries > 0) {
|
|
||||||
int filtered_count = count_filtered_entries();
|
|
||||||
printf("\n📊 Ergebnis: %d von %d Einträgen entsprechen den Filtern\n", filtered_count, total_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("===================================\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
long long time_to_unix_microseconds(struct simple_time time) {
|
|
||||||
int days_since_1970 = (time.year - 1970) * 365 + (time.year - 1970) / 4;
|
|
||||||
|
|
||||||
int days_in_months[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
|
||||||
if (time.month >= 1 && time.month <= 12) {
|
|
||||||
days_since_1970 += days_in_months[time.month - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time.month > 2 && ((time.year % 4 == 0 && time.year % 100 != 0) || time.year % 400 == 0)) {
|
|
||||||
days_since_1970 += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
days_since_1970 += time.day - 1;
|
|
||||||
|
|
||||||
long long seconds = (long long)days_since_1970 * 24 * 60 * 60;
|
|
||||||
seconds += time.hour * 60 * 60;
|
|
||||||
seconds += time.minute * 60;
|
|
||||||
seconds += time.second;
|
|
||||||
|
|
||||||
return seconds * 1000000LL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size) {
|
void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size) {
|
||||||
snprintf(buffer, buffer_size, "%04d-%02d-%02dT%02d:%02d:%02d+00:00",
|
snprintf(buffer, buffer_size, "%04d-%02d-%02dT%02d:%02d:%02d+00:00",
|
||||||
time.year, time.month, time.day, time.hour, time.minute, time.second);
|
time.year, time.month, time.day, time.hour, time.minute, time.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Export in Timesketch-kompatiblem Format
|
||||||
void export_filtered_entries() {
|
void export_filtered_entries() {
|
||||||
printf("Dateiname für Timesketch Export eingeben (ohne .csv): ");
|
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
||||||
char filename[95];
|
//90 chars + delimiter
|
||||||
if (scanf("%94s", filename) != 1) {
|
char filename[91];
|
||||||
|
if (scanf("%90s", filename) != 1) {
|
||||||
printf("FEHLER: Ungültiger Dateiname!\n");
|
printf("FEHLER: Ungültiger Dateiname!\n");
|
||||||
clear_input_buffer();
|
clear_input_buffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clear_input_buffer();
|
clear_input_buffer();
|
||||||
|
// Dateiendung
|
||||||
strcat(filename, ".csv");
|
strcat(filename, ".csv");
|
||||||
|
|
||||||
FILE* file = fopen(filename, "w");
|
FILE* file = fopen(filename, "w");
|
||||||
@@ -1238,7 +999,8 @@ void export_filtered_entries() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file, "message,datetime,timestamp_desc,timestamp,ip_address,method,url_path,status_code,bytes_sent,user_agent\n");
|
// CSV-Kopfzeile für Timesketch-Kompatibilität
|
||||||
|
fprintf(file, "datetime,timestamp_desc,ip_address,method,url_path,status_code,bytes_sent,user_agent,source_file,parsing_timestamp\n");
|
||||||
|
|
||||||
int exported_count = 0;
|
int exported_count = 0;
|
||||||
char iso_datetime[32];
|
char iso_datetime[32];
|
||||||
@@ -1248,27 +1010,17 @@ void export_filtered_entries() {
|
|||||||
if (passes_filter(i)) {
|
if (passes_filter(i)) {
|
||||||
format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime));
|
format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime));
|
||||||
|
|
||||||
long long unix_timestamp = time_to_unix_microseconds(all_entries[i].time);
|
|
||||||
|
|
||||||
snprintf(message_text, sizeof(message_text),
|
fprintf(file, "\"%s\",\"HTTP Access Log\",\"%s\",\"%s\",\"%s\",%d,%d,\"%s\",\"%s\",\"%s\"\n",
|
||||||
"%s %s %s - Status: %d, Bytes: %d",
|
|
||||||
all_entries[i].ip_address,
|
|
||||||
all_entries[i].request_method,
|
|
||||||
all_entries[i].url_path,
|
|
||||||
all_entries[i].status_code,
|
|
||||||
all_entries[i].bytes_sent,
|
|
||||||
all_entries[i].user_agent);
|
|
||||||
|
|
||||||
fprintf(file, "\"%s\",\"%s\",\"HTTP Access Log\",%lld,\"%s\",\"%s\",\"%s\",%d,%d\n",
|
|
||||||
message_text,
|
|
||||||
iso_datetime,
|
iso_datetime,
|
||||||
unix_timestamp,
|
|
||||||
all_entries[i].ip_address,
|
all_entries[i].ip_address,
|
||||||
all_entries[i].request_method,
|
all_entries[i].request_method,
|
||||||
all_entries[i].url_path,
|
all_entries[i].url_path,
|
||||||
all_entries[i].status_code,
|
all_entries[i].status_code,
|
||||||
all_entries[i].bytes_sent,
|
all_entries[i].bytes_sent,
|
||||||
all_entries[i].user_agent);
|
all_entries[i].user_agent,
|
||||||
|
all_entries[i].source_file,
|
||||||
|
all_entries[i].parsing_timestamp);
|
||||||
|
|
||||||
exported_count++;
|
exported_count++;
|
||||||
}
|
}
|
||||||
@@ -1397,13 +1149,34 @@ void show_top_user_agents() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_filtered_entries() {
|
void show_filtered_entries(int num_shown) {
|
||||||
int shown_count = 0;
|
int shown_count = 0;
|
||||||
|
|
||||||
printf("\n=== GEFILTERTE LOG-EINTRÄGE ===\n");
|
printf("\nLOGDATEN:\n");
|
||||||
printf("IP-Adresse | Methode | URL | Status | Bytes | User Agent | Zeit\n");
|
printf("IP-Adresse | Methode | URL | Status | Bytes | User Agent | Zeit\n");
|
||||||
printf("-----------------|---------|------------------------|--------|-------|--------------------------------------|------------------\n");
|
printf("-----------------|---------|------------------------|--------|-------|--------------------------------------|------------------\n");
|
||||||
|
|
||||||
|
if (num_shown != 0) {
|
||||||
|
for (int i = 0; i < num_shown; i++) {
|
||||||
|
if (passes_filter(i)) {
|
||||||
|
printf("%-16s | %-7s | %-22s | %-6d | %-5d | %-36s | %02d.%02d.%d %02d:%02d:%02d\n",
|
||||||
|
all_entries[i].ip_address,
|
||||||
|
all_entries[i].request_method,
|
||||||
|
all_entries[i].url_path,
|
||||||
|
all_entries[i].status_code,
|
||||||
|
all_entries[i].bytes_sent,
|
||||||
|
all_entries[i].user_agent,
|
||||||
|
all_entries[i].time.day,
|
||||||
|
all_entries[i].time.month,
|
||||||
|
all_entries[i].time.year,
|
||||||
|
all_entries[i].time.hour,
|
||||||
|
all_entries[i].time.minute,
|
||||||
|
all_entries[i].time.second);
|
||||||
|
|
||||||
|
shown_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (int i = 0; i < total_entries; i++) {
|
for (int i = 0; i < total_entries; i++) {
|
||||||
if (passes_filter(i)) {
|
if (passes_filter(i)) {
|
||||||
printf("%-16s | %-7s | %-22s | %-6d | %-5d | %-36s | %02d.%02d.%d %02d:%02d:%02d\n",
|
printf("%-16s | %-7s | %-22s | %-6d | %-5d | %-36s | %02d.%02d.%d %02d:%02d:%02d\n",
|
||||||
@@ -1423,6 +1196,7 @@ void show_filtered_entries() {
|
|||||||
shown_count++;
|
shown_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
printf("\nInsgesamt %d Einträge gefunden.\n", shown_count);
|
printf("\nInsgesamt %d Einträge gefunden.\n", shown_count);
|
||||||
|
|
||||||
@@ -1431,6 +1205,241 @@ void show_filtered_entries() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Statusanzeige
|
||||||
|
void show_status() {
|
||||||
|
printf("PREVIEW:\n");
|
||||||
|
show_filtered_entries(10);
|
||||||
|
printf("\nSTATUS\n");
|
||||||
|
|
||||||
|
if (total_entries > 0) {
|
||||||
|
printf(" %d Logzeilen in Datenstruktur\n", total_entries);
|
||||||
|
printf(" Speicherbelegung: %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||||
|
} else {
|
||||||
|
printf(" ERROR: Keine Einträge in Datenstruktur!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n Aktive Filter:\n");
|
||||||
|
int total_filters = filters.status_count + filters.method_count + filters.ip_count + filters.time_count + filters.user_agent_count + filters.url_count;
|
||||||
|
|
||||||
|
if (total_filters == 0) {
|
||||||
|
printf(" -> keine Filter gesetzt\n");
|
||||||
|
} else {
|
||||||
|
printf(" Modus: %s\n", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf(" Ausschlussfilter (!) haben Vorrang, dann Einschlussfilter\n");
|
||||||
|
printf("\n Gesetzt:\n");
|
||||||
|
|
||||||
|
if (filters.status_count > 0) {
|
||||||
|
printf(" -> Status: ");
|
||||||
|
|
||||||
|
int excludes = 0, includes = 0;
|
||||||
|
for (int i = 0; i < filters.status_count; i++) {
|
||||||
|
if (filters.status_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
||||||
|
else includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ausschlussfilter (immer im ODER-Modus)
|
||||||
|
if (excludes > 0) {
|
||||||
|
printf("!(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.status_count; i++) {
|
||||||
|
if (filters.status_filters[i].mode == FILTER_EXCLUDE) {
|
||||||
|
if (!first) printf(" OR ");
|
||||||
|
printf("%d", filters.status_filters[i].code);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
if (includes > 0) printf(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Einschlussfilter (folgen dem gesetzten Modus)
|
||||||
|
if (includes > 0) {
|
||||||
|
if (includes > 1) printf("(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.status_count; i++) {
|
||||||
|
if (filters.status_filters[i].mode == FILTER_INCLUDE) {
|
||||||
|
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf("%d", filters.status_filters[i].code);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includes > 1) printf(")");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.method_count > 0) {
|
||||||
|
printf("Request-Method: ");
|
||||||
|
|
||||||
|
int excludes = 0, includes = 0;
|
||||||
|
for (int i = 0; i < filters.method_count; i++) {
|
||||||
|
if (filters.method_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
||||||
|
else includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludes > 0) {
|
||||||
|
printf("!(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.method_count; i++) {
|
||||||
|
if (filters.method_filters[i].mode == FILTER_EXCLUDE) {
|
||||||
|
if (!first) printf(" OR ");
|
||||||
|
printf("%s", filters.method_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
if (includes > 0) printf(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includes > 0) {
|
||||||
|
if (includes > 1) printf("(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.method_count; i++) {
|
||||||
|
if (filters.method_filters[i].mode == FILTER_INCLUDE) {
|
||||||
|
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf("%s", filters.method_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includes > 1) printf(")");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.ip_count > 0) {
|
||||||
|
printf("IP-Adresse: ");
|
||||||
|
|
||||||
|
int excludes = 0, includes = 0;
|
||||||
|
for (int i = 0; i < filters.ip_count; i++) {
|
||||||
|
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
||||||
|
else includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludes > 0) {
|
||||||
|
printf("!(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.ip_count; i++) {
|
||||||
|
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) {
|
||||||
|
if (!first) printf(" OR ");
|
||||||
|
printf("%s", filters.ip_filters[i].ip_address);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
if (includes > 0) printf(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includes > 0) {
|
||||||
|
if (includes > 1) printf("(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.ip_count; i++) {
|
||||||
|
if (filters.ip_filters[i].mode == FILTER_INCLUDE) {
|
||||||
|
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf("%s", filters.ip_filters[i].ip_address);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includes > 1) printf(")");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.user_agent_count > 0) {
|
||||||
|
printf("UserAgent: ");
|
||||||
|
|
||||||
|
int excludes = 0, includes = 0;
|
||||||
|
for (int i = 0; i < filters.user_agent_count; i++) {
|
||||||
|
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
||||||
|
else includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludes > 0) {
|
||||||
|
printf("!(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.user_agent_count; i++) {
|
||||||
|
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) {
|
||||||
|
if (!first) printf(" OR ");
|
||||||
|
printf("\"%s\"", filters.user_agent_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
if (includes > 0) printf(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includes > 0) {
|
||||||
|
if (includes > 1) printf("(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.user_agent_count; i++) {
|
||||||
|
if (filters.user_agent_filters[i].mode == FILTER_INCLUDE) {
|
||||||
|
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf("\"%s\"", filters.user_agent_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includes > 1) printf(")");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.url_count > 0) {
|
||||||
|
printf("Payload/Pfad: ");
|
||||||
|
|
||||||
|
int excludes = 0, includes = 0;
|
||||||
|
for (int i = 0; i < filters.url_count; i++) {
|
||||||
|
if (filters.url_filters[i].mode == FILTER_EXCLUDE) excludes++;
|
||||||
|
else includes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludes > 0) {
|
||||||
|
printf("!(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.url_count; i++) {
|
||||||
|
if (filters.url_filters[i].mode == FILTER_EXCLUDE) {
|
||||||
|
if (!first) printf(" OR ");
|
||||||
|
printf("\"%s\"", filters.url_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
if (includes > 0) printf(" AND ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includes > 0) {
|
||||||
|
if (includes > 1) printf("(");
|
||||||
|
int first = 1;
|
||||||
|
for (int i = 0; i < filters.url_count; i++) {
|
||||||
|
if (filters.url_filters[i].mode == FILTER_INCLUDE) {
|
||||||
|
if (!first) printf(" %s ", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
|
printf("\"%s\"", filters.url_filters[i].pattern);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includes > 1) printf(")");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.time_count > 0) {
|
||||||
|
printf("Zeitraum: %d Filter gesetzt\n", filters.time_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeigt aktuellen Modus
|
||||||
|
int active_types = (filters.status_count > 0) + (filters.method_count > 0 ) + (filters.ip_count > 0) +
|
||||||
|
(filters.user_agent_count > 0) + (filters.time_count > 0) + (filters.url_count > 0);
|
||||||
|
if (active_types > 1) {
|
||||||
|
printf("\n%s-Verknüpfung (nur Einschlussfilter)\n",
|
||||||
|
filters.combination_mode == 0 ? "UND" : "ODER");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_entries > 0) {
|
||||||
|
int filtered_count = count_filtered_entries();
|
||||||
|
printf("\n ERGEBNIS: \n %d von %d Einträgen entsprechen den Filtern\n", filtered_count, total_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void show_statistics() {
|
void show_statistics() {
|
||||||
int count_200 = 0;
|
int count_200 = 0;
|
||||||
int count_404 = 0;
|
int count_404 = 0;
|
||||||
@@ -1438,7 +1447,7 @@ void show_statistics() {
|
|||||||
int total_bytes = 0;
|
int total_bytes = 0;
|
||||||
int filtered_count = 0;
|
int filtered_count = 0;
|
||||||
|
|
||||||
printf("\n=== STATISTIKEN ===\n");
|
printf("\nSTATISTIKEN\n");
|
||||||
|
|
||||||
for (int i = 0; i < total_entries; i++) {
|
for (int i = 0; i < total_entries; i++) {
|
||||||
if (passes_filter(i)) {
|
if (passes_filter(i)) {
|
||||||
@@ -1465,52 +1474,52 @@ void show_statistics() {
|
|||||||
void print_filter_examples() {
|
void print_filter_examples() {
|
||||||
printf("\nFILTER-DOKUMENTATION\n");
|
printf("\nFILTER-DOKUMENTATION\n");
|
||||||
|
|
||||||
printf("\n🔴 EXKLUSIONS-FILTER (immer OR-Logik, unabhängig vom Modus):\n");
|
printf("\nEXKLUSIONS-FILTER (immer OR-Logik, unabhängig vom Modus):\n");
|
||||||
printf("Beispiel: !('uptime' OR 'scanner')\n");
|
printf("Beispiel: !('uptime' OR 'scanner')\n");
|
||||||
printf("→ Schließt ALLE Einträge aus, die 'uptime' ODER 'scanner' enthalten\n\n");
|
printf("> Schließt ALLE Einträge aus, die 'uptime' ODER 'scanner' enthalten\n\n");
|
||||||
|
|
||||||
printf("🟢 INKLUSIONS-FILTER im AND-Modus:\n");
|
printf("INKLUSIONS-FILTER im AND-Modus:\n");
|
||||||
printf("Beispiel: ('bot' AND 'crawl')\n");
|
printf("Beispiel: ('bot' AND 'crawl')\n");
|
||||||
printf("→ Zeigt nur Einträge mit BEIDEN Begriffen\n\n");
|
printf("> Zeigt nur Einträge mit BEIDEN Begriffen\n\n");
|
||||||
|
|
||||||
printf("🟡 INKLUSIONS-FILTER im OR-Modus:\n");
|
printf("INKLUSIONS-FILTER im OR-Modus:\n");
|
||||||
printf("Beispiel: ('bot' OR 'crawl')\n");
|
printf("Beispiel: ('bot' OR 'crawl')\n");
|
||||||
printf("→ Zeigt Einträge mit 'bot' ODER 'crawl'\n\n");
|
printf("> Zeigt Einträge mit 'bot' ODER 'crawl'\n\n");
|
||||||
|
|
||||||
printf("⚡ KOMBINATION: Exklusion + Inklusion:\n");
|
printf("KOMBINATION: Exklusion + Inklusion:\n");
|
||||||
printf("AND-Modus: !('uptime') AND ('bot' AND 'crawl')\n");
|
printf("AND-Modus: !('uptime') AND ('bot' AND 'crawl')\n");
|
||||||
printf("OR-Modus: !('uptime') AND ('bot' OR 'crawl')\n\n");
|
printf("OR-Modus: !('uptime') AND ('bot' OR 'crawl')\n\n");
|
||||||
|
|
||||||
printf("🎯 PRAKTISCHE ANWENDUNGSFÄLLE:\n");
|
printf("PRAKTISCHE ANWENDUNGSFÄLLE:\n");
|
||||||
printf("Malware-Erkennung:\n");
|
printf("Malware-Erkennung:\n");
|
||||||
printf(" '.git' OR '.env' OR '/admin'\n");
|
printf(" '.git' OR '.env' OR '/admin'\n");
|
||||||
printf(" → Verdächtige Pfad-Zugriffe\n\n");
|
printf(" > Verdächtige Pfad-Zugriffe\n\n");
|
||||||
|
|
||||||
printf("Bot-Traffic bereinigen:\n");
|
printf("Bot-Traffic bereinigen:\n");
|
||||||
printf(" !('bot') AND Status=200 AND Method='GET'\n");
|
printf(" !('bot') AND Status=200 AND Method='GET'\n");
|
||||||
printf(" → Nur menschliche, erfolgreiche GET-Anfragen\n\n");
|
printf(" > Nur menschliche, erfolgreiche GET-Anfragen\n\n");
|
||||||
|
|
||||||
printf("Zeitraum-Analyse:\n");
|
printf("Zeitraum-Analyse:\n");
|
||||||
printf(" Time='08:00-18:00' AND Status=500\n");
|
printf(" Time='08:00-18:00' AND Status=500\n");
|
||||||
printf(" → Server-Fehler nur während Geschäftszeiten\n\n");
|
printf(" > Server-Fehler nur während Geschäftszeiten\n\n");
|
||||||
|
|
||||||
printf("DDoS-Verdacht:\n");
|
printf("DDoS-Verdacht:\n");
|
||||||
printf(" Status=429 OR Status=503 OR Status=500\n");
|
printf(" Status=429 OR Status=503 OR Status=500\n");
|
||||||
printf(" → Alle Überlastungs- und Fehler-Codes\n");
|
printf(" > Alle Überlastungs- und Fehler-Codes\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_set_filters() {
|
void menu_set_filters() {
|
||||||
int choice = 0;
|
int choice = 0;
|
||||||
while (choice != 7) {
|
while (choice != 7) {
|
||||||
show_status();
|
show_status();
|
||||||
printf("\n=== FILTER SETZEN ===\n");
|
printf("\nFILTER SETZEN\n");
|
||||||
printf("1. Status-Code Filter hinzufügen (exakte Suche)\n");
|
printf("1. Status-Code (exakte Suche)\n");
|
||||||
printf("2. IP-Adresse Filter hinzufügen (exakte Suche)\n");
|
printf("2. IP-Adresse (exakte Suche)\n");
|
||||||
printf("3. Zeitraum Filter hinzufügen (interaktiv)\n");
|
printf("3. Zeitraum (interaktiv)\n");
|
||||||
printf("4. User-Agent-Filter setzen (Freitext)\n");
|
printf("4. User-Agent (Freitext)\n");
|
||||||
printf("5. HTTP-Methode Filter hinzufügen (Freitext)\n");
|
printf("5. HTTP-Methode (Freitext)\n");
|
||||||
printf("6. URL-Pfad Filter hinzufügen (Freitext)\n");
|
printf("6. URL-Pfad (Freitext)\n");
|
||||||
printf("7. Zurück zum Filter-Menü\n");
|
printf("7. Zurück\n");
|
||||||
printf("Auswahl: ");
|
printf("Auswahl: ");
|
||||||
|
|
||||||
choice = read_safe_integer();
|
choice = read_safe_integer();
|
||||||
@@ -1536,7 +1545,7 @@ void menu_set_filters() {
|
|||||||
filters.status_filters[filters.status_count].code = status;
|
filters.status_filters[filters.status_count].code = status;
|
||||||
filters.status_filters[filters.status_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
filters.status_filters[filters.status_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
||||||
filters.status_count++;
|
filters.status_count++;
|
||||||
printf("✅ Status-Code Filter hinzugefügt. Total: %d\n", filters.status_count);
|
printf(">Status-Code Filter hinzugefügt. Total: %d\n", filters.status_count);
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
||||||
}
|
}
|
||||||
@@ -1561,7 +1570,7 @@ void menu_set_filters() {
|
|||||||
strcpy(filters.ip_filters[filters.ip_count].ip_address, ip);
|
strcpy(filters.ip_filters[filters.ip_count].ip_address, ip);
|
||||||
filters.ip_filters[filters.ip_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
filters.ip_filters[filters.ip_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
||||||
filters.ip_count++;
|
filters.ip_count++;
|
||||||
printf("✅ IP-Filter hinzugefügt. Total: %d\n", filters.ip_count);
|
printf(">IP-Filter hinzugefügt. Total: %d\n", filters.ip_count);
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
||||||
}
|
}
|
||||||
@@ -1679,7 +1688,7 @@ void menu_set_filters() {
|
|||||||
filters.time_filters[filters.time_count] = new_time_filter;
|
filters.time_filters[filters.time_count] = new_time_filter;
|
||||||
filters.time_count++;
|
filters.time_count++;
|
||||||
|
|
||||||
printf("✅ Zeitraum-Filter hinzugefügt. Total: %d\n", filters.time_count);
|
printf(">Zeitraum-Filter hinzugefügt. Total: %d\n", filters.time_count);
|
||||||
|
|
||||||
} else if (choice == 4) {
|
} else if (choice == 4) {
|
||||||
if (filters.user_agent_count >= MAX_FILTERS) {
|
if (filters.user_agent_count >= MAX_FILTERS) {
|
||||||
@@ -1700,7 +1709,7 @@ void menu_set_filters() {
|
|||||||
strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, pattern);
|
strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, pattern);
|
||||||
filters.user_agent_filters[filters.user_agent_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
filters.user_agent_filters[filters.user_agent_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
||||||
filters.user_agent_count++;
|
filters.user_agent_count++;
|
||||||
printf("✅ User-Agent Filter hinzugefügt. Total: %d\n", filters.user_agent_count);
|
printf(">User-Agent Filter hinzugefügt. Total: %d\n", filters.user_agent_count);
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
||||||
}
|
}
|
||||||
@@ -1715,7 +1724,7 @@ void menu_set_filters() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("HTTP-Methode eingeben (z.B. 'GET', 'POST', 'PUT', ... Sonderwert 'MALFORMED'): ");
|
printf("HTTP-Methode eingeben (z.B. 'GET', 'POST', 'PUT', ... Sonderwert 'ATYPICAL'): ");
|
||||||
char pattern[10];
|
char pattern[10];
|
||||||
if (scanf("%9s", pattern) == 1) {
|
if (scanf("%9s", pattern) == 1) {
|
||||||
printf("Filter-Typ wählen:\n");
|
printf("Filter-Typ wählen:\n");
|
||||||
@@ -1728,7 +1737,7 @@ void menu_set_filters() {
|
|||||||
strcpy(filters.method_filters[filters.method_count].pattern, pattern);
|
strcpy(filters.method_filters[filters.method_count].pattern, pattern);
|
||||||
filters.method_filters[filters.method_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
filters.method_filters[filters.method_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
||||||
filters.method_count++;
|
filters.method_count++;
|
||||||
printf("✅ Method-Filter hinzugefügt. Total: %d\n", filters.method_count);
|
printf(">Method-Filter hinzugefügt. Total: %d\n", filters.method_count);
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
||||||
}
|
}
|
||||||
@@ -1756,7 +1765,7 @@ void menu_set_filters() {
|
|||||||
strcpy(filters.url_filters[filters.url_count].pattern, pattern);
|
strcpy(filters.url_filters[filters.url_count].pattern, pattern);
|
||||||
filters.url_filters[filters.url_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
filters.url_filters[filters.url_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE;
|
||||||
filters.url_count++;
|
filters.url_count++;
|
||||||
printf("✅ URL-Filter hinzugefügt. Total: %d\n", filters.url_count);
|
printf(">URL-Filter hinzugefügt. Total: %d\n", filters.url_count);
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
printf("FEHLER: Ungültiger Filter-Typ!\n");
|
||||||
}
|
}
|
||||||
@@ -1781,7 +1790,7 @@ void menu_delete_filters() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n=== FILTER LÖSCHEN ===\n");
|
printf("\nFILTER LÖSCHEN\n");
|
||||||
printf("Aktuell gesetzte Filter:\n");
|
printf("Aktuell gesetzte Filter:\n");
|
||||||
|
|
||||||
int filter_index = 1;
|
int filter_index = 1;
|
||||||
@@ -1830,7 +1839,7 @@ void menu_delete_filters() {
|
|||||||
mode_str);
|
mode_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Welchen Filter möchten Sie löschen (1-%d) oder 0 für Abbrechen: ", total_filters);
|
printf("Auswahl: (1-%d) oder 0 für Abbrechen: ", total_filters);
|
||||||
int choice = read_safe_integer();
|
int choice = read_safe_integer();
|
||||||
|
|
||||||
if (choice == 0) {
|
if (choice == 0) {
|
||||||
@@ -1850,7 +1859,7 @@ void menu_delete_filters() {
|
|||||||
filters.status_filters[j] = filters.status_filters[j + 1];
|
filters.status_filters[j] = filters.status_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.status_count--;
|
filters.status_count--;
|
||||||
printf("✅ Status-Code Filter gelöscht.\n");
|
printf(">Status-Code Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1862,7 +1871,7 @@ void menu_delete_filters() {
|
|||||||
filters.method_filters[j] = filters.method_filters[j + 1];
|
filters.method_filters[j] = filters.method_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.method_count--;
|
filters.method_count--;
|
||||||
printf("✅ Method-Filter gelöscht.\n");
|
printf(">Method-Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1874,7 +1883,7 @@ void menu_delete_filters() {
|
|||||||
filters.ip_filters[j] = filters.ip_filters[j + 1];
|
filters.ip_filters[j] = filters.ip_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.ip_count--;
|
filters.ip_count--;
|
||||||
printf("✅ IP-Filter gelöscht.\n");
|
printf(">IP-Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1886,7 +1895,7 @@ void menu_delete_filters() {
|
|||||||
filters.user_agent_filters[j] = filters.user_agent_filters[j + 1];
|
filters.user_agent_filters[j] = filters.user_agent_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.user_agent_count--;
|
filters.user_agent_count--;
|
||||||
printf("✅ User-Agent Filter gelöscht.\n");
|
printf(">User-Agent Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1898,7 +1907,7 @@ void menu_delete_filters() {
|
|||||||
filters.url_filters[j] = filters.url_filters[j + 1];
|
filters.url_filters[j] = filters.url_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.url_count--;
|
filters.url_count--;
|
||||||
printf("✅ URL-Filter gelöscht.\n");
|
printf(">URL-Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1910,7 +1919,7 @@ void menu_delete_filters() {
|
|||||||
filters.time_filters[j] = filters.time_filters[j + 1];
|
filters.time_filters[j] = filters.time_filters[j + 1];
|
||||||
}
|
}
|
||||||
filters.time_count--;
|
filters.time_count--;
|
||||||
printf("✅ Zeitraum-Filter gelöscht.\n");
|
printf(">Zeitraum-Filter gelöscht.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_index++;
|
current_index++;
|
||||||
@@ -1918,7 +1927,7 @@ void menu_delete_filters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void menu_filter_mode() {
|
void menu_filter_mode() {
|
||||||
printf("=== FILTER-MODUS ===\n");
|
printf("FILTER-MODUS\n");
|
||||||
printf("Aktueller Modus: %s\n", filters.combination_mode == 0 ? "AND" : "OR");
|
printf("Aktueller Modus: %s\n", filters.combination_mode == 0 ? "AND" : "OR");
|
||||||
printf("\nACHTUNG:\n");
|
printf("\nACHTUNG:\n");
|
||||||
printf("Der Modus wirkt sich nur auf inklusive Filter aus.\n");
|
printf("Der Modus wirkt sich nur auf inklusive Filter aus.\n");
|
||||||
@@ -1932,10 +1941,10 @@ void menu_filter_mode() {
|
|||||||
|
|
||||||
if (choice == 1) {
|
if (choice == 1) {
|
||||||
filters.combination_mode = 0;
|
filters.combination_mode = 0;
|
||||||
printf("✅ Filter-Modus auf AND gesetzt.\n");
|
printf(">Filter-Modus auf AND gesetzt.\n");
|
||||||
} else if (choice == 2) {
|
} else if (choice == 2) {
|
||||||
filters.combination_mode = 1;
|
filters.combination_mode = 1;
|
||||||
printf("✅ Filter-Modus auf OR gesetzt.\n");
|
printf(">Filter-Modus auf OR gesetzt.\n");
|
||||||
} else if (choice == 3) {
|
} else if (choice == 3) {
|
||||||
print_filter_examples();
|
print_filter_examples();
|
||||||
} else if (choice != -1) {
|
} else if (choice != -1) {
|
||||||
@@ -1952,7 +1961,7 @@ void menu_reset_filters() {
|
|||||||
filters.url_count = 0;
|
filters.url_count = 0;
|
||||||
filters.combination_mode = 0;
|
filters.combination_mode = 0;
|
||||||
|
|
||||||
printf("✅ Alle Filter zurückgesetzt.\n");
|
printf(">Alle Filter zurückgesetzt.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_filter_management() {
|
void menu_filter_management() {
|
||||||
@@ -2014,7 +2023,7 @@ void menu_show_entries() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
show_filtered_entries();
|
show_filtered_entries(0);
|
||||||
} else if (choice == 2) {
|
} else if (choice == 2) {
|
||||||
export_filtered_entries();
|
export_filtered_entries();
|
||||||
} else if (choice == 3) {
|
} else if (choice == 3) {
|
||||||
@@ -2051,7 +2060,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("=== NGINX LOG PARSER - VEREINFACHTE VERSION ===\n");
|
printf("NGINX EXAMINATOR\n");
|
||||||
allocate_initial_memory();
|
allocate_initial_memory();
|
||||||
|
|
||||||
load_log_file(argv[1]);
|
load_log_file(argv[1]);
|
||||||
@@ -2080,7 +2089,7 @@ int main(int argc, char* argv[]) {
|
|||||||
} else if (choice == 3) {
|
} else if (choice == 3) {
|
||||||
show_statistics();
|
show_statistics();
|
||||||
} else if (choice == 4) {
|
} else if (choice == 4) {
|
||||||
printf("Auf Wiedersehen!\n");
|
printf("Programmende\n");
|
||||||
} else {
|
} else {
|
||||||
printf("Ungültige Auswahl! Bitte wählen Sie 1-4.\n");
|
printf("Ungültige Auswahl! Bitte wählen Sie 1-4.\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user