131 lines
2.5 KiB
Go
131 lines
2.5 KiB
Go
package whitelist
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/wuko233/sysmonitord/internal/config"
|
|
)
|
|
|
|
type Manager struct {
|
|
mu sync.RWMutex
|
|
official config.OfficialConfig
|
|
user config.UserConfig
|
|
mergedIgnore []string
|
|
}
|
|
|
|
func NewManager() *Manager {
|
|
return &Manager{
|
|
official: config.OfficialConfig{
|
|
WhitelistFiles: make(map[string][]string),
|
|
},
|
|
user: config.UserConfig{
|
|
SupplementFiles: make(map[string][]string),
|
|
SupplementProcesses: make(map[string]string),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (m *Manager) UpdateConfig(official config.OfficialConfig, user config.UserConfig) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
m.official = official
|
|
m.user = user
|
|
|
|
m.mergedIgnore = append([]string{}, m.official.IgnoredPaths...)
|
|
m.mergedIgnore = append(m.mergedIgnore, m.user.IgnoredPaths...)
|
|
}
|
|
|
|
func (m *Manager) IsPathIgnored(path string) bool {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
path = filepath.Clean(path)
|
|
for _, ignore := range m.mergedIgnore {
|
|
if strings.HasPrefix(path, filepath.Clean(ignore)) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CheckFileStatus 检查文件状态
|
|
// 返回: isWhitelisted(是否在白名单), isValid(Hash是否匹配), err
|
|
func (m *Manager) CheckFileStatus(path string) (bool, bool, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if m.IsPathIgnored((path)) {
|
|
return true, true, nil
|
|
}
|
|
|
|
hashes, exists := m.official.WhitelistFiles[path]
|
|
if !exists {
|
|
hashes, exists = m.user.SupplementFiles[path]
|
|
}
|
|
if !exists {
|
|
return false, false, nil
|
|
}
|
|
|
|
fileHash, err := CalculateFileHash(path)
|
|
if err != nil {
|
|
return true, false, fmt.Errorf("计算文件哈希失败: %v", err)
|
|
}
|
|
|
|
for _, h := range hashes {
|
|
if strings.EqualFold(h, fmt.Sprintf("%v", fileHash)) {
|
|
return true, true, nil
|
|
}
|
|
}
|
|
|
|
return true, false, nil
|
|
}
|
|
|
|
func CalculateFileHash(filePath string) (string, error) {
|
|
file, err := os.Open(filePath)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
hash := sha256.New()
|
|
if _, err := io.Copy(hash, file); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return hex.EncodeToString(hash.Sum(nil)), nil
|
|
}
|
|
|
|
func (m *Manager) IsProcessAllowed(procName string, cmdLine string) bool {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
for _, p := range m.official.WhitelistProcesses {
|
|
if p == procName {
|
|
return true
|
|
}
|
|
}
|
|
|
|
if _, ok := m.user.SupplementProcesses[procName]; ok {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (m *Manager) GetAuditServerUrl() string {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
return m.user.AuditServerUrl
|
|
}
|