This commit is contained in:
overcuriousity 2025-09-05 13:34:17 +02:00
parent 87eb2c34d9
commit 80504583a4

View File

@ -32,13 +32,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#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
#define SUSPICIOUS_REQUEST_LEN_THRESHOLD 256 #define SUSPICIOUS_REQUEST_LEN_THRESHOLD 256
// definiert Variablen für den Filtermodus. FILTER_INCLUDE=0, FILTER_EXCLUDE=1. Verbessert die Lesbarkeit des Codes.
// TODO entfernen?
typedef enum {
FILTER_INCLUDE,
FILTER_EXCLUDE
} filter_mode_t;
// struct für die Darstellung von Timestamps. Die granulare Trennung in verschiedene int-Werte macht die spätere Verarbeitung modular anpassbar/erweiterbar und erleichtert die Verarbeitung. // struct für die Darstellung von Timestamps. Die granulare Trennung in verschiedene int-Werte macht die spätere Verarbeitung modular anpassbar/erweiterbar und erleichtert die Verarbeitung.
struct simple_time { struct simple_time {
int day; int day;
@ -68,47 +61,47 @@ struct log_entry {
// Struktur für einen Status-Filtereintrag mit Inhalt & Modus // Struktur für einen Status-Filtereintrag mit Inhalt & Modus
struct status_filter { struct status_filter {
int code; int code;
filter_mode_t mode; int filter_exclude_flag;
}; };
struct method_filter { struct method_filter {
char pattern[10]; char pattern[10];
filter_mode_t mode; int filter_exclude_flag;
}; };
// für IP-Adressen // für IP-Adressen
struct ip_filter { struct ip_filter {
char ip_address[50]; char ip_address[50];
filter_mode_t mode; int filter_exclude_flag;
}; };
// für Zeit, Start- und Endzeit // für Zeit, Start- und Endzeit
struct time_filter { struct time_filter {
struct simple_time start_time; struct simple_time start_time;
struct simple_time end_time; struct simple_time end_time;
filter_mode_t mode; int filter_exclude_flag;
}; };
// Filter für User-Agent // Filter für User-Agent
struct user_agent_filter { struct user_agent_filter {
char pattern[256]; char pattern[256];
filter_mode_t mode; int filter_exclude_flag;
}; };
// Filter für URL-Pfad/Request // Filter für URL-Pfad/Request
struct url_filter { struct url_filter {
char pattern[MAX_REQUEST_LENGTH]; char pattern[MAX_REQUEST_LENGTH];
filter_mode_t mode; int filter_exclude_flag;
}; };
struct annotation_flag_filter { struct annotation_flag_filter {
int annotation_flag_is_present; int annotation_flag_is_present;
filter_mode_t mode; int filter_exclude_flag;
}; };
struct annotation_filter { struct annotation_filter {
char pattern[64]; char pattern[64];
filter_mode_t mode; int filter_exclude_flag;
}; };
// Struktur zum erhalten aller Filtereinträge, kann im Dialogbetrieb bearbeitet werden. Mit Zähler. // Struktur zum erhalten aller Filtereinträge, kann im Dialogbetrieb bearbeitet werden. Mit Zähler.
@ -140,12 +133,20 @@ struct filter_system {
int combination_mode; // 0=AND-Filter oder 1=OR-Filter int combination_mode; // 0=AND-Filter oder 1=OR-Filter
}; };
// Definition einer Datenstruktur für die IP-Adressen Topliste
struct ip_stat {
char ip_address[50];
int count;
};
// Initialisierung eines Arrays für die Logeinträge und weiterer Startvariablen // Initialisierung eines Arrays für die Logeinträge und weiterer Startvariablen
struct log_entry *all_entries = NULL; struct log_entry *all_entries = NULL;
int max_entries = 0; int max_entries = 0;
int total_entries = 0; int total_entries = 0;
int suspicious_patterns_count = 0; int suspicious_patterns_count = 0;
struct filter_system filters = {0}; struct filter_system filters = {0};
// für -v option
int flag_verbose = 0;
// Hilfsfunktion für die Erkennung von Leerzeichen // Hilfsfunktion für die Erkennung von Leerzeichen
int is_space(char c) { int is_space(char c) {
@ -246,7 +247,7 @@ void cleanup_memory(){
// sauberes Schließen und bereinigen bei Fehlerstatus, sofern Speicher nicht alloziert werden kann // sauberes Schließen und bereinigen bei Fehlerstatus, sofern Speicher nicht alloziert werden kann
void cleanup_and_exit(){ void cleanup_and_exit(){
printf("Programmende. Speicher wird freigegeben und mit NULL überschrieben.\n"); if (flag_verbose) printf("DEBUG: Programmende. Speicher wird freigegeben und mit NULL überschrieben.\n");
cleanup_memory(); cleanup_memory();
exit(1); exit(1);
} }
@ -258,7 +259,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("DEBUG: Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR); if (flag_verbose) printf("DEBUG: 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));
@ -269,7 +270,7 @@ void mem_expand_dynamically(){
} }
all_entries = new_ptr; all_entries = new_ptr;
printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry))); if (flag_verbose) printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
} }
} }
@ -283,7 +284,7 @@ void allocate_initial_memory(){
exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
} }
printf("DEBUG: Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry))); if (flag_verbose) printf("DEBUG: 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) { void get_current_timestamp(char* buffer, int buffer_size) {
@ -311,24 +312,30 @@ int is_directory(char* path) {
// Hilfsfunktion zum prüfen, ob es sich um eine plausible nginx-Logdatei handelt (Metrik: Dateiname - BESSER: Regex oder Magic Bytes?) // Hilfsfunktion zum prüfen, ob es sich um eine plausible nginx-Logdatei handelt (Metrik: Dateiname - BESSER: Regex oder Magic Bytes?)
int is_log_file(char* filename) { int is_log_file(char* filename) {
char* log_pos = strstr(filename, ".log"); // Sucht und findet den Pointer auf die Startposition des Suchstrings // versteckte Dateien sowie . oder .. überspringen
if (log_pos == NULL) return 0; if (filename[0] == '.') {
return 0;
char* after_log = log_pos + 4;
if (*after_log == '\0') return 1; // true, wenn die Datei mit .log endet
if (*after_log == '.') {
after_log++;
if (*after_log == '\0') return 0; // false, wenn die Datei mit einem Punkt nach .log endet
while (*after_log != '\0') {
if (*after_log < '0' || *after_log > '9') return 0; // wenn was anderes als Zahlen nach dem . kommen, gib False zurück
after_log++;
}
return 1; // true, wenn nach .log. noch Zahlen vorhanden sind, wie typisch bei NGINX-Logrotation
} }
return 0; // false, wenn nichts zutrifft
// Mögliche Bestandteile von NGINX-Logfile-Dateinamen
char* log_patterns[] = {
".log",
"access",
"error",
"combined",
"redirect",
NULL
};
// Vergleich der vorhandenen Dateinamen mit den Suchmustern
for (int i = 0; log_patterns[i] != NULL; i++) {
if (strstr(filename, log_patterns[i]) != NULL) {
if ((strstr(filename, "error")!= NULL)||(strstr(filename, ".gz")!= NULL)) continue;
return 1;
}
}
return 0;
} }
// Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase) // Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase)
@ -374,12 +381,25 @@ int search_in_string(char* raw_string, char* search_string) {
// Fügt eine Annotation zu einem bestimmten Eintrag hinzu // Fügt eine Annotation zu einem bestimmten Eintrag hinzu
// https://stackoverflow.com/questions/5901181/c-string-append
void annotate_entry(int index, char* annotation_string) { void annotate_entry(int index, char* annotation_string) {
if (index >= 0 && index < total_entries) { if (index >= 0 && index < total_entries) {
strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1); if (all_entries[index].annotation== NULL){
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0'; strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1);
all_entries[index].annotated_flag = 1; all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
//printf("DEBUG: Annotation zu Eintrag %d: %s\n", index, annotation_string); all_entries[index].annotated_flag = 1;
} else {
char * new_str ;
if((new_str = malloc(strlen(all_entries[index].annotation)+strlen(",")+strlen(annotation_string)+1)) != NULL){
new_str[0] = '\0'; // ensures the memory is an empty string
strcat(new_str,",");
strcat(new_str,annotation_string);
strncpy(all_entries[index].annotation, new_str, sizeof(all_entries[index].annotation) - 1);
all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0';
free(new_str);
new_str=NULL;
}
}
} }
} }
@ -387,7 +407,7 @@ void annotate_entry(int index, char* annotation_string) {
// TRANSPARENZ: Diese Funktion ist KI-generiert // TRANSPARENZ: Diese Funktion ist KI-generiert
void annotate_suspicious_entries(struct log_entry* dataset) { void annotate_suspicious_entries(struct log_entry* dataset) {
printf("DEBUG: Prüfe %d Einträge auf verdächtige Muster...\n", total_entries); if (flag_verbose) printf("DEBUG: Prüfe %d Einträge auf verdächtige Muster...\n", total_entries);
for (int i = 0; i < total_entries; i++) { for (int i = 0; i < total_entries; i++) {
// Initialisierung der Annotation falls noch nicht gesetzt // Initialisierung der Annotation falls noch nicht gesetzt
@ -616,7 +636,7 @@ void annotate_suspicious_entries(struct log_entry* dataset) {
} }
} }
printf("DEBUG: Analyse abgeschlossen. %d verdächtige Muster erkannt.\n", suspicious_patterns_count); if (flag_verbose) printf("DEBUG: Analyse abgeschlossen. %d verdächtige Muster erkannt.\n", suspicious_patterns_count);
} }
/* /*
@ -921,8 +941,8 @@ void load_log_file(char* path) {
char full_path[512]; char full_path[512];
if (is_directory(path)) { if (is_directory(path)) {
printf("DEBUG: Verzeichnis erkannt: %s\n", path); if (flag_verbose) printf("DEBUG: Verzeichnis erkannt: %s\n", path);
printf("DEBUG: Suche nach .log Dateien...\n"); if (flag_verbose) printf("DEBUG: Suche nach .log Dateien...\n");
DIR* dir = opendir(path); DIR* dir = opendir(path);
if (dir == NULL) { if (dir == NULL) {
@ -962,7 +982,7 @@ void load_log_file(char* path) {
printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found); printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found);
} }
} else { } else {
printf("DEBUG: Einzelne Datei erkannt: %s\n", path); if (flag_verbose) printf("DEBUG: Einzelne Datei erkannt: %s\n", path);
if (strstr(path, ".gz") != NULL) { if (strstr(path, ".gz") != NULL) {
load_gz_file(path); load_gz_file(path);
} else { } else {
@ -972,9 +992,8 @@ void load_log_file(char* path) {
printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries); printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
// die aufgerufene Funktion ist KI-generiert und annotiert verdächtige Requests automatisch. // die aufgerufene Funktion ist KI-generiert und annotiert verdächtige Requests automatisch.
// TODO
annotate_suspicious_entries(all_entries); annotate_suspicious_entries(all_entries);
printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", if (flag_verbose) printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n",
(unsigned long)(max_entries * sizeof(struct log_entry)), max_entries); (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
} }
@ -983,7 +1002,7 @@ int user_agent_matches(char* user_agent) {
if (filters.user_agent_count == 0) return 1; if (filters.user_agent_count == 0) return 1;
// Ausschluss-Filter geht vor // Ausschluss-Filter geht vor
for (int i = 0; i < filters.user_agent_count; i++) { for (int i = 0; i < filters.user_agent_count; i++) {
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) { if (filters.user_agent_filters[i].filter_exclude_flag == 1) {
int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern); int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft
@ -995,7 +1014,7 @@ int user_agent_matches(char* user_agent) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.user_agent_count; i++) { for (int i = 0; i < filters.user_agent_count; i++) {
if (filters.user_agent_filters[i].mode == FILTER_INCLUDE) { if (filters.user_agent_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern); int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
@ -1024,7 +1043,7 @@ int url_matches(char* url_path) {
if (filters.url_count == 0) return 1; if (filters.url_count == 0) return 1;
// Ausschluss-Filter geht vor // Ausschluss-Filter geht vor
for (int i = 0; i < filters.url_count; i++) { for (int i = 0; i < filters.url_count; i++) {
if (filters.url_filters[i].mode == FILTER_EXCLUDE) { if (filters.url_filters[i].filter_exclude_flag == 1) {
int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern); int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft
@ -1036,7 +1055,7 @@ int url_matches(char* url_path) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.url_count; i++) { for (int i = 0; i < filters.url_count; i++) {
if (filters.url_filters[i].mode == FILTER_INCLUDE) { if (filters.url_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern); int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
@ -1065,7 +1084,7 @@ int method_matches(char* request_method) {
if (filters.method_count == 0) return 1; if (filters.method_count == 0) return 1;
// Ausschluss-Filter geht vor // Ausschluss-Filter geht vor
for (int i = 0; i < filters.method_count; i++) { for (int i = 0; i < filters.method_count; i++) {
if (filters.method_filters[i].mode == FILTER_EXCLUDE) { if (filters.method_filters[i].filter_exclude_flag == 1) {
int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern); int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft
@ -1077,7 +1096,7 @@ int method_matches(char* request_method) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.method_count; i++) { for (int i = 0; i < filters.method_count; i++) {
if (filters.method_filters[i].mode == FILTER_INCLUDE) { if (filters.method_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern); int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
@ -1105,7 +1124,7 @@ int status_code_matches(int status_code) {
if (filters.status_count == 0) return 1; if (filters.status_count == 0) return 1;
// Ausschluss-Filter prüfen: immer übergeordnet gültig // Ausschluss-Filter prüfen: immer übergeordnet gültig
for (int i = 0; i < filters.status_count; i++) { for (int i = 0; i < filters.status_count; i++) {
if (filters.status_filters[i].mode == FILTER_EXCLUDE) { if (filters.status_filters[i].filter_exclude_flag == 1) {
if (filters.status_filters[i].code == status_code) { if (filters.status_filters[i].code == status_code) {
return 0; return 0;
} }
@ -1117,7 +1136,7 @@ int status_code_matches(int status_code) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.status_count; i++) { for (int i = 0; i < filters.status_count; i++) {
if (filters.status_filters[i].mode == FILTER_INCLUDE) { if (filters.status_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
if (filters.status_filters[i].code == status_code) { if (filters.status_filters[i].code == status_code) {
include_matches++; include_matches++;
@ -1144,7 +1163,7 @@ int ip_address_matches(char* ip_address) {
// Prüfen der Ausschlussfilter, sind dem Rest vorgelagert // Prüfen der Ausschlussfilter, sind dem Rest vorgelagert
for (int i = 0; i < filters.ip_count; i++) { for (int i = 0; i < filters.ip_count; i++) {
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) { if (filters.ip_filters[i].filter_exclude_flag == 1) {
if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) { if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) {
return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert
} }
@ -1156,7 +1175,7 @@ int ip_address_matches(char* ip_address) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.ip_count; i++) { for (int i = 0; i < filters.ip_count; i++) {
if (filters.ip_filters[i].mode == FILTER_INCLUDE) { if (filters.ip_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) { if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) {
include_matches++; include_matches++;
@ -1179,14 +1198,14 @@ int ip_address_matches(char* ip_address) {
} }
int is_annotated(int annotated_flag){ int is_annotated(int annotated_flag){
if (filters.annotation_flag_filter.mode == FILTER_EXCLUDE && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { if (filters.annotation_flag_filter.filter_exclude_flag == 1 && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) {
return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert
} }
else if (filters.annotation_flag_filter.mode == FILTER_INCLUDE && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { else if (filters.annotation_flag_filter.filter_exclude_flag == 0 && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) {
return 1; // zutreffender Einschlussfilter führt zu positivem Rückgabewert return 1; // zutreffender Einschlussfilter führt zu positivem Rückgabewert
} }
// nichtannotiert, aber inklusiver Filter aktiv -> Eintrag nicht anzeigen // nichtannotiert, aber inklusiver Filter aktiv -> Eintrag nicht anzeigen
else if (annotated_flag == 0 && filters.annotation_flag_filter.mode == FILTER_INCLUDE && filters.annotation_flag_filter_enabled == 1){ else if (annotated_flag == 0 && filters.annotation_flag_filter.filter_exclude_flag == 0 && filters.annotation_flag_filter_enabled == 1){
return 0; return 0;
} }
// Filter nicht aktiv, positiver Rückgabewert // Filter nicht aktiv, positiver Rückgabewert
@ -1198,7 +1217,7 @@ int annotation_matches(char* annotation) {
if (filters.annotation_count == 0) return 1; if (filters.annotation_count == 0) return 1;
// Ausschluss-Filter geht vor // Ausschluss-Filter geht vor
for (int i = 0; i < filters.annotation_count; i++) { for (int i = 0; i < filters.annotation_count; i++) {
if (filters.annotation_filters[i].mode == FILTER_EXCLUDE) { if (filters.annotation_filters[i].filter_exclude_flag == 1) {
int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern); int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft
@ -1210,7 +1229,7 @@ int annotation_matches(char* annotation) {
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.annotation_count; i++) { for (int i = 0; i < filters.annotation_count; i++) {
if (filters.annotation_filters[i].mode == FILTER_INCLUDE) { if (filters.annotation_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern); int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern);
if (pattern_found) { if (pattern_found) {
@ -1240,7 +1259,7 @@ int time_matches(struct simple_time entry_time) {
// Übergeordneter Ausschlussfilter // Übergeordneter Ausschlussfilter
for (int i = 0; i < filters.time_count; i++) { for (int i = 0; i < filters.time_count; i++) {
if (filters.time_filters[i].mode == FILTER_EXCLUDE) { if (filters.time_filters[i].filter_exclude_flag == 1) {
int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 && int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 &&
compare_times(entry_time, filters.time_filters[i].end_time) <= 0); compare_times(entry_time, filters.time_filters[i].end_time) <= 0);
if (in_range) { if (in_range) {
@ -1253,7 +1272,7 @@ int time_matches(struct simple_time entry_time) {
int include_count = 0; int include_count = 0;
int include_matches = 0; int include_matches = 0;
for (int i = 0; i < filters.time_count; i++) { for (int i = 0; i < filters.time_count; i++) {
if (filters.time_filters[i].mode == FILTER_INCLUDE) { if (filters.time_filters[i].filter_exclude_flag == 0) {
include_count++; include_count++;
int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 && int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 &&
compare_times(entry_time, filters.time_filters[i].end_time) <= 0); compare_times(entry_time, filters.time_filters[i].end_time) <= 0);
@ -1387,7 +1406,7 @@ void export_filtered_entries(char *filepath) {
} }
// CSV-Kopfzeile für Timesketch-Kompatibilität // 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,annotation\n"); fprintf(file, "datetime,message,timestamp_desc,ip_address,method,url_path,status_code,bytes_sent,user_agent,parsing_timestamp,tag\n");
int exported_count = 0; int exported_count = 0;
char iso_datetime[32]; char iso_datetime[32];
@ -1396,20 +1415,44 @@ void export_filtered_entries(char *filepath) {
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));
// https://stackoverflow.com/questions/5901181/c-string-append
// https://www.quora.com/How-can-we-count-the-number-of-special-characters-in-a-string-in-the-C-language-using-fgets
char* tag_str;
int num_delimiters = 0;
int c=0;
while(all_entries[i].annotation[c]!='\0'){
num_delimiters++;
}
if (tag_str=malloc(sizeof(all_entries[i].annotation)+sizeof("[ ]")+(sizeof(','))*num_delimiters)+1)!=NULL){
tag_str[0] = '\0';
fprintf(file, "\"%s\",\"HTTP Access Log\",\"%s\",\"%s\",\"%s\",%d,%d,\"%s\",\"%s\",\"%s\"\n",
iso_datetime, char* token = strtok(all_entries[i].annotation, ",");
if (!token) return;
strcat(tag_str, "[ ");
for (i=0;i<num_delimiters;i++){
strcat(tag_str, "\"");
strcat(tag_str, strtok(NULL, ","));
strcat(tag_str, '"');
}
strcat(tag_str, " ]");
}
fprintf(file, "\"%s\",\"%s\",\"HTTP Access Log\",\"%s\",\"%s\",\"%s\",%d,%d,\"%s\",\"%s\",\"%s\"\n",
iso_datetime, // datetime
all_entries[i].source_file, // message
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, all_entries[i].parsing_timestamp,
all_entries[i].annotation tag_str
//all_entries[i].annotation // tag
); );
free(tag_str);
tag_str=NULL;
exported_count++; exported_count++;
} }
} }
@ -1418,10 +1461,6 @@ void export_filtered_entries(char *filepath) {
printf("INFO: %d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename); printf("INFO: %d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename);
} }
struct ip_stat {
char ip_address[50];
int count;
};
// zeigt alle annotierten Einträge detailliert an // zeigt alle annotierten Einträge detailliert an
void show_annotated_entries() { void show_annotated_entries() {
@ -1461,27 +1500,36 @@ void show_annotated_entries() {
} }
} }
// TODO doku // top-IP-Adressen sortieren nach Aufkommen und anzeigen
void show_top_x_ips(){ void show_top_x_ips(){
// initialisieren von 1000 Datenstrukturen mit einem char ip_address[50] und int count (oben definiert)
struct ip_stat ip_stats[1000]; struct ip_stat ip_stats[1000];
// lokaler Zähler
int unique_ips = 0; int unique_ips = 0;
// iterieren über alle IP-Adressen, die im Filterset sind
for (int i = 0; i < total_entries; i++) { for (int i = 0; i < total_entries; i++) {
if (!passes_filter(i)) continue; if (!passes_filter(i)) continue;
// IP lokal speichern
char* current_ip = all_entries[i].ip_address; char* current_ip = all_entries[i].ip_address;
// initialisieren des Index - -1 heißt bisher nie aufgetreten
int found_index = -1; int found_index = -1;
for (int j = 0; j < unique_ips; j++) { for (int j = 0; j < unique_ips; j++) {
// Wenn die IP-Adresse im Vergeichsdatensatz gefunden wird, wird der index entsprechend gesetzt/erstellt
if (strcmp(ip_stats[j].ip_address, current_ip) == 0) { if (strcmp(ip_stats[j].ip_address, current_ip) == 0) {
found_index = j; found_index = j;
break; break;
} }
} }
// wenn ein neuer index erstellt wurde (IP-Adresse war noch nicht in der Datenstruktur) oder gefunden wurde...
if (found_index >= 0) { if (found_index >= 0) {
// inkrementieren des counters für Anzahl wie oft gefunden
ip_stats[found_index].count++; ip_stats[found_index].count++;
} else { } else {
// wenn nicht gefunden (found_index == -1) wird die IP mit count = 1 neu angelegt
if (unique_ips < 1000) { if (unique_ips < 1000) {
strcpy(ip_stats[unique_ips].ip_address, current_ip); strcpy(ip_stats[unique_ips].ip_address, current_ip);
ip_stats[unique_ips].count = 1; ip_stats[unique_ips].count = 1;
@ -1490,6 +1538,8 @@ void show_top_x_ips(){
} }
} }
// iterieren über alle unique ips
// Bubble sort: https://www.proggen.org/doku.php?id=training:sorting:bubblesort:solution
for (int i = 0; i < unique_ips - 1; i++) { for (int i = 0; i < unique_ips - 1; i++) {
for (int j = 0; j < unique_ips - i - 1; j++) { for (int j = 0; j < unique_ips - i - 1; j++) {
if (ip_stats[j].count < ip_stats[j + 1].count) { if (ip_stats[j].count < ip_stats[j + 1].count) {
@ -1500,6 +1550,7 @@ void show_top_x_ips(){
} }
} }
// visuelle Darstellung
printf("\nTOP %d IP-ADRESSEN\n", TOP_X); printf("\nTOP %d IP-ADRESSEN\n", TOP_X);
printf("Rang | IP-Adresse | Anzahl Anfragen\n"); printf("Rang | IP-Adresse | Anzahl Anfragen\n");
printf("-----|------------------|----------------\n"); printf("-----|------------------|----------------\n");
@ -1516,7 +1567,7 @@ void show_top_x_ips(){
} }
} }
// TODO doku // gleiche Mechanik wie in show_top_x_ips - könnte wahrscheinlich vereinheitlicht werden
void show_top_user_agents(){ void show_top_user_agents(){
struct user_agent_stat { struct user_agent_stat {
char user_agent[256]; char user_agent[256];
@ -1633,7 +1684,7 @@ void print_filter_args(){
printf("--status="); printf("--status=");
for (int i = 0; i < filters.status_count; i++) { for (int i = 0; i < filters.status_count; i++) {
if (i > 0) {printf(",");}; if (i > 0) {printf(",");};
if (filters.status_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.status_filters[i].filter_exclude_flag == 1) printf("!");
printf("%d", filters.status_filters[i].code); printf("%d", filters.status_filters[i].code);
} }
printf(" "); printf(" ");
@ -1643,7 +1694,7 @@ void print_filter_args(){
printf("--method="); printf("--method=");
for (int i = 0; i < filters.method_count; i++) { for (int i = 0; i < filters.method_count; i++) {
if (i > 0) {printf(",");} if (i > 0) {printf(",");}
if (filters.method_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.method_filters[i].filter_exclude_flag == 1) printf("!");
printf("%s", filters.method_filters[i].pattern); printf("%s", filters.method_filters[i].pattern);
} }
printf(" "); printf(" ");
@ -1653,7 +1704,7 @@ void print_filter_args(){
printf("--ip="); printf("--ip=");
for (int i = 0; i < filters.ip_count; i++) { for (int i = 0; i < filters.ip_count; i++) {
if (i > 0) {printf(",");}; if (i > 0) {printf(",");};
if (filters.ip_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.ip_filters[i].filter_exclude_flag == 1) printf("!");
printf("%s", filters.ip_filters[i].ip_address); printf("%s", filters.ip_filters[i].ip_address);
} }
printf(" "); printf(" ");
@ -1663,7 +1714,7 @@ void print_filter_args(){
printf("--useragent="); printf("--useragent=");
for (int i = 0; i < filters.user_agent_count; i++) { for (int i = 0; i < filters.user_agent_count; i++) {
if (i > 0) {printf(",");}; if (i > 0) {printf(",");};
if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.user_agent_filters[i].filter_exclude_flag == 1) printf("!");
printf("%s", filters.user_agent_filters[i].pattern); printf("%s", filters.user_agent_filters[i].pattern);
} }
printf(" "); printf(" ");
@ -1673,7 +1724,7 @@ void print_filter_args(){
printf("--url="); printf("--url=");
for (int i = 0; i < filters.url_count; i++) { for (int i = 0; i < filters.url_count; i++) {
if (i > 0) {printf(",");}; if (i > 0) {printf(",");};
if (filters.url_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.url_filters[i].filter_exclude_flag == 1) printf("!");
printf("%s", filters.url_filters[i].pattern); printf("%s", filters.url_filters[i].pattern);
} }
printf(" "); printf(" ");
@ -1683,7 +1734,7 @@ void print_filter_args(){
printf("--timerange="); printf("--timerange=");
for(int i =0; i < filters.time_count;i++){ for(int i =0; i < filters.time_count;i++){
if(i > 0) {printf(",");}; if(i > 0) {printf(",");};
if (filters.time_filters[i].mode == FILTER_EXCLUDE) {printf("!");}; if (filters.time_filters[i].filter_exclude_flag == 1) {printf("!");};
// die führenden 0 sind hier wichtig // die führenden 0 sind hier wichtig
printf("%04d-%02d-%02d-%02d-%02d-%02d:%04d-%02d-%02d-%02d-%02d-%02d ", printf("%04d-%02d-%02d-%02d-%02d-%02d:%04d-%02d-%02d-%02d-%02d-%02d ",
filters.time_filters[i].start_time.year, filters.time_filters[i].start_time.year,
@ -1704,7 +1755,7 @@ void print_filter_args(){
// macht nicht viel Sinn, diese hier zu integrieren, so lang der User nicht weiß, wie die Annotationen lauten // macht nicht viel Sinn, diese hier zu integrieren, so lang der User nicht weiß, wie die Annotationen lauten
if (filters.annotation_flag_filter_enabled) { if (filters.annotation_flag_filter_enabled) {
printf("--annotated="); printf("--annotated=");
if (filters.annotation_flag_filter.mode == FILTER_EXCLUDE) printf("!"); if (filters.annotation_flag_filter.filter_exclude_flag == 1) printf("!");
printf("true "); printf("true ");
} }
@ -1712,7 +1763,7 @@ void print_filter_args(){
printf("--annotation="); printf("--annotation=");
for (int i = 0; i < filters.annotation_count; i++) { for (int i = 0; i < filters.annotation_count; i++) {
if (i > 0) printf(","); if (i > 0) printf(",");
if (filters.annotation_filters[i].mode == FILTER_EXCLUDE) printf("!"); if (filters.annotation_filters[i].filter_exclude_flag == 1) printf("!");
printf("%s", filters.annotation_filters[i].pattern); printf("%s", filters.annotation_filters[i].pattern);
} }
printf(" "); printf(" ");
@ -1982,7 +2033,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
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].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.status_count++; filters.status_count++;
printf("Status-Code Filter hinzugefügt. Gesamt: %d\n", filters.status_count); printf("Status-Code Filter hinzugefügt. Gesamt: %d\n", filters.status_count);
@ -2004,7 +2055,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
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].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.ip_count++; filters.ip_count++;
printf("IP-Filter hinzugefügt. Gesamt: %d\n", filters.ip_count); printf("IP-Filter hinzugefügt. Gesamt: %d\n", filters.ip_count);
@ -2076,7 +2127,7 @@ int menu_set_filters(){
new_time_filter.end_time.minute = end_minute; new_time_filter.end_time.minute = end_minute;
new_time_filter.end_time.second = end_second; new_time_filter.end_time.second = end_second;
new_time_filter.mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; new_time_filter.filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.time_filters[filters.time_count] = new_time_filter; filters.time_filters[filters.time_count] = new_time_filter;
filters.time_count++; filters.time_count++;
@ -2101,7 +2152,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
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].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.user_agent_count++; filters.user_agent_count++;
printf("User-Agent Filter hinzugefügt. Gesamt: %d\n", filters.user_agent_count); printf("User-Agent Filter hinzugefügt. Gesamt: %d\n", filters.user_agent_count);
@ -2123,7 +2174,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
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].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.method_count++; filters.method_count++;
printf("Method-Filter hinzugefügt. Gesamt: %d\n", filters.method_count); printf("Method-Filter hinzugefügt. Gesamt: %d\n", filters.method_count);
@ -2145,7 +2196,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
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].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.url_count++; filters.url_count++;
printf("URL-Filter hinzugefügt. Gesamt: %d\n", filters.url_count); printf("URL-Filter hinzugefügt. Gesamt: %d\n", filters.url_count);
} else if (choice == 7) { } else if (choice == 7) {
@ -2155,7 +2206,7 @@ int menu_set_filters(){
int filter_type = safe_read_integer("Auswahl: ", 1, 2); int filter_type = safe_read_integer("Auswahl: ", 1, 2);
if (filter_type < 0) continue; if (filter_type < 0) continue;
filters.annotation_flag_filter.mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; filters.annotation_flag_filter.filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.annotation_flag_filter_enabled = 1; filters.annotation_flag_filter_enabled = 1;
} else if (choice == 8) { } else if (choice == 8) {
if (filters.annotation_count >= MAX_FILTERS) { if (filters.annotation_count >= MAX_FILTERS) {
@ -2175,7 +2226,7 @@ int menu_set_filters(){
if (filter_type < 0) continue; if (filter_type < 0) continue;
strcpy(filters.annotation_filters[filters.annotation_count].pattern, pattern); strcpy(filters.annotation_filters[filters.annotation_count].pattern, pattern);
filters.annotation_filters[filters.annotation_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; filters.annotation_filters[filters.annotation_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0;
filters.annotation_count++; filters.annotation_count++;
printf("Annotations-Filter hinzugefügt. Gesamt: %d\n", filters.annotation_count); printf("Annotations-Filter hinzugefügt. Gesamt: %d\n", filters.annotation_count);
} else if (choice == -2) { } else if (choice == -2) {
@ -2203,32 +2254,32 @@ void menu_delete_filters(){
int filter_index = 1; int filter_index = 1;
for (int i = 0; i < filters.status_count; i++) { for (int i = 0; i < filters.status_count; i++) {
char* mode_str = (filters.status_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.status_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. Status-Code: %d (%s)\n", filter_index++, filters.status_filters[i].code, mode_str); printf("%2d. Status-Code: %d (%s)\n", filter_index++, filters.status_filters[i].code, mode_str);
} }
for (int i = 0; i < filters.method_count; i++) { for (int i = 0; i < filters.method_count; i++) {
char* mode_str = (filters.method_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.method_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. HTTP-Methode: \"%s\" (%s)\n", filter_index++, filters.method_filters[i].pattern, mode_str); printf("%2d. HTTP-Methode: \"%s\" (%s)\n", filter_index++, filters.method_filters[i].pattern, mode_str);
} }
for (int i = 0; i < filters.ip_count; i++) { for (int i = 0; i < filters.ip_count; i++) {
char* mode_str = (filters.ip_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.ip_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. IP-Adresse: %s (%s)\n", filter_index++, filters.ip_filters[i].ip_address, mode_str); printf("%2d. IP-Adresse: %s (%s)\n", filter_index++, filters.ip_filters[i].ip_address, mode_str);
} }
for (int i = 0; i < filters.user_agent_count; i++) { for (int i = 0; i < filters.user_agent_count; i++) {
char* mode_str = (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.user_agent_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. User-Agent: \"%s\" (%s)\n", filter_index++, filters.user_agent_filters[i].pattern, mode_str); printf("%2d. User-Agent: \"%s\" (%s)\n", filter_index++, filters.user_agent_filters[i].pattern, mode_str);
} }
for (int i = 0; i < filters.url_count; i++) { for (int i = 0; i < filters.url_count; i++) {
char* mode_str = (filters.url_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.url_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. URL-Pfad: \"%s\" (%s)\n", filter_index++, filters.url_filters[i].pattern, mode_str); printf("%2d. URL-Pfad: \"%s\" (%s)\n", filter_index++, filters.url_filters[i].pattern, mode_str);
} }
for (int i = 0; i < filters.time_count; i++) { for (int i = 0; i < filters.time_count; i++) {
char* mode_str = (filters.time_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.time_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. Zeitraum: %02d.%02d.%d %02d:%02d:%02d - %02d.%02d.%d %02d:%02d:%02d (%s)\n", printf("%2d. Zeitraum: %02d.%02d.%d %02d:%02d:%02d - %02d.%02d.%d %02d:%02d:%02d (%s)\n",
filter_index++, filter_index++,
filters.time_filters[i].start_time.day, filters.time_filters[i].start_time.day,
@ -2247,12 +2298,12 @@ void menu_delete_filters(){
} }
if (filters.annotation_flag_filter_enabled){ if (filters.annotation_flag_filter_enabled){
char* mode_str = (filters.annotation_flag_filter.mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.annotation_flag_filter.filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. Annotierte Einträge %s", filter_index++, mode_str); printf("%2d. Annotierte Einträge %s", filter_index++, mode_str);
} }
for (int i = 0; i < filters.annotation_count; i++) { for (int i = 0; i < filters.annotation_count; i++) {
char* mode_str = (filters.annotation_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; char* mode_str = (filters.annotation_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen";
printf("%2d. Annotations-Filter: \"%s\" (%s)\n", filter_index++, filters.annotation_filters[i].pattern, mode_str); printf("%2d. Annotations-Filter: \"%s\" (%s)\n", filter_index++, filters.annotation_filters[i].pattern, mode_str);
} }
@ -2531,7 +2582,7 @@ void menu_show_entries(){
} }
// Funktionen zum setzen der Filter (existierende Datenstrukturen) // Funktionen zum setzen der Filter (existierende Datenstrukturen)
void add_parsed_status_filter(char* value, filter_mode_t mode) { void add_parsed_status_filter(char* value, int filter_exclude_flag) {
if (filters.status_count >= MAX_FILTERS) { if (filters.status_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2539,7 +2590,7 @@ void add_parsed_status_filter(char* value, filter_mode_t mode) {
// Kovertierung des Statuscodes zu long mit Error handling // Kovertierung des Statuscodes zu long mit Error handling
char* endptr; char* endptr;
int status_code = strtol(value, &endptr, 10); int status_code = strtol(value, &endptr, 10);
if (*endptr != '\n'){ if (*endptr != '\0'){
printf("ERROR: Ungültiger Wert im Statuscode-Filter: %s", value); printf("ERROR: Ungültiger Wert im Statuscode-Filter: %s", value);
} }
if (status_code < 100 || status_code > 599) { if (status_code < 100 || status_code > 599) {
@ -2549,13 +2600,13 @@ void add_parsed_status_filter(char* value, filter_mode_t mode) {
// setzen des Filters // setzen des Filters
filters.status_filters[filters.status_count].code = status_code; filters.status_filters[filters.status_count].code = status_code;
filters.status_filters[filters.status_count].mode = mode; filters.status_filters[filters.status_count].filter_exclude_flag = filter_exclude_flag;
filters.status_count++; filters.status_count++;
printf("DEBUG: Filter hinzugefügt: %s%d\n", mode == FILTER_EXCLUDE ? "!" : "", status_code); if (flag_verbose) printf("DEBUG: Filter hinzugefügt: %s%d\n", filter_exclude_flag == 1 ? "!" : "", status_code);
} }
void add_parsed_ip_filter(char* value, filter_mode_t mode) { void add_parsed_ip_filter(char* value, int filter_exclude_flag) {
if (filters.ip_count >= MAX_FILTERS) { if (filters.ip_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2569,14 +2620,14 @@ void add_parsed_ip_filter(char* value, filter_mode_t mode) {
// setzen des Filters // setzen des Filters
strcpy(filters.ip_filters[filters.ip_count].ip_address, value); strcpy(filters.ip_filters[filters.ip_count].ip_address, value);
filters.ip_filters[filters.ip_count].mode = mode; filters.ip_filters[filters.ip_count].filter_exclude_flag = filter_exclude_flag;
filters.ip_count++; filters.ip_count++;
printf("DEBUG: IP-Adressfilter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: IP-Adressfilter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
} }
// gleiche Mechanik wie bei IP-Adresse // gleiche Mechanik wie bei IP-Adresse
void add_parsed_method_filter(char* value, filter_mode_t mode) { void add_parsed_method_filter(char* value, int filter_exclude_flag) {
if (filters.method_count >= MAX_FILTERS) { if (filters.method_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2588,14 +2639,14 @@ void add_parsed_method_filter(char* value, filter_mode_t mode) {
} }
strcpy(filters.method_filters[filters.method_count].pattern, value); strcpy(filters.method_filters[filters.method_count].pattern, value);
filters.method_filters[filters.method_count].mode = mode; filters.method_filters[filters.method_count].filter_exclude_flag = filter_exclude_flag;
filters.method_count++; filters.method_count++;
printf("DEBUG: Methoden-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: Methoden-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
} }
// gleiche Mechanik wie bei IP-Adresse // gleiche Mechanik wie bei IP-Adresse
void add_parsed_useragent_filter(char* value, filter_mode_t mode) { void add_parsed_useragent_filter(char* value, int filter_exclude_flag) {
if (filters.user_agent_count >= MAX_FILTERS) { if (filters.user_agent_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2607,14 +2658,14 @@ void add_parsed_useragent_filter(char* value, filter_mode_t mode) {
} }
strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, value); strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, value);
filters.user_agent_filters[filters.user_agent_count].mode = mode; filters.user_agent_filters[filters.user_agent_count].filter_exclude_flag = filter_exclude_flag;
filters.user_agent_count++; filters.user_agent_count++;
printf("DEBUG: User Agent Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: User Agent Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
} }
// gleiche Mechanik wie bei IP-Adresse // gleiche Mechanik wie bei IP-Adresse
void add_parsed_url_filter(char* value, filter_mode_t mode) { void add_parsed_url_filter(char* value, int filter_exclude_flag) {
if (filters.url_count >= MAX_FILTERS) { if (filters.url_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2626,14 +2677,14 @@ void add_parsed_url_filter(char* value, filter_mode_t mode) {
} }
strcpy(filters.url_filters[filters.url_count].pattern, value); strcpy(filters.url_filters[filters.url_count].pattern, value);
filters.url_filters[filters.url_count].mode = mode; filters.url_filters[filters.url_count].filter_exclude_flag = filter_exclude_flag;
filters.url_count++; filters.url_count++;
printf("DEBUG: URL/Payload-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: URL/Payload-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
} }
// Parsen des Timestamp-Filters ist etwas komplexer, da er in die Datenstruktur geschrieben werden muss. // Parsen des Timestamp-Filters ist etwas komplexer, da er in die Datenstruktur geschrieben werden muss.
void add_parsed_timerange_filter(char* value, filter_mode_t mode) { void add_parsed_timerange_filter(char* value, int filter_exclude_flag) {
if (filters.time_count >= MAX_FILTERS) { if (filters.time_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2760,14 +2811,14 @@ void add_parsed_timerange_filter(char* value, filter_mode_t mode) {
new_time_filter.end_time.minute = end_minute; new_time_filter.end_time.minute = end_minute;
new_time_filter.end_time.second = end_second; new_time_filter.end_time.second = end_second;
new_time_filter.mode = mode; new_time_filter.filter_exclude_flag = filter_exclude_flag;
// Logik hier: der neue Filter wird stets an einen neuen Index geschrieben. Dieser ergibt sich aus der aktuellen ANZAHL der existierenden Zeitfilter. Das funktioniert, weil der index bei 0 beginnt // Logik hier: der neue Filter wird stets an einen neuen Index geschrieben. Dieser ergibt sich aus der aktuellen ANZAHL der existierenden Zeitfilter. Das funktioniert, weil der index bei 0 beginnt
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("DEBUG: Zeitraum-Filter hinzugefügt (%s): %04d-%02d-%02d %02d:%02d:%02d bis %04d-%02d-%02d %02d:%02d:%02d\n", if (flag_verbose) printf("DEBUG: Zeitraum-Filter hinzugefügt (%s): %04d-%02d-%02d %02d:%02d:%02d bis %04d-%02d-%02d %02d:%02d:%02d\n",
mode == FILTER_EXCLUDE ? "ausschließen" : "einschließen", filter_exclude_flag == 1 ? "ausschließen" : "einschließen",
new_time_filter.start_time.year, new_time_filter.start_time.month, new_time_filter.start_time.day, new_time_filter.start_time.year, new_time_filter.start_time.month, new_time_filter.start_time.day,
new_time_filter.start_time.hour, new_time_filter.start_time.minute, new_time_filter.start_time.second, new_time_filter.start_time.hour, new_time_filter.start_time.minute, new_time_filter.start_time.second,
new_time_filter.end_time.year, new_time_filter.end_time.month, new_time_filter.end_time.day, new_time_filter.end_time.year, new_time_filter.end_time.month, new_time_filter.end_time.day,
@ -2775,25 +2826,25 @@ void add_parsed_timerange_filter(char* value, filter_mode_t mode) {
} }
// recht einfache Mechanik für den Bool´schen Filter für annotierte Einträge // recht einfache Mechanik für den Bool´schen Filter für annotierte Einträge
void add_parsed_annotated_filter(char* value, filter_mode_t mode) { void add_parsed_annotated_filter(char* value, int filter_exclude_flag) {
if (strcmp(value, "true") == 0) { if (strcmp(value, "true") == 0) {
filters.annotation_flag_filter.annotation_flag_is_present = 1; filters.annotation_flag_filter.annotation_flag_is_present = 1;
filters.annotation_flag_filter.mode = mode; filters.annotation_flag_filter.filter_exclude_flag = filter_exclude_flag;
filters.annotation_flag_filter_enabled = 1; filters.annotation_flag_filter_enabled = 1;
printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
// falls doch mal jemand false eingibt // falls doch mal jemand false eingibt
} else if (strcmp(value, "false") == 0) { } else if (strcmp(value, "false") == 0) {
filters.annotation_flag_filter.annotation_flag_is_present = 0; filters.annotation_flag_filter.annotation_flag_is_present = 0;
filters.annotation_flag_filter.mode = mode; filters.annotation_flag_filter.filter_exclude_flag = filter_exclude_flag;
filters.annotation_flag_filter_enabled = 1; filters.annotation_flag_filter_enabled = 1;
printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); if (flag_verbose) printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value);
} else { } else {
printf("WARNING: Ungültiger Wert für --annotated Filter: %s (nur 'true' unterstützt)\n", value); printf("WARNING: Ungültiger Wert für --annotated Filter: %s (nur 'true' unterstützt)\n", value);
} }
} }
// Wieder gleiche Mechanik wie beim User Agent etc // Wieder gleiche Mechanik wie beim User Agent etc
void add_parsed_annotation_filter(char* value, filter_mode_t mode) { void add_parsed_annotation_filter(char* value, int filter_exclude_flag) {
if (filters.annotation_count >= MAX_FILTERS) { if (filters.annotation_count >= MAX_FILTERS) {
printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value);
return; return;
@ -2805,11 +2856,11 @@ void add_parsed_annotation_filter(char* value, filter_mode_t mode) {
} }
strcpy(filters.annotation_filters[filters.annotation_count].pattern, value); strcpy(filters.annotation_filters[filters.annotation_count].pattern, value);
filters.annotation_filters[filters.annotation_count].mode = mode; filters.annotation_filters[filters.annotation_count].filter_exclude_flag = filter_exclude_flag;
filters.annotation_count++; filters.annotation_count++;
printf("DEBUG: Annotations-Filter hinzugefügt: %s%s\n", if (flag_verbose) printf("DEBUG: Annotations-Filter hinzugefügt: %s%s\n",
mode == FILTER_EXCLUDE ? "!" : "", value); filter_exclude_flag == 1 ? "!" : "", value);
} }
// Funktion zum Parsen der Filter-Werte, die mit --<Filtertyp>=<Werte,Komma-getrennt> übergeben werden. // Funktion zum Parsen der Filter-Werte, die mit --<Filtertyp>=<Werte,Komma-getrennt> übergeben werden.
@ -2828,31 +2879,31 @@ void parse_filter_values(char* values_str, char* filter_type) {
// Sollte der Nutzer Leerzeichen verwendet haben, müssen diese übersprungen werden // Sollte der Nutzer Leerzeichen verwendet haben, müssen diese übersprungen werden
while (*token == ' ') token++; while (*token == ' ') token++;
// setzen des Modus, Standard inklusiv // setzen des Modus, Standard inklusiv
filter_mode_t mode = FILTER_INCLUDE; int filter_exclude_flag = 0;
// ..mit !-Präfix exklusiv. // ..mit !-Präfix exklusiv.
if (*token == '!') { if (*token == '!') {
mode = FILTER_EXCLUDE; filter_exclude_flag = 1;
token++; // den Pointer vom ! weiteriterieren, dieser ist nicht Teil des Filters token++; // den Pointer vom ! weiteriterieren, dieser ist nicht Teil des Filters
} }
if (strlen(token) > 0) { if (strlen(token) > 0) {
// wenn das token Werte hat, werden die entsprechenden Funktionen aufgerufen, die die Filter setzen // wenn das token Werte hat, werden die entsprechenden Funktionen aufgerufen, die die Filter setzen
if (strcmp(filter_type, "status") == 0) { if (strcmp(filter_type, "status") == 0) {
add_parsed_status_filter(token, mode); add_parsed_status_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "ip") == 0) { } else if (strcmp(filter_type, "ip") == 0) {
add_parsed_ip_filter(token, mode); add_parsed_ip_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "method") == 0) { } else if (strcmp(filter_type, "method") == 0) {
add_parsed_method_filter(token, mode); add_parsed_method_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "useragent") == 0) { } else if (strcmp(filter_type, "useragent") == 0) {
add_parsed_useragent_filter(token, mode); add_parsed_useragent_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "url") == 0) { } else if (strcmp(filter_type, "url") == 0) {
add_parsed_url_filter(token, mode); add_parsed_url_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "timerange") == 0) { } else if (strcmp(filter_type, "timerange") == 0) {
add_parsed_timerange_filter(token, mode); add_parsed_timerange_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "annotated") == 0) { } else if (strcmp(filter_type, "annotated") == 0) {
add_parsed_annotated_filter(token, mode); add_parsed_annotated_filter(token, filter_exclude_flag);
} else if (strcmp(filter_type, "annotation") == 0) { } else if (strcmp(filter_type, "annotation") == 0) {
add_parsed_annotation_filter(token, mode); add_parsed_annotation_filter(token, filter_exclude_flag);
} }
} }
// nächste Iteration - nächstes token einlesen, damit die while-Schleife weiteriteriert // nächste Iteration - nächstes token einlesen, damit die while-Schleife weiteriteriert
@ -2903,10 +2954,10 @@ int parse_filter_argument(char* arg) {
} else if (strstr(filter_type, "mode") != NULL) { } else if (strstr(filter_type, "mode") != NULL) {
if (strstr(values, "and") != NULL || strstr(values, "AND") != NULL) { if (strstr(values, "and") != NULL || strstr(values, "AND") != NULL) {
filters.combination_mode = 0; filters.combination_mode = 0;
printf("DEBUG: AND-Modus gesetzt\n"); if (flag_verbose) printf("DEBUG: AND-Modus gesetzt\n");
} else if (strstr(values, "or") != NULL || strstr(values, "OR") != NULL) { } else if (strstr(values, "or") != NULL || strstr(values, "OR") != NULL) {
filters.combination_mode = 1; filters.combination_mode = 1;
printf("DEBUG: OR-Modus gesetzt\n"); if (flag_verbose) printf("DEBUG: OR-Modus gesetzt\n");
} else { } else {
printf("WARNING: ungültiger Modus-Wert: %s ('and' oder 'oder' möglich)\n", values); printf("WARNING: ungültiger Modus-Wert: %s ('and' oder 'oder' möglich)\n", values);
} }
@ -3010,6 +3061,7 @@ int main(int argc, char* argv[]) {
int flag_interactive = 0; int flag_interactive = 0;
int flag_export = 0; int flag_export = 0;
int flag_help = 0; int flag_help = 0;
// int flag_verbose = 0; - global definiert
char export_filename[90]; char export_filename[90];
int flag_has_filename = 0; int flag_has_filename = 0;
@ -3039,6 +3091,8 @@ int main(int argc, char* argv[]) {
} else if (strcmp(argv[i], "-h")==0) { } else if (strcmp(argv[i], "-h")==0) {
flag_help = 1; flag_help = 1;
} else if (strcmp(argv[i], "-v")==0) {
flag_verbose = 1;
} }
} }
} }
@ -3074,7 +3128,7 @@ int main(int argc, char* argv[]) {
} else if (choice == 3) { } else if (choice == 3) {
export_filtered_entries(0); export_filtered_entries(0);
} else if (choice == 4) { } else if (choice == 4) {
printf("Programmende\n"); if (flag_verbose) printf("DEBUG: Programmende\n");
break; break;
} else if (choice == -4) { } else if (choice == -4) {
break; break;