Add timeout to notifications
This commit is contained in:
parent
715e1eb30a
commit
794593a71f
|
@ -3,6 +3,7 @@ package actions
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/quexten/goldwarden/agent/bitwarden"
|
||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||
|
@ -85,7 +86,7 @@ func handleLogin(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault
|
|||
err = crypto.InitKeyringFromMasterKey(vault.Keyring, profile.Profile.Key, profile.Profile.PrivateKey, orgKeys, masterKey)
|
||||
if err != nil {
|
||||
defer func() {
|
||||
notify.Notify("Goldwarden", "Could not decrypt. Wrong password?", "", func() {})
|
||||
notify.Notify("Goldwarden", "Could not decrypt. Wrong password?", "", 10*time.Second, func() {})
|
||||
cfg.SetToken(config.LoginToken{})
|
||||
vault.Clear()
|
||||
}()
|
||||
|
@ -112,7 +113,7 @@ func handleLogin(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault
|
|||
}
|
||||
if err != nil {
|
||||
defer func() {
|
||||
notify.Notify("Goldwarden", "Could not decrypt. Wrong password?", "", func() {})
|
||||
notify.Notify("Goldwarden", "Could not decrypt. Wrong password?", "", 10*time.Second, func() {})
|
||||
cfg.SetToken(config.LoginToken{})
|
||||
vault.Clear()
|
||||
}()
|
||||
|
|
|
@ -2,7 +2,6 @@ package actions
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/quexten/goldwarden/agent/bitwarden"
|
||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||
|
@ -53,16 +52,25 @@ func handleUnlockVault(request messages.IPCMessage, cfg *config.Config, vault *v
|
|||
return
|
||||
}
|
||||
|
||||
actionsLog.Info("Unlocking vault...")
|
||||
if cfg.IsLoggedIn() {
|
||||
token, err := cfg.GetToken()
|
||||
if err == nil {
|
||||
if token.AccessToken != "" {
|
||||
ctx := context.Background()
|
||||
bitwarden.RefreshToken(ctx, cfg)
|
||||
gotToken := bitwarden.RefreshToken(ctx, cfg)
|
||||
if gotToken {
|
||||
actionsLog.Info("Token refreshed")
|
||||
} else {
|
||||
actionsLog.Warn("Token refresh failed")
|
||||
}
|
||||
token, err := cfg.GetToken()
|
||||
if err != nil {
|
||||
actionsLog.Error("Could not get token: %s", err.Error())
|
||||
}
|
||||
userSymmkey, err := cfg.GetUserSymmetricKey()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
actionsLog.Error("Could not get user symmetric key: %s", err.Error())
|
||||
}
|
||||
|
||||
var safeUserSymmkey crypto.SymmetricEncryptionKey
|
||||
|
@ -72,14 +80,18 @@ func handleUnlockVault(request messages.IPCMessage, cfg *config.Config, vault *v
|
|||
safeUserSymmkey, err = crypto.MemorySymmetricEncryptionKeyFromBytes(userSymmkey)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
actionsLog.Error("Could not create safe user symmetric key: %s", err.Error())
|
||||
}
|
||||
|
||||
err = bitwarden.DoFullSync(context.WithValue(ctx, bitwarden.AuthToken{}, token.AccessToken), vault, cfg, &safeUserSymmkey, true)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
actionsLog.Error("Could not sync: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
actionsLog.Warn("Access token is empty")
|
||||
}
|
||||
} else {
|
||||
actionsLog.Warn("Could not get token: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,12 +71,12 @@ func deviceType() string {
|
|||
func LoginWithApiKey(ctx context.Context, email string, cfg *config.Config, vault *vault.Vault) (LoginResponseToken, crypto.MasterKey, string, error) {
|
||||
clientID, err := cfg.GetClientID()
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get client ID: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get client ID: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not get client ID: %v", err)
|
||||
}
|
||||
clientSecret, err := cfg.GetClientSecret()
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get client secret: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get client secret: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not get client secret: %v", err)
|
||||
}
|
||||
|
||||
|
@ -93,19 +93,19 @@ func LoginWithApiKey(ctx context.Context, email string, cfg *config.Config, vaul
|
|||
var loginResponseToken LoginResponseToken
|
||||
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via API key: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via API key: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not login via API key: %v", err)
|
||||
}
|
||||
|
||||
password, err := pinentry.GetPassword("Bitwarden Password", "Enter your Bitwarden password")
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get password: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get password: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
||||
}
|
||||
|
||||
masterKey, err := crypto.DeriveMasterKey([]byte(strings.Clone(password)), email, crypto.KDFConfig{Type: crypto.KDFType(loginResponseToken.Kdf), Iterations: uint32(loginResponseToken.KdfIterations), Memory: uint32(loginResponseToken.KdfMemory), Parallelism: uint32(loginResponseToken.KdfParallelism)})
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not derive master key: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not derive master key: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
||||
}
|
||||
hashedPassword := b64enc.EncodeToString(pbkdf2.Key(masterKey.GetBytes(), []byte(password), 1, 32, sha256.New))
|
||||
|
@ -119,7 +119,7 @@ func LoginWithMasterpassword(ctx context.Context, email string, cfg *config.Conf
|
|||
if err := authenticatedHTTPPost(ctx, cfg.ConfigFile.ApiUrl+"/accounts/prelogin", &preLogin, preLoginRequest{
|
||||
Email: email,
|
||||
}); err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not pre-login: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not pre-login: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not pre-login: %v", err)
|
||||
}
|
||||
|
||||
|
@ -129,13 +129,13 @@ func LoginWithMasterpassword(ctx context.Context, email string, cfg *config.Conf
|
|||
|
||||
password, err := pinentry.GetPassword("Bitwarden Password", "Enter your Bitwarden password")
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get password: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not get password: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
||||
}
|
||||
|
||||
masterKey, err = crypto.DeriveMasterKey([]byte(strings.Clone(password)), email, crypto.KDFConfig{Type: crypto.KDFType(preLogin.KDF), Iterations: uint32(preLogin.KDFIterations), Memory: uint32(preLogin.KDFMemory), Parallelism: uint32(preLogin.KDFParallelism)})
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not derive master key: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not derive master key: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
||||
}
|
||||
|
||||
|
@ -158,14 +158,14 @@ func LoginWithMasterpassword(ctx context.Context, email string, cfg *config.Conf
|
|||
if ok && bytes.Contains(errsc.body, []byte("TwoFactor")) {
|
||||
loginResponseToken, err = Perform2FA(values, errsc, cfg, ctx)
|
||||
if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via two-factor: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via two-factor: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
||||
}
|
||||
} else if err != nil && strings.Contains(err.Error(), "Captcha required.") {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Captcha required"), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Captcha required"), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("captcha required, please login via the web interface")
|
||||
} else if err != nil {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via password: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not login via password: %v", err), "", 0, func() {})
|
||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not login via password: %v", err)
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ func RefreshToken(ctx context.Context, cfg *config.Config) bool {
|
|||
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
|
||||
if err != nil {
|
||||
authLog.Error("Could not refresh token: %s", err.Error())
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not refresh token: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not refresh token: %v", err), "", 0, func() {})
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ func RefreshToken(ctx context.Context, cfg *config.Config) bool {
|
|||
))
|
||||
if err != nil {
|
||||
authLog.Error("Could not refresh token: %s", err.Error())
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not refresh token: %v", err), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Could not refresh token: %v", err), "", 0, func() {})
|
||||
return false
|
||||
}
|
||||
cfg.SetToken(config.LoginToken{
|
||||
|
|
|
@ -35,7 +35,7 @@ func DoFullSync(ctx context.Context, vault *vault.Vault, config *config.Config,
|
|||
sync, err := Sync(ctx, config)
|
||||
if err != nil {
|
||||
log.Error("Could not sync: %v", err)
|
||||
notify.Notify("Goldwarden", "Could not sync", "", func() {})
|
||||
notify.Notify("Goldwarden", "Could not sync", "", 0, func() {})
|
||||
if allowCache {
|
||||
home, _ := os.UserHomeDir()
|
||||
sync, err = ReadVault(home + path)
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||
|
@ -131,7 +132,7 @@ func (c *Config) Unlock(password string) bool {
|
|||
|
||||
keyBuffer := NewBufferFromBytes(key, c.useMemguard)
|
||||
c.key = &keyBuffer
|
||||
notify.Notify("Goldwarden", "Vault Unlocked", "", func() {})
|
||||
notify.Notify("Goldwarden", "Vault Unlocked", "", 60*time.Second, func() {})
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -155,7 +156,7 @@ func (c *Config) Lock() {
|
|||
return
|
||||
}
|
||||
(*c.key).Wipe()
|
||||
notify.Notify("Goldwarden", "Vault Locked", "", func() {})
|
||||
notify.Notify("Goldwarden", "Vault Locked", "", 60*time.Second, func() {})
|
||||
}
|
||||
|
||||
func (c *Config) Purge() {
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
package notify
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
var closeListenerMap = make(map[uint32]func())
|
||||
var notificationID uint32 = 1000000
|
||||
|
||||
func Notify(title string, body string, actionName string, onclose func()) error {
|
||||
func Notify(title string, body string, actionName string, timeout time.Duration, onclose func()) error {
|
||||
bus, err := dbus.SessionBus()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -18,7 +21,10 @@ func Notify(title string, body string, actionName string, onclose func()) error
|
|||
if actionName != "" {
|
||||
actions = append(actions, actionName)
|
||||
}
|
||||
call := obj.Call("org.freedesktop.Notifications.Notify", 0, "goldwarden", uint32(0), "", title, body, actions, map[string]dbus.Variant{}, int32(60000))
|
||||
|
||||
notificationID++
|
||||
|
||||
call := obj.Call("org.freedesktop.Notifications.Notify", 0, "goldwarden", uint32(notificationID), "", title, body, actions, map[string]dbus.Variant{}, int32(60000))
|
||||
if call.Err != nil {
|
||||
return call.Err
|
||||
}
|
||||
|
@ -28,6 +34,18 @@ func Notify(title string, body string, actionName string, onclose func()) error
|
|||
id := call.Body[0].(uint32)
|
||||
closeListenerMap[id] = onclose
|
||||
|
||||
if timeout == 0 {
|
||||
return nil
|
||||
} else {
|
||||
go func(id uint32) {
|
||||
time.Sleep(timeout)
|
||||
call := obj.Call("org.freedesktop.Notifications.CloseNotification", 0, uint32(id))
|
||||
if call.Err != nil {
|
||||
return
|
||||
}
|
||||
}(id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/quexten/goldwarden/agent/config"
|
||||
"github.com/quexten/goldwarden/agent/notify"
|
||||
|
@ -125,9 +126,9 @@ func (vaultAgent vaultAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signatur
|
|||
var rand = rand.Reader
|
||||
log.Info("Sign Request for key: %s %s accepted", ssh.FingerprintSHA256(key), sshKey.Name)
|
||||
if isGit {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Git Signing Request Approved for %s", sshKey.Name), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("Git Signing Request Approved for %s", sshKey.Name), "", 10*time.Second, func() {})
|
||||
} else {
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("SSH Signing Request Approved for %s", sshKey.Name), "", func() {})
|
||||
notify.Notify("Goldwarden", fmt.Sprintf("SSH Signing Request Approved for %s", sshKey.Name), "", 10*time.Second, func() {})
|
||||
}
|
||||
return signer.Sign(rand, data)
|
||||
}
|
||||
|
|
|
@ -210,10 +210,14 @@ func StartUnixAgent(path string, runtimeConfig config.RuntimeConfig) error {
|
|||
token, err := cfg.GetToken()
|
||||
if err == nil {
|
||||
if token.AccessToken != "" {
|
||||
bitwarden.RefreshToken(ctx, &cfg)
|
||||
gotToken := bitwarden.RefreshToken(ctx, &cfg)
|
||||
if !gotToken {
|
||||
log.Warn("Could not get token")
|
||||
return false
|
||||
}
|
||||
userSymmetricKey, err := cfg.GetUserSymmetricKey()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Error("Could not get user symmetric key: %s", err.Error())
|
||||
}
|
||||
var protectedUserSymetricKey crypto.SymmetricEncryptionKey
|
||||
if vault.Keyring.IsMemguard {
|
||||
|
@ -224,11 +228,17 @@ func StartUnixAgent(path string, runtimeConfig config.RuntimeConfig) error {
|
|||
|
||||
err = bitwarden.DoFullSync(context.WithValue(ctx, bitwarden.AuthToken{}, token.AccessToken), vault, &cfg, &protectedUserSymetricKey, true)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Error("Could not sync: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
log.Warn("Access token is empty")
|
||||
}
|
||||
} else {
|
||||
log.Error("Could not get token: %s", err.Error())
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
log.Warn("Could not unlock: %s", err.Error())
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue