Exec Guardian
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
execguard/core/scanner/scanner.go

98 lines
2.4 KiB

package scanner
// Copyright (c) 2025 Robert Strutts <bobs@NewToFaith.com>
// License: MIT
// GIT: https://git.mysnippetsofcode.com/bobs/execguard
import (
"execguard/core/alert"
"execguard/core/configure"
"execguard/core/sys_database"
"database/sql"
"path/filepath"
"time"
"strings"
"fmt"
"log"
"os"
"io/fs"
"sync"
)
var (
config configure.Config
initMode bool
initFile string
updateFile string
migrateMode bool
dbMutex sync.Mutex
alertCache sync.Map
)
func SetModes(mode bool, file string, update string, migrate bool) {
initMode = mode
initFile = file
updateFile = update
migrateMode = migrate
}
func SetGlobalConfig(c configure.Config) {
config = c
}
func PeriodicScan(dirs []string, db *sql.DB, log *log.Logger, mailPath string, scanInterval int) {
skipSet := make(map[string]struct{})
for _, skip := range config.SkipDirs {
if abs, err := filepath.Abs(skip); err == nil {
skipSet[abs] = struct{}{}
}
}
interval := time.Duration(scanInterval) * time.Minute
// log.Printf("Starting periodic scan every %v...", interval)
for {
for _, dir := range dirs {
filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
absPath, err := filepath.Abs(path)
if err != nil {
return nil
}
// Skip if in any of the SkipDirs
for skipDir := range skipSet {
if strings.HasPrefix(absPath, skipDir) {
return filepath.SkipDir
}
}
if d.Type().IsRegular() {
info, err := d.Info()
if err != nil || (info.Mode().Perm()&0111 == 0) {
return nil
}
absPath, _ = filepath.EvalSymlinks(absPath)
if initMode {
sys_database.AddToAllowed(db, log, absPath)
} else if !sys_database.IsAllowed(db, log, absPath) {
log.Printf("Found unauthorized executable: %s", absPath)
os.Chmod(absPath, info.Mode()&^0111)
if _, seen := alertCache.LoadOrStore(absPath, struct{}{}); !seen {
go alert.SendAlert(fmt.Sprintf("Unauthorized execution attempt blocked: %s", absPath), db, log)
time.AfterFunc(10*time.Minute, func() {
alertCache.Delete(absPath)
})
}
}
}
return nil
})
}
time.Sleep(interval)
}
}