progress
This commit is contained in:
		
							parent
							
								
									58237b1ec4
								
							
						
					
					
						commit
						e9cdb49877
					
				
							
								
								
									
										126
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								src/main.c
									
									
									
									
									
								
							@ -203,7 +203,7 @@ int read_safe_integer() {
 | 
			
		||||
// Speicher freigeben und mit 0 überschreiben (Prävention von use-after-free-Schwachstelle)
 | 
			
		||||
void cleanup_memory() {
 | 
			
		||||
    if (all_entries != NULL) {
 | 
			
		||||
        printf("%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)));
 | 
			
		||||
        free(all_entries);
 | 
			
		||||
        all_entries = NULL;
 | 
			
		||||
    }
 | 
			
		||||
@ -225,7 +225,7 @@ void mem_expand_dynamically() {
 | 
			
		||||
        int old_max = max_entries;
 | 
			
		||||
        max_entries = max_entries * GROWTH_FACTOR;
 | 
			
		||||
        
 | 
			
		||||
        printf("Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
 | 
			
		||||
        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));
 | 
			
		||||
        
 | 
			
		||||
@ -236,7 +236,7 @@ void mem_expand_dynamically() {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        all_entries = new_ptr;
 | 
			
		||||
        printf("Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
        printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -250,7 +250,7 @@ void allocate_initial_memory() {
 | 
			
		||||
        exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    printf("Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
 | 
			
		||||
    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) {
 | 
			
		||||
@ -540,7 +540,7 @@ void load_regular_file(char* filename) {
 | 
			
		||||
        printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    printf("Lade Datei: %s\n", filename);
 | 
			
		||||
    printf("INFO: Lade Datei: %s\n", filename);
 | 
			
		||||
    char line[MAX_LINE_LENGTH_BUF];
 | 
			
		||||
    int loaded_from_this_file = 0;
 | 
			
		||||
    while (fgets(line, sizeof(line), file) != NULL) {
 | 
			
		||||
@ -558,8 +558,8 @@ void load_log_file(char* path) {
 | 
			
		||||
    total_entries = 0;
 | 
			
		||||
    
 | 
			
		||||
    if (is_directory(path)) {
 | 
			
		||||
        printf("Verzeichnis erkannt: %s\n", path);
 | 
			
		||||
        printf("Suche nach .log Dateien...\n");
 | 
			
		||||
        printf("DEBUG: Verzeichnis erkannt: %s\n", path);
 | 
			
		||||
        printf("DEBUG: Suche nach .log Dateien...\n");
 | 
			
		||||
        
 | 
			
		||||
        DIR* dir = opendir(path);
 | 
			
		||||
        if (dir == NULL) {
 | 
			
		||||
@ -592,10 +592,10 @@ void load_log_file(char* path) {
 | 
			
		||||
        closedir(dir);
 | 
			
		||||
        
 | 
			
		||||
        if (files_found == 0) {
 | 
			
		||||
            printf("Keine .log Dateien im Verzeichnis gefunden.\n");
 | 
			
		||||
            printf("Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
 | 
			
		||||
            printf("WARNING: Keine .log Dateien im Verzeichnis gefunden.\n");
 | 
			
		||||
            printf("    Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("Insgesamt %d .log Dateien verarbeitet.\n", files_found);
 | 
			
		||||
            printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    } else {
 | 
			
		||||
@ -603,7 +603,7 @@ void load_log_file(char* path) {
 | 
			
		||||
        
 | 
			
		||||
        if (strstr(path, ".gz") != NULL) {
 | 
			
		||||
            printf("FEHLER: .gz Dateien werden in dieser Version nicht unterstützt!\n");
 | 
			
		||||
            printf("Lösung: Dekomprimieren Sie die Datei zuerst:\n");
 | 
			
		||||
            printf("    Lösung: Dekomprimieren Sie die Datei zuerst:\n");
 | 
			
		||||
            printf("        gunzip %s\n", path);
 | 
			
		||||
            printf("        Dann: %s %.*s\n", "PROGRAMM", (int)(strlen(path)-3), path);
 | 
			
		||||
            return;
 | 
			
		||||
@ -612,8 +612,8 @@ void load_log_file(char* path) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    printf("Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
 | 
			
		||||
    printf("Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
 | 
			
		||||
    printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
 | 
			
		||||
    printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase)
 | 
			
		||||
@ -981,19 +981,23 @@ void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Export in Timesketch-kompatiblem Format
 | 
			
		||||
void export_filtered_entries() {
 | 
			
		||||
    printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
 | 
			
		||||
void export_filtered_entries(char *filepath) {
 | 
			
		||||
    //90 chars + delimiter
 | 
			
		||||
    char filename[91];
 | 
			
		||||
    if (filepath == NULL) {
 | 
			
		||||
        printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
 | 
			
		||||
        if (scanf("%90s", filename) != 1) {
 | 
			
		||||
            printf("FEHLER: Ungültiger Dateiname!\n");
 | 
			
		||||
            clear_input_buffer();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    clear_input_buffer();
 | 
			
		||||
    } else {
 | 
			
		||||
        strncpy(filename, filepath, sizeof(filename) - 1);
 | 
			
		||||
        filename[sizeof(filename) - 1] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    // Dateiendung
 | 
			
		||||
    strcat(filename, ".csv");
 | 
			
		||||
    
 | 
			
		||||
    printf("\nINFO: Schreibe Datei %s...\n", filename);
 | 
			
		||||
    FILE* file = fopen(filename, "w");
 | 
			
		||||
    if (file == NULL) {
 | 
			
		||||
        printf("ERROR: Kann Datei '%s' nicht erstellen!\n", filename);
 | 
			
		||||
@ -1028,7 +1032,7 @@ void export_filtered_entries() {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fclose(file);
 | 
			
		||||
    printf("%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 {
 | 
			
		||||
@ -2150,7 +2154,7 @@ void menu_show_entries() {
 | 
			
		||||
            supress_preview = 1;
 | 
			
		||||
            show_filtered_entries(0);
 | 
			
		||||
        } else if (choice == 2) {
 | 
			
		||||
            export_filtered_entries();
 | 
			
		||||
            export_filtered_entries(0);
 | 
			
		||||
        } else if (choice == 3) {
 | 
			
		||||
            show_top_x_ips();
 | 
			
		||||
        } else if (choice == 4) {
 | 
			
		||||
@ -2165,24 +2169,67 @@ void menu_show_entries() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
    if (argc != 2) {
 | 
			
		||||
        printf("Verwendung: %s <nginx-log-datei-oder-verzeichnis>\n", argv[0]);
 | 
			
		||||
        printf("Unterstützte Formate: .log Dateien, sowie für rotierte Logs: .log.1 etc.\n");
 | 
			
		||||
        printf("Beispiele:\n");
 | 
			
		||||
        printf("  %s /var/log/nginx/access.log     (einzelne .log Datei)\n", argv[0]);
 | 
			
		||||
        printf("  %s /var/log/nginx/               (Verzeichnis mit .log Dateien)\n", argv[0]);
 | 
			
		||||
        printf("\nRotierte nginx-Logs (.gz-Archive) müssen manuell dekomprimiert werden:\n");
 | 
			
		||||
        printf("  1. Dekomprimieren: gunzip /var/log/nginx/*.gz\n");
 | 
			
		||||
        printf("  2. Dann ausführen: %s /var/log/nginx/\n", argv[0]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else if (argc == 3) {
 | 
			
		||||
void print_help(char* binary) {
 | 
			
		||||
    printf("\nNGINX EXAMINATOR\n");
 | 
			
		||||
    printf("Verwendung:\n");
 | 
			
		||||
    printf("  %s <LOGDATEI|VERZEICHNIS> -i                         Interaktiver Modus (Filter/Analyse/Export)\n", binary);
 | 
			
		||||
    printf("  %s <LOGDATEI|VERZEICHNIS> -e <DATEINAME(optional)>   Export generieren\n", binary);
 | 
			
		||||
    printf("  %s                        -h    Diese Hilfe anzeigen\n", binary);
 | 
			
		||||
 | 
			
		||||
    printf("\nArgumente:\n");
 | 
			
		||||
    printf("  <LOGDATEI|VERZEICHNIS>   Pfad zu einer einzelnen *.log Datei ODER zu einem Ordner,\n");
 | 
			
		||||
    printf("                           der eine oder mehrere *.log / *.log.N Dateien enthält.\n");
 | 
			
		||||
 | 
			
		||||
    printf("\nFlags:\n");
 | 
			
		||||
    printf("  -i   Startet interaktiven Modus mit Filtern (Status, Methode, IP, Zeitraum,\n");
 | 
			
		||||
    printf("       User-Agent, URL-Teilstring), Vorschau, Statistiken und CSV-Export (Timesketch).\n");
 | 
			
		||||
    printf("  -e   Generiert Timesketch-kompatible CSV-Datei, nimmt optional Dateinamen entgegen.\n");
 | 
			
		||||
    printf("  -h   Zeigt diese Hilfe an.\n");
 | 
			
		||||
 | 
			
		||||
    printf("\nUnterstützte Eingaben:\n");
 | 
			
		||||
    printf("  - Normale NGINX-Access-Logs: *.log\n");
 | 
			
		||||
    printf("  - Rotierte Logs: *.log.1, *.log.2, ... (rein textbasiert)\n");
 | 
			
		||||
    printf("  - GZIP-Archive (*.gz) werden NICHT direkt unterstützt.\n");
 | 
			
		||||
    printf("    Tipp: Dekomprimieren Sie vorher, z.B.:\n");
 | 
			
		||||
    printf("      gunzip /var/log/nginx/*.gz\n");
 | 
			
		||||
    printf("      %s /var/log/nginx/ -i\n", binary);
 | 
			
		||||
 | 
			
		||||
    printf("\nErwartetes NGINX-Logformat (default `log_format main`):\n");
 | 
			
		||||
    printf("  log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n");
 | 
			
		||||
    printf("                        '$status $body_bytes_sent \"$http_referer\" '\n");
 | 
			
		||||
    printf("                        '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n");
 | 
			
		||||
 | 
			
		||||
    printf("\nBeispielzeile (eine Zeile pro Request):\n");
 | 
			
		||||
    printf("  0.0.0.0 - - [31/Aug/2025:00:11:42 +0000] \"GET /.git/config HTTP/1.1\" 400 255 \"-\" \"Mozilla/5.0\" \"-\"\n");
 | 
			
		||||
 | 
			
		||||
    printf("\nBeispiele:\n");
 | 
			
		||||
    printf("  - Einzeldatei analysieren:\n");
 | 
			
		||||
    printf("      %s /var/log/nginx/access.log -i\n", binary);
 | 
			
		||||
    printf("  - Verzeichnis mit mehreren .log / .log.N Dateien:\n");
 | 
			
		||||
    printf("      %s /var/log/nginx/ -i\n", binary);
 | 
			
		||||
 | 
			
		||||
    printf("\nCSV-Export (Timesketch-kompatibel):\n");
 | 
			
		||||
    printf("  Spalten: datetime, timestamp_desc, ip_address, method, url_path, status_code,\n");
 | 
			
		||||
    printf("           bytes_sent, user_agent, source_file, parsing_timestamp\n");
 | 
			
		||||
 | 
			
		||||
    printf("\nHinweise & Einschränkungen:\n");
 | 
			
		||||
    printf("  - Parser erwartet das obige Standardformat. Abweichungen können zum Abbruch führen.\n");
 | 
			
		||||
    printf("  - Zeitzone aus dem Log wird gelesen, aber intern als einfache Felder verarbeitet.\n");
 | 
			
		||||
    printf("  - ATYPICAL-Methode: für fehlerhafte/binäre Requests innerhalb der \"request\"-Spalte.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
    if (argc <= 3) {
 | 
			
		||||
        print_help(argv[0]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("\nNGINX EXAMINATOR\n");
 | 
			
		||||
 | 
			
		||||
    allocate_initial_memory();
 | 
			
		||||
 | 
			
		||||
    if (strcmp(argv[2], "-i") == 0) {
 | 
			
		||||
        load_log_file(argv[1]);
 | 
			
		||||
        
 | 
			
		||||
        if (total_entries == 0) {
 | 
			
		||||
@ -2190,14 +2237,13 @@ int main(int argc, char* argv[]) {
 | 
			
		||||
            cleanup_memory();
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        int choice = 0;
 | 
			
		||||
        int stats_show = 0;
 | 
			
		||||
        while (choice != 4 && choice != -4) {
 | 
			
		||||
            show_status();
 | 
			
		||||
            if (stats_show == 1) {
 | 
			
		||||
                show_stats();
 | 
			
		||||
            int stats_show = 0;
 | 
			
		||||
                stats_show = 0;
 | 
			
		||||
            }
 | 
			
		||||
            show_main_menu();
 | 
			
		||||
            
 | 
			
		||||
@ -2214,7 +2260,7 @@ int main(int argc, char* argv[]) {
 | 
			
		||||
            } else if (choice == 2) {
 | 
			
		||||
                menu_show_entries();
 | 
			
		||||
            } else if (choice == 3) {
 | 
			
		||||
            stats_show =1;
 | 
			
		||||
                stats_show = 1;
 | 
			
		||||
            } else if (choice == 4) {
 | 
			
		||||
                printf("Programmende\n");
 | 
			
		||||
                break;
 | 
			
		||||
@ -2224,7 +2270,17 @@ int main(int argc, char* argv[]) {
 | 
			
		||||
                printf("FEHLER: Ungültige Auswahl! Bitte wählen Sie 1-4 oder b/m/q.\n");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    } else if (strcmp(argv[2], "-e") == 0){
 | 
			
		||||
        load_log_file(argv[1]);
 | 
			
		||||
        if (argc == 4) {
 | 
			
		||||
            export_filtered_entries(argv[3]);
 | 
			
		||||
        } else {
 | 
			
		||||
            export_filtered_entries(NULL);
 | 
			
		||||
        }
 | 
			
		||||
    } else if (strcmp(argv[2], "-h") == 0){
 | 
			
		||||
        print_help(argv[0]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    cleanup_memory();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user