package main import ( "execguard/core/alert" "execguard/core/configure" "execguard/core/hasher" "execguard/core/make_key" "execguard/core/monitor" "execguard/core/scanner" "execguard/core/sys_database" "database/sql" "flag" "log" "os" "path/filepath" _ "github.com/mattn/go-sqlite3" ) const ( configFileDefault = "/etc/execguard/config.json" dbFileDefault = "/etc/execguard/system.db" logFileDefault = "/var/log/execguard.log" mailPathDefault = "/usr/bin/mail" ) var ( configFile string dbFile string logFile string mailPath string configFlag string dbFlag string logFlag string mailFlag string initMode bool initFile string updateFile string migrateMode bool newKey bool config *configure.Config ) func main() { var err error var log log.Logger flag.StringVar(&configFlag, "config", "", "use specified file for config") flag.StringVar(&dbFlag, "db", "", "use specified file for database") flag.StringVar(&logFlag, "log", "", "use specified file for Logging") flag.StringVar(&mailFlag, "mail", "", "use specified file for Mail sending") flag.BoolVar(&initMode, "init", false, "initialize and populate allowed executable database") flag.StringVar(&initFile, "initFile", "", "file containing files to add to allowed database with hash") flag.StringVar(&updateFile, "update", "", "add specified file to allowed database with hash") flag.BoolVar(&migrateMode, "migrate", false, "recompute hashes of all allowed paths using current settings") flag.BoolVar(&newKey, "newKey", false, "generate a new XXTEA-compatible encryption key") flag.Parse() if os.Geteuid() != 0 { log.Fatal("This program must be run as root") os.Exit(1) // Exit with status code 1 } scanner.SetModes(initMode, initFile, updateFile, migrateMode) monitor.SetModes(initMode, initFile, updateFile, migrateMode) sys_database.SetModes(initMode, initFile, updateFile, migrateMode) if configFlag != "" { configFile = configFlag } else { configFile = configFileDefault } config, err := configure.LoadConfig(configFile) if err != nil { log.Fatalf("Error loading config: %v", err) os.Exit(3) // Exit with status code 3 } hasher.SetGlobalConfig(*config) alert.SetGlobalConfig(*config) monitor.SetGlobalConfig(*config) scanner.SetGlobalConfig(*config) // Set Vars...arguemtns first, then config, then defaults if dbFlag != "" { dbFile = dbFlag } else if config.DbFile != "" { dbFile = config.DbFile } else { dbFile = dbFileDefault } if logFlag != "" { logFile = logFlag } else if config.LogFile != "" { logFile = config.LogFile } else { logFile = logFileDefault } if mailFlag != "" { mailPath = mailFlag } else if config.MailProg != "" { mailPath = config.MailProg } else { mailPath = mailPathDefault } alert.SetGlobalMail(mailPath) logf, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatalf("Error opening log file: %v", err) } defer logf.Close() log.SetOutput(logf) if newKey { make_key.Make_a_key(log) return } db, err := sql.Open("sqlite3", dbFile) if err != nil { log.Fatalf("Error opening database: %v", err) os.Exit(2) // Exit with status code 2 } defer db.Close() sys_database.CreateTable(db, log) if initFile != "" { absPath, err := filepath.Abs(initFile) if err != nil { log.Fatalf("Invalid init file path: %v", err) os.Exit(1) // Exit with status code 1 } sys_database.RunInit(db, log, absPath) return } if updateFile != "" { absPath, err := filepath.Abs(updateFile) if err != nil { log.Fatalf("Invalid update file path: %v", err) os.Exit(1) // Exit with status code 1 } sys_database.AddToAllowed(db, log, absPath) log.Printf("Added to allowed list: %s", absPath) return } if migrateMode { sys_database.RunMigration(db, log) return } if config.ScanInterval > 0 { go func() { defer func() { if r := recover(); r != nil { log.Printf("Recovered from scan panic: %v", r) } }() scanner.PeriodicScan(config.ProtectedDirs, db, log, mailPath) }() } if err := monitor.MonitorExecutions(db, log, mailPath); err != nil { log.Fatalf("Execution monitoring failed: %v", err) os.Exit(4) // Exit with status code 4 } }