diff --git a/README.md b/README.md index cde84b2..0fb78cd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,23 @@ # gokill + +gokill is aimed at activists, journalists and others that need to protect their data against access under all circumstances. +gokill falls under the category of anti-forensic tools, helping you to protect yourself against repression. +It is built for worst case scenarios when intruders physical gaining access to a device. +In such heated situations gokill helps you automatically executing tasks like: +- locking the screen +- notify someone +- deleting data +- encrypting partitions +- destroying encrypted partitions +- and many more + +the tasks gokill executes could be done by hand using shellscripts, cronjobs, daemons ect. +but that means everyone needs to figure it out for themselves, and eventually make mistakes. +the idea of gokill is to provide a wide variarity of possibilities out of the box while making sure they are well tested. + + +gokill aims to be highly configurable and easily extendable. + 'gokill' is a tool that completes some actions when a certain event occurs. actions can vary from shuting down the machine to sending mails over erasing data. actions can be triggert by certain conditions like specific outcomes of unix diff --git a/actions/actions.go b/actions/actions.go index 15af3e2..3d418f4 100644 --- a/actions/actions.go +++ b/actions/actions.go @@ -36,7 +36,7 @@ func (a StagedActions) executeInternal(f func(Action)) { continue } - fmt.Printf("Execute Stage %v\n", idx+1) + internal.Log.Infof("Execute Stage %v", idx+1) for actionidx, _ := range stage.Actions { go f(stage.Actions[actionidx]) } @@ -45,7 +45,7 @@ func (a StagedActions) executeInternal(f func(Action)) { err := <-a.ActionChan if err != nil { - fmt.Printf("Error occured on Stage %d: %s\n", idx+1, err) + internal.Log.Errorf("Error occured on Stage %d: %s", idx+1, err) } } } diff --git a/actions/printer.go b/actions/printer.go index 2019d2a..843d61a 100644 --- a/actions/printer.go +++ b/actions/printer.go @@ -2,7 +2,6 @@ package actions import ( "encoding/json" - "fmt" "unknown.com/gokill/internal" ) @@ -13,12 +12,12 @@ type Printer struct { } func (p Printer) Execute() { - fmt.Printf("Print action fires. Message: %s\n", p.Message) + internal.LogDoc(p).Infof("Print action fires. Message: %s", p.Message) p.ActionChan <- nil } func (p Printer) DryExecute() { - fmt.Printf("Print action fire test. Message: %s\n", p.Message) + internal.LogDoc(p).Infof("Print action fire test. Message: %s", p.Message) p.ActionChan <- nil } diff --git a/actions/send_matrix.go b/actions/send_matrix.go index 4b832d8..59b0992 100644 --- a/actions/send_matrix.go +++ b/actions/send_matrix.go @@ -53,7 +53,7 @@ func (s SendMatrix) sendMessage(message string) error { client.Crypto = cryptoHelper - fmt.Println("Matrix Client Now running") + internal.LogDoc(s).Info("Matrix Client Now running") syncCtx, cancelSync := context.WithCancel(context.Background()) var syncStopWait sync.WaitGroup syncStopWait.Add(1) @@ -72,8 +72,8 @@ func (s SendMatrix) sendMessage(message string) error { if err != nil { return fmt.Errorf("Failed to send event") } else { - fmt.Println("Matrix Client: Message sent") - fmt.Printf("Matrix Client: event_id: %s", resp.EventID.String()) + internal.LogDoc(s).Info("Matrix Client: Message sent") + internal.LogDoc(s).Infof("Matrix Client: event_id: %s", resp.EventID.String()) } cancelSync() @@ -87,22 +87,22 @@ func (s SendMatrix) sendMessage(message string) error { } func (s SendMatrix) DryExecute() { - fmt.Println("SendMatrix: Trying to send test message") + internal.LogDoc(s).Info("SendMatrix: Trying to send test message") err := s.sendMessage(s.TestMessage) if err != nil { - fmt.Println("SendMatrix: failed to send test message") + internal.LogDoc(s).Info("SendMatrix: failed to send test message") } s.ActionChan <- err } func (s SendMatrix) Execute() { - fmt.Println("SendMatrix: Trying to send message") + internal.LogDoc(s).Info("SendMatrix: Trying to send message") err := s.sendMessage(s.Message) if err != nil { - fmt.Println("SendMatrix: failed to send message") + internal.LogDoc(s).Info("SendMatrix: failed to send message") } s.ActionChan <- err diff --git a/actions/send_telegram.go b/actions/send_telegram.go index 0b88f8f..a1d2d5b 100644 --- a/actions/send_telegram.go +++ b/actions/send_telegram.go @@ -24,9 +24,6 @@ func (s SendTelegram) sendMessage(message string) error { } bot.Debug = true - - fmt.Printf("Authorized on account %s", bot.Self.UserName) - u := tgbotapi.NewUpdate(0) u.Timeout = 60 @@ -37,22 +34,22 @@ func (s SendTelegram) sendMessage(message string) error { } func (s SendTelegram) DryExecute() { - fmt.Println("SendTelegram: Trying to send test message") - err := s.sendMessage(s.TestMessage) + internal.LogDoc(s).Info("SendTelegram: Trying to send test message") + err := s.sendMessage(s.TestMessage) if err != nil { - fmt.Println("SendTelegram: failed to send test message") + internal.LogDoc(s).Info("SendTelegram: failed to send test message") } s.ActionChan <- err } func (s SendTelegram) Execute() { - fmt.Println("SendTelegram: Trying to send message") + internal.LogDoc(s).Info("SendTelegram: Trying to send message") err := s.sendMessage(s.Message) if err != nil { - fmt.Println("SendTelegram: failed to send message") + internal.LogDoc(s).Info("SendTelegram: failed to send message") } s.ActionChan <- err diff --git a/actions/shell_script.go b/actions/shell_script.go index b132e63..0300335 100644 --- a/actions/shell_script.go +++ b/actions/shell_script.go @@ -18,7 +18,6 @@ func isExecutableFile(path string) bool { fi, err := os.Lstat(path) if err != nil { - fmt.Println("Test executing Shellscript Failed.") return false } @@ -33,18 +32,18 @@ func isExecutableFile(path string) bool { } func (c ShellScript) DryExecute() { - fmt.Printf("Test Executing ShellScript:\n%s\n", c.Path) + internal.LogDoc(c).Infof("Test Executing ShellScript:\n%s", c.Path) _, err := os.Open(c.Path) if err != nil { - fmt.Println("Test executing Shellscript Failed.") + internal.LogDoc(c).Warning("Test executing Shellscript Failed.") c.ActionChan <- err return } if !isExecutableFile(c.Path) { - fmt.Println("Test executing Shellscript Failed.") + internal.LogDoc(c).Warning("Test executing Shellscript Failed.") c.ActionChan <- fmt.Errorf("File is not executable: %s", c.Path) return } @@ -54,7 +53,7 @@ func (c ShellScript) DryExecute() { func (c ShellScript) Execute() { if !isExecutableFile(c.Path) { - fmt.Println("Test executing Shellscript Failed.") + internal.LogDoc(c).Warning("Executing Shellscript Failed.") c.ActionChan <- fmt.Errorf("File is not executable: %s", c.Path) return } @@ -64,11 +63,11 @@ func (c ShellScript) Execute() { stdout, err := cmd.Output() if err != nil { - fmt.Println(err.Error()) - c.ActionChan <- err + internal.LogDoc(c).Warning("Failed to execute Shellscript") + c.ActionChan <- fmt.Errorf("Error during ShellScript execute: %s", err) } - fmt.Println(string(stdout[:])) + internal.LogDoc(c).Infof("Shellscript output:\n%s", string(stdout[:])) c.ActionChan <- nil } diff --git a/actions/shutdown.go b/actions/shutdown.go index 0973de9..86975df 100644 --- a/actions/shutdown.go +++ b/actions/shutdown.go @@ -1,7 +1,6 @@ package actions import ( - "fmt" "os/exec" "encoding/json" @@ -14,17 +13,17 @@ type Shutdown struct { } func (s Shutdown) DryExecute() { - fmt.Printf("shutdown -h %s\n", s.Timeout) - fmt.Println("Test Shutdown executed...") + internal.LogDoc(s).Infof("shutdown -h %s", s.Timeout) + internal.LogDoc(s).Info("Test Shutdown executed...") s.ActionChan <- nil } func (s Shutdown) Execute() { if err := exec.Command("shutdown", "-h", s.Timeout).Run(); err != nil { - fmt.Println("Failed to initiate shutdown:", err) + internal.LogDoc(s).Errorf("Failed to initiate shutdown: %s", err) } - fmt.Println("Shutdown executed...") + internal.LogDoc(s).Notice("Shutdown executed...") s.ActionChan <- nil } @@ -37,7 +36,7 @@ func (s Shutdown) Create(config internal.ActionConfig, c ActionResultChan) (Acti err := json.Unmarshal(config.Options, &result) if err != nil { - fmt.Println("Parsing Shutdown options failed.") + internal.LogDoc(s).Warning("Parsing Shutdown options failed.") return Shutdown{}, err } diff --git a/actions/timeout.go b/actions/timeout.go index d78a14b..a825313 100644 --- a/actions/timeout.go +++ b/actions/timeout.go @@ -2,7 +2,6 @@ package actions import ( "encoding/json" - "fmt" "time" "unknown.com/gokill/internal" @@ -18,7 +17,7 @@ func (t TimeOut) DryExecute() { } func (t TimeOut) Execute() { - fmt.Printf("Waiting %d seconds\n", t.Duration) + internal.LogDoc(t).Infof("Waiting %d seconds", t.Duration) time.Sleep(time.Duration(t.Duration) * time.Second) t.ActionChan <- nil } diff --git a/actions/unix_command.go b/actions/unix_command.go index 3df195f..2188baf 100644 --- a/actions/unix_command.go +++ b/actions/unix_command.go @@ -24,19 +24,19 @@ func isCommandAvailable(name string) bool { } func (c Command) DryExecute() { - fmt.Printf("Test Executing Command:\n%s\n", c.Command) + internal.LogDoc(c).Infof("Test Executing Command: %s", c.Command) command, _, err := c.splitCommandString() if err != nil { - fmt.Printf("Error during argument parsing of command '%s'\n", c.Command) - fmt.Println(err) + internal.LogDoc(c).Errorf("Error during argument parsing of command '%s'", c.Command) + c.ActionChan <- fmt.Errorf("Error on Command action: %s", err) return } isAvailable := isCommandAvailable(command) if !isAvailable { - fmt.Printf("Command %s not found\n", command) + internal.LogDoc(c).Warningf("Command %s not found", command) c.ActionChan <- fmt.Errorf("Command %s not found!", command) return } @@ -60,7 +60,7 @@ func (c Command) splitCommandString() (string, []string, error) { func (c Command) Execute() { command, args, err := c.splitCommandString() - fmt.Println("Executing command: ", c.Command) + internal.LogDoc(c).Infof("Executing command: ", c.Command) if err != nil { c.ActionChan <- err @@ -72,11 +72,11 @@ func (c Command) Execute() { stdout, err := cmd.Output() if err != nil { - fmt.Println(err.Error()) - c.ActionChan <- err + internal.LogDoc(c).Errorf("%s", err.Error()) + c.ActionChan <- fmt.Errorf("Executing Command '%s' failed: %s", c.Command, err) } - fmt.Println(string(stdout[:])) + internal.LogDoc(c).Infof("Command Output:\n%s", string(stdout[:])) c.ActionChan <- nil } diff --git a/cmd/docbuilder/docbuilder.go b/cmd/docbuilder/docbuilder.go index d7c1215..90f71d1 100644 --- a/cmd/docbuilder/docbuilder.go +++ b/cmd/docbuilder/docbuilder.go @@ -37,7 +37,7 @@ func writeToFile(path string, documenter internal.Documenter) error { f, err := os.Create(fileName) if err != nil { - fmt.Println(err) + internal.Log.Errorf("Error during writeToFile: %s", err) return err } @@ -46,7 +46,7 @@ func writeToFile(path string, documenter internal.Documenter) error { _, err = f.WriteString(getMarkdown(documenter)) if err != nil { - fmt.Println(err) + internal.Log.Errorf("Error during writeToFile: %s", err) return err } @@ -86,9 +86,12 @@ func printDocumentersSummary() { func main() { outputPath := flag.String("output", "", "path where docs/ shoud be created") - + verbose := flag.Bool("verbose", false, "log debug information") flag.Parse() + internal.InitLogger() + internal.SetVerbose(*verbose) + if *outputPath == "" { printDocumentersSummary() return diff --git a/cmd/gokill/gokill.go b/cmd/gokill/gokill.go index 6ccb5d0..80f32aa 100644 --- a/cmd/gokill/gokill.go +++ b/cmd/gokill/gokill.go @@ -37,19 +37,24 @@ func GetDocumentation() string { } func main() { + configFilePath := flag.String("c", "", "path to config file") showDoc := flag.Bool("d", false, "show doc") testRun := flag.Bool("t", false, "test run") + verbose := flag.Bool("verbose", false, "log debug info") flag.Parse() + internal.InitLogger() + internal.SetVerbose(*verbose) + if *showDoc { fmt.Print(GetDocumentation()) return } if *configFilePath == "" { - fmt.Println("No config file given. Use --help to show usage.") + internal.Log.Warning("No config file given. Use --help to show usage.") return } @@ -58,7 +63,7 @@ func main() { configFile, err := os.ReadFile(*configFilePath) if err != nil { - fmt.Println("Error loading config file: ", err) + internal.Log.Errorf("Error loading config file: %s", err) return } @@ -66,7 +71,7 @@ func main() { err = json.Unmarshal(configFile, &f) if err != nil { - fmt.Println(err) + internal.Log.Errorf("Error pasing json file: %s", err) return } @@ -75,7 +80,7 @@ func main() { trigger, err := triggers.NewTrigger(cfg) if err != nil { - fmt.Println(err) + internal.Log.Errorf("%s", err) return } diff --git a/docbuilder b/docbuilder new file mode 100755 index 0000000..03a1da5 Binary files /dev/null and b/docbuilder differ diff --git a/flake.nix b/flake.nix index 7f3261c..4cf2d4b 100644 --- a/flake.nix +++ b/flake.nix @@ -12,6 +12,7 @@ (utils.lib.eachSystem (utils.lib.defaultSystems) ( system: let pkgs = nixpkgs.legacyPackages.${system}; + currentVendorHash = "sha256-Q14p7L2Ez/kvBhMUxlyMA1I/XEIxgSXOp4dpmH/SQyI="; in { devShells.default = pkgs.mkShell { @@ -27,7 +28,7 @@ gokill = pkgs.buildGoModule rec { pname = "gokill"; version = "1.0"; - vendorHash = "sha256-8xHjVwNskgiSoDKbOpL2phHub1F21ios1t9BcZB944o="; + vendorHash = currentVendorHash; src = ./.; buildInputs = [ @@ -41,7 +42,7 @@ gokill-docbuilder = pkgs.buildGoModule rec { pname = "docbuilder"; version = "1.0"; - vendorHash = "sha256-8xHjVwNskgiSoDKbOpL2phHub1F21ios1t9BcZB944o="; + vendorHash = currentVendorHash; buildFLags = "-o . $dest/cmd/gokill/docbuilder"; src = ./.; diff --git a/go.mod b/go.mod index 5c3e620..32c09f6 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module unknown.com/gokill go 1.21.3 require ( + github.com/apsdehal/go-logger v0.0.0-20190515212710-b0d6ccfee0e6 github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/mattn/go-sqlite3 v1.14.17 maunium.net/go/mautrix v0.16.1 diff --git a/go.sum b/go.sum index 91de7a2..c64476c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/apsdehal/go-logger v0.0.0-20190515212710-b0d6ccfee0e6 h1:qISSdUEX4sjDHfdD/vf65fhuCh3pIhiILDB7ktjJrqU= +github.com/apsdehal/go-logger v0.0.0-20190515212710-b0d6ccfee0e6/go.mod h1:U3/8D6R9+bVpX0ORZjV+3mU9pQ86m7h1lESgJbXNvXA= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/gokill b/gokill new file mode 100755 index 0000000..26bf2f8 Binary files /dev/null and b/gokill differ diff --git a/internal/logging.go b/internal/logging.go new file mode 100644 index 0000000..9d21019 --- /dev/null +++ b/internal/logging.go @@ -0,0 +1,63 @@ +package internal + +import ( + "github.com/apsdehal/go-logger" + "fmt" + "os" +) + +var Log *logger.Logger +var documenterLoggers map[string]*logger.Logger +var verbose bool + +var formatNormal string = "%{message}" +var formatVerbose string = "%{time} %{level}: %{message}" +var formatModuleNormal string = "%{module}: %{message}" +var formatModuleVerbose string = "%{time} %{level} %{module}: %{message}" + +func InitLogger() error { + var err error + Log, err = logger.New("UsbDisconnect", 1, os.Stdout) + + if err != nil { + return fmt.Errorf("Logger initialization error: %s", err) + } + + documenterLoggers = make(map[string]*logger.Logger) + verbose = false + Log.SetLogLevel(logger.InfoLevel) + + return nil +} + +func LogDoc(documenter Documenter) *logger.Logger { + documenterLogger, ok := documenterLoggers[documenter.GetName()] + + if !ok { + documenterLogger, _ = logger.New(documenter.GetName(), 1, os.Stdout) + documenterLoggers[documenter.GetName()] = documenterLogger + } + + SetVerbose(verbose) + //documenterLogger.SetFormat("%{message}") + + return documenterLogger +} + +func SetVerbose(value bool) { + verbose = value + toggleVerbosity := func(l *logger.Logger, formatN string, formatV string) { + if value { + l.SetLogLevel(logger.DebugLevel) + l.SetFormat(formatV) + } else { + l.SetLogLevel(logger.InfoLevel) + l.SetFormat(formatN) + } + } + + toggleVerbosity(Log, formatNormal, formatVerbose) + for _, documenterLogger := range documenterLoggers { + toggleVerbosity(documenterLogger, formatModuleNormal, formatModuleVerbose) + } +} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..82dc9e1 --- /dev/null +++ b/test.sh @@ -0,0 +1,2 @@ +#/bin/sh +echo "hello world" diff --git a/triggers/ethernet.go b/triggers/ethernet.go index bba3b8b..d67d715 100644 --- a/triggers/ethernet.go +++ b/triggers/ethernet.go @@ -20,7 +20,7 @@ func isEthernetConnected(deviceName string) bool { content, err := os.ReadFile(fmt.Sprintf("/sys/class/net/%s/operstate", deviceName)) if err != nil { - fmt.Println(err) + internal.LogDoc(EthernetDisconnect{}).Errorf("Cant read devices operstate. Check the deviceName. error: %s", err) return false } diff --git a/triggers/timeout.go b/triggers/timeout.go index b046f1e..5f4677d 100644 --- a/triggers/timeout.go +++ b/triggers/timeout.go @@ -1,7 +1,6 @@ package triggers import ( "encoding/json" - "fmt" "time" "unknown.com/gokill/actions" @@ -14,10 +13,10 @@ type TimeOut struct { } func (t TimeOut) Listen() { - fmt.Println("TimeOut listens") - fmt.Println(t.Duration) + internal.LogDoc(t).Info("TimeOut listens") + internal.LogDoc(t).Infof("%d", t.Duration) time.Sleep(time.Duration(t.Duration) * time.Second) - fmt.Println("TimeOut fires") + internal.LogDoc(t).Notice("TimeOut fires") actions.Fire(t.action) } diff --git a/triggers/usb.go b/triggers/usb.go index b74416d..2081e92 100644 --- a/triggers/usb.go +++ b/triggers/usb.go @@ -3,7 +3,6 @@ package triggers import ( "encoding/json" "errors" - "fmt" "os" "time" @@ -35,8 +34,8 @@ func (t UsbDisconnect) Listen() { time.Sleep(1 * time.Second) } - fmt.Printf("Device %s detected.\n", t.DeviceName) - fmt.Println("UsbDisconnect Trigger is Armed") + internal.LogDoc(t).Infof("Device %s detected.\n", t.DeviceName) + internal.LogDoc(t).Notice("Trigger is Armed") } for {