goldwarden-vaultwarden-bitw.../agent/virtualagent.go

170 lines
4.4 KiB
Go
Raw Permalink Normal View History

2023-08-21 13:52:06 +02:00
package agent
import (
"context"
"encoding/json"
"fmt"
"os/user"
"time"
"github.com/quexten/goldwarden/agent/actions"
"github.com/quexten/goldwarden/agent/bitwarden"
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/config"
2023-08-24 03:22:03 +02:00
"github.com/quexten/goldwarden/agent/processsecurity"
2023-08-21 13:52:06 +02:00
"github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/vault"
2023-09-20 03:05:44 +02:00
"github.com/quexten/goldwarden/ipc/messages"
2023-08-21 13:52:06 +02:00
)
func writeErrorToLog(err error) {
log.Error(err.Error())
}
func serveVirtualAgent(recv chan []byte, send chan []byte, ctx context.Context, vault *vault.Vault, cfg *config.Config) {
for {
data := <-recv
2023-09-20 03:05:44 +02:00
var msg messages.IPCMessage
2023-08-21 13:52:06 +02:00
err := json.Unmarshal(data, &msg)
if err != nil {
writeErrorToLog(err)
continue
}
responseBytes := []byte{}
if action, actionFound := actions.AgentActionsRegistry.Get(msg.Type); actionFound {
user, _ := user.Current()
process := "goldwarden"
parent := "SINGLE_PROC_MODE"
grandparent := "SINGLE_PROC_MODE"
callingContext := sockets.CallingContext{
UserName: user.Name,
ProcessName: process,
ParentProcessName: parent,
GrandParentProcessName: grandparent,
}
2023-09-12 18:56:35 +02:00
payload, err := action(msg, cfg, vault, &callingContext)
2023-08-21 13:52:06 +02:00
if err != nil {
writeErrorToLog(err)
continue
}
responseBytes, err = json.Marshal(payload)
if err != nil {
writeErrorToLog(err)
continue
}
} else {
2023-09-20 03:05:44 +02:00
payload := messages.ActionResponse{
2023-08-21 13:52:06 +02:00
Success: false,
Message: "Action not found",
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
writeErrorToLog(err)
continue
}
responseBytes = payloadBytes
}
send <- responseBytes
}
}
2023-08-21 18:37:34 +02:00
func StartVirtualAgent(runtimeConfig config.RuntimeConfig) (chan []byte, chan []byte) {
2023-08-21 13:52:06 +02:00
ctx := context.Background()
2023-12-22 08:02:23 +01:00
var keyring crypto.Keyring
if runtimeConfig.UseMemguard {
keyring = crypto.NewMemguardKeyring(nil)
} else {
keyring = crypto.NewMemoryKeyring(nil)
}
2023-08-21 13:52:06 +02:00
var vault = vault.NewVault(&keyring)
2023-08-21 18:37:34 +02:00
cfg, err := config.ReadConfig(runtimeConfig)
2023-08-21 13:52:06 +02:00
if err != nil {
2023-12-22 12:01:21 +01:00
var cfg = config.DefaultConfig(runtimeConfig.UseMemguard)
2023-08-21 13:52:06 +02:00
cfg.WriteConfig()
}
2023-08-21 18:37:34 +02:00
cfg.ConfigFile.RuntimeConfig = runtimeConfig
if cfg.ConfigFile.RuntimeConfig.ApiURI != "" {
cfg.ConfigFile.ApiUrl = cfg.ConfigFile.RuntimeConfig.ApiURI
}
if cfg.ConfigFile.RuntimeConfig.IdentityURI != "" {
cfg.ConfigFile.IdentityUrl = cfg.ConfigFile.RuntimeConfig.IdentityURI
}
2023-09-11 14:14:27 +02:00
if cfg.ConfigFile.RuntimeConfig.NotificationsURI != "" {
cfg.ConfigFile.NotificationsUrl = cfg.ConfigFile.RuntimeConfig.NotificationsURI
}
2023-08-21 18:37:34 +02:00
if cfg.ConfigFile.RuntimeConfig.DeviceUUID != "" {
cfg.ConfigFile.DeviceUUID = cfg.ConfigFile.RuntimeConfig.DeviceUUID
}
if !cfg.IsLocked() && !cfg.ConfigFile.RuntimeConfig.DoNotPersistConfig {
2023-08-21 13:52:06 +02:00
log.Warn("Config is not locked. SET A PIN!!")
token, err := cfg.GetToken()
if err == nil {
if token.AccessToken != "" {
bitwarden.RefreshToken(ctx, &cfg)
userSymmetricKey, err := cfg.GetUserSymmetricKey()
if err != nil {
fmt.Println(err)
}
2023-12-22 08:02:23 +01:00
var protectedUserSymetricKey crypto.SymmetricEncryptionKey
if keyring.IsMemguard {
protectedUserSymetricKey, err = crypto.MemguardSymmetricEncryptionKeyFromBytes(userSymmetricKey)
} else {
protectedUserSymetricKey, err = crypto.MemorySymmetricEncryptionKeyFromBytes(userSymmetricKey)
}
2023-08-21 13:52:06 +02:00
err = bitwarden.DoFullSync(context.WithValue(ctx, bitwarden.AuthToken{}, token.AccessToken), vault, &cfg, &protectedUserSymetricKey, true)
if err != nil {
fmt.Println(err)
}
}
}
}
2023-08-24 03:22:03 +02:00
processsecurity.DisableDumpable()
2023-12-23 08:37:17 +01:00
err = processsecurity.MonitorLocks(func() {
cfg.Lock()
vault.Clear()
vault.Keyring.Lock()
})
if err != nil {
log.Warn("Could not monitor screensaver: %s", err.Error())
}
2023-08-21 13:52:06 +02:00
go func() {
for {
time.Sleep(TokenRefreshInterval)
if !cfg.IsLocked() {
bitwarden.RefreshToken(ctx, &cfg)
}
}
}()
go func() {
for {
time.Sleep(FullSyncInterval)
if !cfg.IsLocked() {
token, err := cfg.GetToken()
if err != nil {
log.Warn("Could not get token: %s", err.Error())
continue
}
bitwarden.DoFullSync(context.WithValue(ctx, bitwarden.AuthToken{}, token), vault, &cfg, nil, false)
}
}
}()
recv := make(chan []byte)
send := make(chan []byte)
go func() {
go serveVirtualAgent(recv, send, ctx, vault, &cfg)
}()
return recv, send
}