src/main.c aktualisiert
This commit is contained in:
		
							parent
							
								
									cd57025123
								
							
						
					
					
						commit
						2df49d7860
					
				
							
								
								
									
										222
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								src/main.c
									
									
									
									
									
								
							@ -30,9 +30,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
			
		||||
#define GROWTH_FACTOR 1.1 // wird in mem_expand_dynamically() genutzt, um den Speicher zu vergrößern
 | 
			
		||||
#define MAX_FILTERS 100
 | 
			
		||||
#define MAX_REQUEST_LENGTH 8192 // das hohe Limit ist erforderlich, da teilweise ausufernde JSON-Requests in nginx auflaufen können.
 | 
			
		||||
#define MAX_PREVIEW 10000
 | 
			
		||||
 | 
			
		||||
// 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_t {
 | 
			
		||||
    int day;
 | 
			
		||||
    int month;
 | 
			
		||||
    int year;
 | 
			
		||||
@ -42,13 +43,13 @@ struct simple_time {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Struktur für die Darstellung eines Standard-NGINX-Logeintrags.
 | 
			
		||||
struct log_entry {
 | 
			
		||||
struct log_entry_t {
 | 
			
		||||
    char ip_address[50]; // ausreichende Längenbegrenzung für IP-Adressen. Könnte theoretisch auch ipv6 (ungetestet)
 | 
			
		||||
    char request_method[10]; // GET, POST, PUT, DELETE, PROPFIND ...
 | 
			
		||||
    char url_path[MAX_REQUEST_LENGTH]; // Pfade können lang werden, insbesodere bei base64-Strings wie oft in Malware verwendet
 | 
			
		||||
    int status_code;
 | 
			
		||||
    int bytes_sent;
 | 
			
		||||
    struct simple_time time;
 | 
			
		||||
    struct simple_time_t time;
 | 
			
		||||
    char referrer[128];
 | 
			
		||||
    char user_agent[256];
 | 
			
		||||
    char source_file[256];
 | 
			
		||||
@ -56,57 +57,57 @@ struct log_entry {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Struktur für einen Status-Filtereintrag mit Inhalt & Modus
 | 
			
		||||
struct status_filter {
 | 
			
		||||
struct status_filter_t {
 | 
			
		||||
    int code;
 | 
			
		||||
    int filter_exclude_flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct method_filter {
 | 
			
		||||
struct method_filter_t {
 | 
			
		||||
    char pattern[10];
 | 
			
		||||
    int filter_exclude_flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// für IP-Adressen
 | 
			
		||||
struct ip_filter {
 | 
			
		||||
struct ip_filter_t {
 | 
			
		||||
    char ip_address[50];
 | 
			
		||||
    int filter_exclude_flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Filter für User-Agent
 | 
			
		||||
struct user_agent_filter {
 | 
			
		||||
struct user_agent_filter_t {
 | 
			
		||||
    char pattern[256];  
 | 
			
		||||
    int filter_exclude_flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Filter für URL-Pfad/Request
 | 
			
		||||
struct url_filter {
 | 
			
		||||
struct url_filter_t {
 | 
			
		||||
    char pattern[MAX_REQUEST_LENGTH];
 | 
			
		||||
    int filter_exclude_flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Struktur zum erhalten aller Filtereinträge, kann im Dialogbetrieb bearbeitet werden. Mit Zähler.
 | 
			
		||||
struct filter_system {
 | 
			
		||||
    struct status_filter status_filters[MAX_FILTERS];
 | 
			
		||||
struct filter_system_t {
 | 
			
		||||
    struct status_filter_t status_filters[MAX_FILTERS];
 | 
			
		||||
    int status_count;
 | 
			
		||||
 | 
			
		||||
    struct method_filter method_filters[MAX_FILTERS];
 | 
			
		||||
    struct method_filter_t method_filters[MAX_FILTERS];
 | 
			
		||||
    int method_count;
 | 
			
		||||
    
 | 
			
		||||
    struct ip_filter ip_filters[MAX_FILTERS];
 | 
			
		||||
    struct ip_filter_t ip_filters[MAX_FILTERS];
 | 
			
		||||
    int ip_count;
 | 
			
		||||
 | 
			
		||||
    struct user_agent_filter user_agent_filters[MAX_FILTERS];
 | 
			
		||||
    struct user_agent_filter_t user_agent_filters[MAX_FILTERS];
 | 
			
		||||
    int user_agent_count;
 | 
			
		||||
 | 
			
		||||
    struct url_filter url_filters[MAX_FILTERS];
 | 
			
		||||
    struct url_filter_t url_filters[MAX_FILTERS];
 | 
			
		||||
    int url_count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Initialisierung eines Arrays für die Logeinträge und weiterer Startvariablen
 | 
			
		||||
struct log_entry *all_entries = NULL;
 | 
			
		||||
struct log_entry_t *all_entries = NULL;
 | 
			
		||||
int max_entries = 0;
 | 
			
		||||
int total_entries = 0;
 | 
			
		||||
struct filter_system filters = {0};
 | 
			
		||||
struct filter_system_t filters = {0};
 | 
			
		||||
// für -v option
 | 
			
		||||
int flag_verbose = 0;
 | 
			
		||||
 | 
			
		||||
@ -160,7 +161,7 @@ int month_name_to_number(char* month_name) {
 | 
			
		||||
// Speicher freigeben und mit 0 überschreiben (Prävention von use-after-free-Schwachstelle)
 | 
			
		||||
void cleanup_memory(){
 | 
			
		||||
    if (all_entries != NULL){
 | 
			
		||||
        printf("\nDEBUG: %lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
        printf("\nDEBUG: %lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry_t)));
 | 
			
		||||
        free(all_entries);
 | 
			
		||||
        all_entries = NULL;
 | 
			
		||||
    }
 | 
			
		||||
@ -191,47 +192,49 @@ void mem_expand_dynamically(){
 | 
			
		||||
        
 | 
			
		||||
        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_t *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry_t));
 | 
			
		||||
        
 | 
			
		||||
        if (new_ptr == NULL){
 | 
			
		||||
            printf("ERROR: Speicher konnte nicht auf %d Einträge erweitert werden, ..\n", max_entries);
 | 
			
		||||
            printf("ERROR: Benötigter Speicher: %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
            printf("ERROR: Benötigter Speicher: %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry_t)));
 | 
			
		||||
            cleanup_and_exit();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        all_entries = new_ptr;
 | 
			
		||||
        if (flag_verbose) 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_t)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void allocate_initial_memory(){
 | 
			
		||||
    max_entries = INITIAL_ENTRIES; // Startwert 1000, globale Variable
 | 
			
		||||
    all_entries = malloc(max_entries * sizeof(struct log_entry));
 | 
			
		||||
    all_entries = malloc(max_entries * sizeof(struct log_entry_t));
 | 
			
		||||
    
 | 
			
		||||
    if (all_entries == NULL){
 | 
			
		||||
        printf("ERROR: Konnte %d Einträge nicht allozieren, ..\n", max_entries);
 | 
			
		||||
        printf("ERROR: %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
        printf("ERROR: %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry_t)));
 | 
			
		||||
        exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    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)));
 | 
			
		||||
    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_t)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void get_current_timestamp(char* buffer, int buffer_size) {
 | 
			
		||||
// aktuelle Timestamp erfassen
 | 
			
		||||
void get_current_timestamp(char* buffer){
 | 
			
		||||
    time_t raw_time;
 | 
			
		||||
    struct tm *time_info;
 | 
			
		||||
    
 | 
			
		||||
    int timestamp_buffer_size =32;
 | 
			
		||||
    time(&raw_time);
 | 
			
		||||
    time_info = localtime(&raw_time);
 | 
			
		||||
    
 | 
			
		||||
    if (time_info != NULL){
 | 
			
		||||
        strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", time_info);
 | 
			
		||||
        strftime(buffer, timestamp_buffer_size, "%Y-%m-%d %H:%M:%S", time_info);
 | 
			
		||||
    } else {
 | 
			
		||||
        snprintf(buffer, buffer_size, "UNKNOWN");
 | 
			
		||||
        sprintf(buffer, "UNKNOWN");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hilfsfunktion zum Prüfen, ob es sich beim Pfad um ein Directory handelt - für rekursives Parsen
 | 
			
		||||
// https://stackoverflow.com/questions/4553012/checking-if-a-file-is-a-directory-or-just-a-file
 | 
			
		||||
int is_directory(char* path){
 | 
			
		||||
    struct stat path_stat;
 | 
			
		||||
    if (stat(path, &path_stat) != 0){
 | 
			
		||||
@ -438,7 +441,7 @@ int parse_simple_log_line(char* line, int entry_index, char* source_file) { // N
 | 
			
		||||
        
 | 
			
		||||
        if (is_valid_method){
 | 
			
		||||
            // Normal parsen: HTTP-Methode bis zum nächsten Leerzeichen einlesen und speichern
 | 
			
		||||
            strcpy(all_entries[entry_index].request_method, temp_method);
 | 
			
		||||
            strncpy(all_entries[entry_index].request_method, temp_method,sizeof(all_entries[entry_index].request_method));
 | 
			
		||||
            while (*current_pos != ' ' && *current_pos != '\0'){
 | 
			
		||||
                current_pos++;
 | 
			
		||||
            }
 | 
			
		||||
@ -461,15 +464,17 @@ int parse_simple_log_line(char* line, int entry_index, char* source_file) { // N
 | 
			
		||||
        } else {
 | 
			
		||||
            // 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 "ATYPICAL" repräsentiert
 | 
			
		||||
            // strcpy reicht hier aus, da der Wert "ATYPICAL" hard-gecoded und somit deterministisch ist"
 | 
			
		||||
            strcpy(all_entries[entry_index].request_method, "ATYPICAL");
 | 
			
		||||
            
 | 
			
		||||
            // Read entire quoted content into url_path for forensic analysis
 | 
			
		||||
            // Kompletten Inhalt zwischen "" einlesen
 | 
			
		||||
            int i = 0;
 | 
			
		||||
            while (*current_pos != '"' && *current_pos != '\0' && i < sizeof(all_entries[entry_index].url_path) - 1){
 | 
			
		||||
                all_entries[entry_index].url_path[i] = *current_pos;
 | 
			
		||||
                i++;
 | 
			
		||||
                current_pos++;
 | 
			
		||||
            }
 | 
			
		||||
            // Nullterminator anfügen
 | 
			
		||||
            all_entries[entry_index].url_path[i] = '\0';
 | 
			
		||||
 | 
			
		||||
            // zum Ende des request-strings vorarbeiten, wenn der String zu lang war.
 | 
			
		||||
@ -507,19 +512,23 @@ int parse_simple_log_line(char* line, int entry_index, char* source_file) { // N
 | 
			
		||||
    }
 | 
			
		||||
    current_pos = skip_spaces(current_pos);
 | 
			
		||||
    
 | 
			
		||||
    // Parsen des Referrer-Feldes innerhalb "", wird übersprungen da nicht gespeichert
 | 
			
		||||
    // Parsen des Referrer-Feldes innerhalb ""
 | 
			
		||||
    if (*current_pos == '"'){
 | 
			
		||||
        current_pos++; // öffnendes Anführungszeichen überspringen
 | 
			
		||||
        // Referrer-Inhalt bis zum schließenden Anführungszeichen überspringen
 | 
			
		||||
        while (*current_pos != '"' && *current_pos != '\0') {
 | 
			
		||||
        // Referrer-Inhalt zwischen "" einlesen
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        while (*current_pos != '"' && *current_pos != '\0' && i < sizeof(all_entries[entry_index].referrer) - 1){
 | 
			
		||||
            all_entries[entry_index].referrer[i] = *current_pos;
 | 
			
		||||
            i++;
 | 
			
		||||
            current_pos++;
 | 
			
		||||
        }
 | 
			
		||||
        all_entries[entry_index].referrer[i] = '\0';
 | 
			
		||||
        
 | 
			
		||||
        if (*current_pos == '"') current_pos++; // schließendes Anführungszeichen überspringen
 | 
			
		||||
    } else {
 | 
			
		||||
        printf("ERROR: Unerwartetes Log-Format. Lediglich mit standard-nginx-accesslog kompatibel.\nDer Fehler ist beim Prüfen des Referrer-Feldes aufgetreten.\nLogeintrag: %s\n", line);
 | 
			
		||||
        cleanup_and_exit();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    current_pos = skip_spaces(current_pos);
 | 
			
		||||
    // parsen des user agents innerhalb ""
 | 
			
		||||
    if (*current_pos == '"'){
 | 
			
		||||
@ -536,7 +545,7 @@ int parse_simple_log_line(char* line, int entry_index, char* source_file) { // 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);\"\nLogeintrag: %s\n", line);
 | 
			
		||||
        cleanup_and_exit();
 | 
			
		||||
    }
 | 
			
		||||
    get_current_timestamp(all_entries[entry_index].parsing_timestamp, sizeof(all_entries[entry_index].parsing_timestamp));
 | 
			
		||||
    get_current_timestamp(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
 | 
			
		||||
@ -637,11 +646,11 @@ void load_log_file(char* path) {
 | 
			
		||||
            int needs_slash = (path_len > 0 && path[path_len - 1] != '/');
 | 
			
		||||
 | 
			
		||||
            if (is_log_file(filename)){
 | 
			
		||||
                (needs_slash) ? snprintf(full_path, sizeof(full_path), "%s/%s", path, filename) : snprintf(full_path, sizeof(full_path), "%s%s", path, filename);
 | 
			
		||||
                (needs_slash) ? sprintf(full_path, "%s/%s", path, filename) : sprintf(full_path, "%s%s", path, filename);
 | 
			
		||||
                load_regular_file(full_path);
 | 
			
		||||
                files_found++;
 | 
			
		||||
            } else if (strstr(filename, ".gz") != NULL){
 | 
			
		||||
                (needs_slash) ? snprintf(full_path, sizeof(full_path), "%s/%s", path, filename) : snprintf(full_path, sizeof(full_path), "%s%s", path, filename);
 | 
			
		||||
                (needs_slash) ? sprintf(full_path, "%s/%s", path, filename) : sprintf(full_path, "%s%s", path, filename);
 | 
			
		||||
                load_gz_file(full_path);
 | 
			
		||||
                files_found++;
 | 
			
		||||
            }
 | 
			
		||||
@ -665,7 +674,7 @@ void load_log_file(char* path) {
 | 
			
		||||
 | 
			
		||||
    printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
 | 
			
		||||
    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_t)), max_entries);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filterfunktion für den User-Agent. Nimmt den Datensatz entgegen und prüft gegen die gesetzten Filter, gibt dann 0 oder 1 zurück
 | 
			
		||||
@ -822,10 +831,34 @@ int count_filtered_entries(){
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// notwendig, um konformes Timestamp-Format aus simple_time struct zu generieren. Unterstützt derzeit nur UTC
 | 
			
		||||
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", time.year, time.month, time.day, time.hour, time.minute, time.second);
 | 
			
		||||
void format_datetime(struct simple_time_t time, char* buffer){
 | 
			
		||||
    sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d+00:00", time.year, time.month, time.day, time.hour, time.minute, time.second);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void show_preview(){
 | 
			
		||||
    char datetime[32];
 | 
			
		||||
    int lines_shown = 0;
 | 
			
		||||
    int count_filtered =0;
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    printf("| TIMESTAMP           | IP-Adresse      | HTTP-METHODE | PFAD/PAYLOAD                   | USERAGENT            | STATUSCODE | BYTES    | REFERRER             |\n");
 | 
			
		||||
    printf("|---------------------|-----------------|--------------|--------------------------------|----------------------|------------|----------|----------------------|\n");
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < MAX_PREVIEW; i++){
 | 
			
		||||
        if (passes_filter(i)){
 | 
			
		||||
            format_datetime(all_entries[i].time, datetime);
 | 
			
		||||
            printf("| %-19.19s | %-15.15s | %-12.12s | %-30.30s | %-20.20s | %-10d | %-8d | %-20.20s |\n", datetime, all_entries[i].ip_address, all_entries[i].request_method, all_entries[i].url_path, all_entries[i].user_agent, all_entries[i].status_code, all_entries[i].bytes_sent, all_entries[i].referrer);
 | 
			
		||||
            lines_shown++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    for (int i = 0; i < total_entries; i++){
 | 
			
		||||
        if (passes_filter(i)){
 | 
			
		||||
            count_filtered++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n%d Zeilen von insgesamt %d Einträgen(gefiltert) angezeigt.\nInsgesamt %d Einträge im Datensatz.\n", lines_shown, total_entries, count_filtered);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void export_filtered_entries(char *filepath){
 | 
			
		||||
    // 90 chars +delimiter
 | 
			
		||||
    char filename[91];
 | 
			
		||||
@ -836,6 +869,7 @@ void export_filtered_entries(char *filepath) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // buffer overflow verhindern
 | 
			
		||||
        strncpy(filename, filepath, sizeof(filename) - 1);
 | 
			
		||||
        filename[sizeof(filename) - 1] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
@ -851,12 +885,12 @@ void export_filtered_entries(char *filepath) {
 | 
			
		||||
    // CSV-Kopfzeile für Timesketch-Kompatibilität
 | 
			
		||||
    fprintf(file, "datetime,message,timestamp_desc,ip_address,method,url_path,status_code,bytes_sent,user_agent,parsing_timestamp\n");
 | 
			
		||||
    
 | 
			
		||||
    char iso_datetime[32];
 | 
			
		||||
    char datetime[32];
 | 
			
		||||
    
 | 
			
		||||
    for (int i = 0; i < total_entries; i++){
 | 
			
		||||
        if (passes_filter(i)){
 | 
			
		||||
            format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime));
 | 
			
		||||
            fprintf(file, "%s,%s,\"NGINX Log\",%s,%s,%s,%d,%d,%s,%s\n", iso_datetime, all_entries[i].source_file, 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].parsing_timestamp);
 | 
			
		||||
            format_datetime(all_entries[i].time, datetime);
 | 
			
		||||
            fprintf(file, "%s,%s,\"NGINX Log\",%s,%s,%s,%d,%d,%s,%s,%s\n", datetime, all_entries[i].source_file, 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].referrer,all_entries[i].parsing_timestamp);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
@ -902,7 +936,7 @@ void apply_ip_filter(char* value, int filter_exclude_flag) {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // setzen des Filters
 | 
			
		||||
    strcpy(filters.ip_filters[filters.ip_count].ip_address, value);
 | 
			
		||||
    strncpy(filters.ip_filters[filters.ip_count].ip_address, value,sizeof(filters.ip_filters[filters.ip_count].ip_address));
 | 
			
		||||
    filters.ip_filters[filters.ip_count].filter_exclude_flag = filter_exclude_flag;
 | 
			
		||||
    filters.ip_count++;
 | 
			
		||||
    
 | 
			
		||||
@ -921,7 +955,7 @@ void apply_method_filter(char* value, int filter_exclude_flag) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    strcpy(filters.method_filters[filters.method_count].pattern, value);
 | 
			
		||||
    strncpy(filters.method_filters[filters.method_count].pattern,value, sizeof(filters.method_filters[filters.method_count].pattern));
 | 
			
		||||
    filters.method_filters[filters.method_count].filter_exclude_flag = filter_exclude_flag;
 | 
			
		||||
    filters.method_count++;
 | 
			
		||||
    
 | 
			
		||||
@ -940,7 +974,7 @@ void apply_useragent_filter(char* value, int filter_exclude_flag) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, value);
 | 
			
		||||
    strncpy(filters.user_agent_filters[filters.user_agent_count].pattern, value,sizeof(filters.user_agent_filters[filters.user_agent_count].pattern));
 | 
			
		||||
    filters.user_agent_filters[filters.user_agent_count].filter_exclude_flag = filter_exclude_flag;
 | 
			
		||||
    filters.user_agent_count++;
 | 
			
		||||
    
 | 
			
		||||
@ -959,7 +993,7 @@ void apply_url_filter(char* value, int filter_exclude_flag) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    strcpy(filters.url_filters[filters.url_count].pattern, value);
 | 
			
		||||
    strncpy(filters.url_filters[filters.url_count].pattern, value,sizeof(filters.url_filters[filters.url_count].pattern));
 | 
			
		||||
    filters.url_filters[filters.url_count].filter_exclude_flag = filter_exclude_flag;
 | 
			
		||||
    filters.url_count++;
 | 
			
		||||
    
 | 
			
		||||
@ -1054,6 +1088,7 @@ void print_help(char* binary) {
 | 
			
		||||
    printf("NGINX-Auditor (Beleg)\n");
 | 
			
		||||
    printf("Nutzung: %s <LOGFILE|VERZEICHNIS> [Flags]\n\n", binary);
 | 
			
		||||
    printf("Flags:\n");
 | 
			
		||||
    printf("    -i [Logfile|Verzeichnis]    Optional Eingabe definieren - Datei oder Verzeichnis; Standard /var/log/nginx\n");
 | 
			
		||||
    printf("    -e [Dateiname ohne Endung]  Export zu Timestamp-kompatiblem CSV\n");
 | 
			
		||||
    printf("    -f  --[Filterobjekt]        Filtern mit den folgenden Optionen:\n");
 | 
			
		||||
    printf("        --status=[HTTP-Statuscode],[Weiterer],[...]  HTTP Status Codes, z.B. 200, 404,301,...\n");
 | 
			
		||||
@ -1068,82 +1103,65 @@ void print_help(char* binary) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]){
 | 
			
		||||
    if (argc < 2) {
 | 
			
		||||
        print_help(argv[0]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("\nNGINX EXAMINATOR\n");
 | 
			
		||||
 | 
			
		||||
    // Dateipfad: wenn nicht angegeben, wird /var/log/nginx (Standardpfad) untersucht
 | 
			
		||||
    char* input_path;
 | 
			
		||||
    int arg_offset = 1;  // Offset für die args
 | 
			
		||||
    
 | 
			
		||||
    // Prüfen des ersten Zeichens des ersten Arguments - Pfad oder Flag?
 | 
			
		||||
    if (argv[1][0] == '-') {
 | 
			
		||||
        // Ist ein Flag - Standardpfad, Offset bleibt bei 1
 | 
			
		||||
        input_path = "/var/log/nginx/";
 | 
			
		||||
        arg_offset = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        input_path = argv[1];
 | 
			
		||||
        arg_offset = 2;  // Offset inkrementieren, Dateipfad schiebt die args nach hinten
 | 
			
		||||
    }
 | 
			
		||||
    char* input_path = "/var/log/nginx";  // Standardpfad
 | 
			
		||||
    char export_filename[50];
 | 
			
		||||
    int flag_export = 0;
 | 
			
		||||
    int flag_help = 0;
 | 
			
		||||
    // int flag_verbose = 0; - global definiert
 | 
			
		||||
 | 
			
		||||
    char export_filename[90];
 | 
			
		||||
    int flag_has_filename = 0;
 | 
			
		||||
 | 
			
		||||
    int flag_filter =0;
 | 
			
		||||
    int flag_has_export_filename = 0;
 | 
			
		||||
    int flag_showpreview =0;
 | 
			
		||||
    allocate_initial_memory();
 | 
			
		||||
 | 
			
		||||
    if (argc >= 2){
 | 
			
		||||
        // hier wird das offset angewendet
 | 
			
		||||
        for (int i=arg_offset; i<argc; i++) {
 | 
			
		||||
            if (strcmp(argv[i], "-e")==0) {
 | 
			
		||||
    for (int i=1; i<argc; i++){
 | 
			
		||||
        if (i==0){
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (starts_with(argv[i], "-i")){
 | 
			
		||||
            if (!starts_with(argv[i+1], "-")&& i+1<argc){
 | 
			
		||||
                input_path = argv[i+1];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (starts_with(argv[i], "-e")){
 | 
			
		||||
            flag_export =1;
 | 
			
		||||
                if (i+1<argc && argv[i+1][0]!='-'){
 | 
			
		||||
            if (!starts_with(argv[i+1], "-")&& i+1<argc){
 | 
			
		||||
                strncpy(export_filename, argv[i + 1], sizeof(export_filename) - 1);
 | 
			
		||||
                    flag_has_filename = 1;
 | 
			
		||||
                    i++; // Schleife weiter iterieren
 | 
			
		||||
                }
 | 
			
		||||
            } else if (strcmp(argv[i], "-f")==0) {
 | 
			
		||||
                // parsen der nachfolgenden Argumente --ip= usw.
 | 
			
		||||
                for (int j = i + 1; j < argc; j++) {
 | 
			
		||||
                    if (starts_with(argv[j], "--")) {
 | 
			
		||||
                        parse_filter_argument(argv[j]);
 | 
			
		||||
                    }else{
 | 
			
		||||
                        break;
 | 
			
		||||
                flag_has_export_filename =1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            } else if (strcmp(argv[i], "-h")==0) {
 | 
			
		||||
                flag_help = 1;
 | 
			
		||||
            } else if (strcmp(argv[i], "-v")==0) {
 | 
			
		||||
                flag_verbose = 1;
 | 
			
		||||
        if (starts_with(argv[i], "-f")){
 | 
			
		||||
            flag_filter = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if (starts_with(argv[i], "--")){
 | 
			
		||||
            parse_filter_argument(argv[i]);
 | 
			
		||||
        }
 | 
			
		||||
        if (starts_with(argv[i], "-v")){
 | 
			
		||||
            flag_verbose =1; // globale Variable oben definiert
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    // Aktionen basierend auf gesetzten flags ausführen
 | 
			
		||||
    if (flag_help == 1){
 | 
			
		||||
        if (starts_with(argv[i], "-s")){
 | 
			
		||||
            flag_showpreview =1;
 | 
			
		||||
            printf("Flag for show prewview set\n");
 | 
			
		||||
        }
 | 
			
		||||
        if (starts_with(argv[i], "-h")){
 | 
			
		||||
            print_help(argv[0]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else if (flag_export == 1) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    load_log_file(input_path);
 | 
			
		||||
        if (flag_has_filename == 1) {
 | 
			
		||||
    if (flag_export ==1){
 | 
			
		||||
        if (flag_has_export_filename){
 | 
			
		||||
            export_filtered_entries(export_filename);
 | 
			
		||||
        } else {
 | 
			
		||||
            export_filtered_entries(NULL);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // Standard-Verhalten: Logs laden und Zusammenfassung anzeigen
 | 
			
		||||
        load_log_file(input_path);
 | 
			
		||||
        int filtered_count = count_filtered_entries();
 | 
			
		||||
        printf("Geladen: %d Einträge, %d entsprechen den Filtern. Nutzen Sie -e zum Exportieren.\n", 
 | 
			
		||||
               total_entries, filtered_count);
 | 
			
		||||
        printf("Geladen: %d Einträge, %d entsprechen den Filtern. Nutzen Sie -e zum Exportieren.\n", total_entries, filtered_count);
 | 
			
		||||
    }
 | 
			
		||||
    if (flag_showpreview==1){
 | 
			
		||||
        printf("should show preview here\n");
 | 
			
		||||
        show_preview();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    cleanup_memory();
 | 
			
		||||
    printf("INFO: Ausführung beendet.\n");
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user