Rework systemauth

This commit is contained in:
Bernd Schoolmann 2023-09-19 21:49:56 +02:00
parent 368fe2bae6
commit e53a49b47a
No known key found for this signature in database
15 changed files with 166 additions and 78 deletions

View File

@ -31,4 +31,5 @@ package() {
cd "$pkgname-$pkgver" cd "$pkgname-$pkgver"
install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname
install -Dm644 "$srcdir/$pkgname-$pkgver/resources/com.quexten.goldwarden.policy" "$pkgdir/usr/share/polkit-1/actions/com.quexten.goldwarden.policy" install -Dm644 "$srcdir/$pkgname-$pkgver/resources/com.quexten.goldwarden.policy" "$pkgdir/usr/share/polkit-1/actions/com.quexten.goldwarden.policy"
chown root:root "$pkgdir/usr/share/polkit-1/actions/com.quexten.goldwarden.policy"
} }

View File

@ -8,7 +8,6 @@ import (
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/biometrics"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc" "github.com/quexten/goldwarden/ipc"
) )
@ -81,16 +80,16 @@ func ensureIsNotLocked(action Action) Action {
}) })
} }
systemauth.CreateSession(*ctx) systemauth.CreatePinSession(*ctx)
} }
return action(request, cfg, vault, ctx) return action(request, cfg, vault, ctx)
} }
} }
func ensureBiometricsAuthorized(approvalType biometrics.Approval, action Action) Action { func ensureBiometricsAuthorized(approvalType systemauth.SessionType, action Action) Action {
return func(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx *sockets.CallingContext) (ipc.IPCMessage, error) { return func(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx *sockets.CallingContext) (ipc.IPCMessage, error) {
if !systemauth.CheckBiometrics(ctx, approvalType) { if permission, err := systemauth.GetPermission(approvalType, *ctx, cfg); err != nil || !permission {
return ipc.IPCMessageFromPayload(ipc.ActionResponse{ return ipc.IPCMessageFromPayload(ipc.ActionResponse{
Success: false, Success: false,
Message: "Polkit authorization failed required", Message: "Polkit authorization failed required",
@ -101,6 +100,6 @@ func ensureBiometricsAuthorized(approvalType biometrics.Approval, action Action)
} }
} }
func ensureEverything(approvalType biometrics.Approval, action Action) Action { func ensureEverything(approvalType systemauth.SessionType, action Action) Action {
return ensureIsNotLocked(ensureIsLoggedIn(ensureBiometricsAuthorized(approvalType, action))) return ensureIsNotLocked(ensureIsLoggedIn(ensureBiometricsAuthorized(approvalType, action)))
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth/biometrics"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
@ -13,6 +14,17 @@ import (
) )
func handleGetBiometricsKey(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx *sockets.CallingContext) (response ipc.IPCMessage, err error) { func handleGetBiometricsKey(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx *sockets.CallingContext) (response ipc.IPCMessage, err error) {
if !(systemauth.VerifyPinSession(*ctx) || biometrics.CheckBiometrics(biometrics.BrowserBiometrics)) {
response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{
Success: false,
Message: "not approved",
})
if err != nil {
return ipc.IPCMessage{}, err
}
return response, nil
}
if approved, err := pinentry.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access your vault encryption key for browser biometric unlock.", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName)); err != nil || !approved { if approved, err := pinentry.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access your vault encryption key for browser biometric unlock.", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName)); err != nil || !approved {
response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{ response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{
Success: false, Success: false,
@ -25,6 +37,9 @@ func handleGetBiometricsKey(request ipc.IPCMessage, cfg *config.Config, vault *v
} }
masterKey, err := cfg.GetMasterKey() masterKey, err := cfg.GetMasterKey()
if err != nil {
return ipc.IPCMessage{}, err
}
masterKeyB64 := base64.StdEncoding.EncodeToString(masterKey) masterKeyB64 := base64.StdEncoding.EncodeToString(masterKey)
response, err = ipc.IPCMessageFromPayload(ipc.GetBiometricsKeyResponse{ response, err = ipc.IPCMessageFromPayload(ipc.GetBiometricsKeyResponse{
Key: masterKeyB64, Key: masterKeyB64,
@ -33,5 +48,5 @@ func handleGetBiometricsKey(request ipc.IPCMessage, cfg *config.Config, vault *v
} }
func init() { func init() {
AgentActionsRegistry.Register(ipc.IPCMessageTypeGetBiometricsKeyRequest, ensureEverything(biometrics.BrowserBiometrics, handleGetBiometricsKey)) AgentActionsRegistry.Register(ipc.IPCMessageTypeGetBiometricsKeyRequest, ensureIsNotLocked(ensureIsLoggedIn(handleGetBiometricsKey)))
} }

View File

@ -5,7 +5,7 @@ import (
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc" "github.com/quexten/goldwarden/ipc"
@ -45,5 +45,5 @@ func handleGetCliCredentials(request ipc.IPCMessage, cfg *config.Config, vault *
} }
func init() { func init() {
AgentActionsRegistry.Register(ipc.IPCMessageTypeGetCLICredentialsRequest, ensureEverything(biometrics.AccessCredential, handleGetCliCredentials)) AgentActionsRegistry.Register(ipc.IPCMessageTypeGetCLICredentialsRequest, ensureEverything(systemauth.AccessVault, handleGetCliCredentials))
} }

View File

@ -10,7 +10,7 @@ import (
"github.com/quexten/goldwarden/agent/bitwarden/crypto" "github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc" "github.com/quexten/goldwarden/ipc"
@ -157,6 +157,6 @@ func handleListLoginsRequest(request ipc.IPCMessage, cfg *config.Config, vault *
} }
func init() { func init() {
AgentActionsRegistry.Register(ipc.IPCMessageGetLoginRequest, ensureEverything(biometrics.AccessCredential, handleGetLoginCipher)) AgentActionsRegistry.Register(ipc.IPCMessageGetLoginRequest, ensureEverything(systemauth.AccessVault, handleGetLoginCipher))
AgentActionsRegistry.Register(ipc.IPCMessageListLoginsRequest, ensureEverything(biometrics.AccessCredential, handleListLoginsRequest)) AgentActionsRegistry.Register(ipc.IPCMessageListLoginsRequest, ensureEverything(systemauth.AccessVault, handleListLoginsRequest))
} }

View File

@ -8,7 +8,7 @@ import (
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/ssh" "github.com/quexten/goldwarden/agent/ssh"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc" "github.com/quexten/goldwarden/ipc"
"github.com/quexten/goldwarden/logging" "github.com/quexten/goldwarden/logging"
@ -57,6 +57,6 @@ func handleListSSH(msg ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, c
} }
func init() { func init() {
AgentActionsRegistry.Register(ipc.IPCMessageTypeCreateSSHKeyRequest, ensureEverything(biometrics.SSHKey, handleAddSSH)) AgentActionsRegistry.Register(ipc.IPCMessageTypeCreateSSHKeyRequest, ensureEverything(systemauth.SSHKey, handleAddSSH))
AgentActionsRegistry.Register(ipc.IPCMessageTypeGetSSHKeysRequest, ensureIsNotLocked(ensureIsLoggedIn(handleListSSH))) AgentActionsRegistry.Register(ipc.IPCMessageTypeGetSSHKeysRequest, ensureIsNotLocked(ensureIsLoggedIn(handleListSSH)))
} }

View File

@ -8,7 +8,7 @@ import (
"github.com/quexten/goldwarden/agent/bitwarden/crypto" "github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc" "github.com/quexten/goldwarden/ipc"
@ -181,6 +181,6 @@ func init() {
AgentActionsRegistry.Register(ipc.IPCMessageTypeUnlockVaultRequest, handleUnlockVault) AgentActionsRegistry.Register(ipc.IPCMessageTypeUnlockVaultRequest, handleUnlockVault)
AgentActionsRegistry.Register(ipc.IPCMessageTypeLockVaultRequest, handleLockVault) AgentActionsRegistry.Register(ipc.IPCMessageTypeLockVaultRequest, handleLockVault)
AgentActionsRegistry.Register(ipc.IPCMessageTypeWipeVaultRequest, handleWipeVault) AgentActionsRegistry.Register(ipc.IPCMessageTypeWipeVaultRequest, handleWipeVault)
AgentActionsRegistry.Register(ipc.IPCMessageTypeUpdateVaultPINRequest, ensureBiometricsAuthorized(biometrics.ChangePin, handleUpdateVaultPin)) AgentActionsRegistry.Register(ipc.IPCMessageTypeUpdateVaultPINRequest, ensureBiometricsAuthorized(systemauth.AccessVault, handleUpdateVaultPin))
AgentActionsRegistry.Register(ipc.IPCMessageTypeGetVaultPINStatusRequest, handlePinStatus) AgentActionsRegistry.Register(ipc.IPCMessageTypeGetVaultPINStatusRequest, handlePinStatus)
} }

View File

@ -179,11 +179,12 @@ func connectToWebsocket(ctx context.Context, vault *vault.Vault, cfg *config.Con
} }
websocketLog.Info("AuthRequest details " + authRequest.RequestIpAddress + " " + authRequest.RequestDeviceType) websocketLog.Info("AuthRequest details " + authRequest.RequestIpAddress + " " + authRequest.RequestDeviceType)
if approved, err := pinentry.GetApproval("Paswordless Login Request", "Do you want to allow "+authRequest.RequestIpAddress+" ("+authRequest.RequestDeviceType+") to login to your account?"); err != nil || !approved { var message = "Do you want to allow " + authRequest.RequestIpAddress + " (" + authRequest.RequestDeviceType + ") to login to your account?"
if approved, err := pinentry.GetApproval("Paswordless Login Request", message); err != nil || !approved {
websocketLog.Info("AuthRequest denied") websocketLog.Info("AuthRequest denied")
break break
} }
if !biometrics.CheckBiometrics(biometrics.AccessCredential) { if !biometrics.CheckBiometrics(biometrics.AccessVault) {
websocketLog.Info("AuthRequest denied - biometrics required") websocketLog.Info("AuthRequest denied - biometrics required")
break break
} }

View File

@ -43,7 +43,6 @@ type RuntimeConfig struct {
User string User string
Password string Password string
Pin string Pin string
SessionToken string
} }
type ConfigFile struct { type ConfigFile struct {
@ -121,6 +120,18 @@ func (c *Config) Unlock(password string) bool {
return true return true
} }
func (c *Config) VerifyPin(password string) bool {
key := argon2.Key([]byte(password), []byte(c.ConfigFile.DeviceUUID), KDFIterations, KDFMemory, KDFThreads, 32)
debug.FreeOSMemory()
keyHash := sha3.Sum256(key)
configKeyHash := hex.EncodeToString(keyHash[:])
if cryptoSubtle.ConstantTimeCompare([]byte(configKeyHash), []byte(c.ConfigFile.ConfigKeyHash)) != 1 {
return false
} else {
return true
}
}
func (c *Config) Lock() { func (c *Config) Lock() {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()

View File

@ -8,9 +8,9 @@ import (
"net" "net"
"os" "os"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth" "github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/systemauth/biometrics"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/logging" "github.com/quexten/goldwarden/logging"
@ -22,6 +22,7 @@ var log = logging.GetLogger("Goldwarden", "SSH")
type vaultAgent struct { type vaultAgent struct {
vault *vault.Vault vault *vault.Vault
config *config.Config
unlockRequestAction func() bool unlockRequestAction func() bool
context sockets.CallingContext context sockets.CallingContext
} }
@ -77,7 +78,7 @@ func (vaultAgent vaultAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signatur
return nil, errors.New("vault is locked") return nil, errors.New("vault is locked")
} }
systemauth.CreateSession(vaultAgent.context) systemauth.CreatePinSession(vaultAgent.context)
} }
var signer ssh.Signer var signer ssh.Signer
@ -103,7 +104,7 @@ func (vaultAgent vaultAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signatur
return nil, errors.New("Approval not given") return nil, errors.New("Approval not given")
} }
if !systemauth.CheckBiometrics(&vaultAgent.context, biometrics.SSHKey) { if permission, err := systemauth.GetPermission(systemauth.SSHKey, vaultAgent.context, vaultAgent.config); err != nil || !permission {
log.Info("Sign Request for key: %s denied", key.Marshal()) log.Info("Sign Request for key: %s denied", key.Marshal())
return nil, errors.New("Biometrics not checked") return nil, errors.New("Biometrics not checked")
} }
@ -124,6 +125,7 @@ func (vaultAgent) Unlock(passphrase []byte) error {
type SSHAgentServer struct { type SSHAgentServer struct {
vault *vault.Vault vault *vault.Vault
config *config.Config
unlockRequestAction func() bool unlockRequestAction func() bool
} }
@ -131,9 +133,10 @@ func (v *SSHAgentServer) SetUnlockRequestAction(action func() bool) {
v.unlockRequestAction = action v.unlockRequestAction = action
} }
func NewVaultAgent(vault *vault.Vault) SSHAgentServer { func NewVaultAgent(vault *vault.Vault, config *config.Config) SSHAgentServer {
return SSHAgentServer{ return SSHAgentServer{
vault: vault, vault: vault,
config: config,
unlockRequestAction: func() bool { unlockRequestAction: func() bool {
log.Info("Unlock Request, but no action defined") log.Info("Unlock Request, but no action defined")
return false return false
@ -175,6 +178,7 @@ func (v SSHAgentServer) Serve() {
go agent.ServeAgent(vaultAgent{ go agent.ServeAgent(vaultAgent{
vault: v.vault, vault: v.vault,
config: v.config,
unlockRequestAction: v.unlockRequestAction, unlockRequestAction: v.unlockRequestAction,
context: callingContext, context: callingContext,
}, conn) }, conn)

View File

@ -19,10 +19,8 @@ func init() {
type Approval string type Approval string
const ( const (
AccessCredential Approval = "com.quexten.goldwarden.accesscredential" AccessVault Approval = "com.quexten.goldwarden.accessvault"
ChangePin Approval = "com.quexten.goldwarden.changepin"
SSHKey Approval = "com.quexten.goldwarden.usesshkey" SSHKey Approval = "com.quexten.goldwarden.usesshkey"
ModifyVault Approval = "com.quexten.goldwarden.modifyvault"
BrowserBiometrics Approval = "com.quexten.goldwarden.browserbiometrics" BrowserBiometrics Approval = "com.quexten.goldwarden.browserbiometrics"
) )

View File

@ -12,18 +12,9 @@ const POLICY = `<?xml version="1.0" encoding="UTF-8"?>
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig> <policyconfig>
<action id="com.quexten.goldwarden.accesscredential"> <action id="com.quexten.goldwarden.accessvault">
<description>Allow Credential Access</description> <description>Allow access to the vault</description>
<message>Authenticate to allow access to a single credential</message> <message>Allows access to the vault entries</message>
<defaults>
<allow_any>auth_self</allow_any>
<allow_inactive>auth_self</allow_inactive>
<allow_active>auth_self</allow_active>
</defaults>
</action>
<action id="com.quexten.goldwarden.changepin">
<description>Approve Pin Change</description>
<message>Authenticate to change your Goldwarden PIN.</message>
<defaults> <defaults>
<allow_any>auth_self</allow_any> <allow_any>auth_self</allow_any>
<allow_inactive>auth_self</allow_inactive> <allow_inactive>auth_self</allow_inactive>
@ -31,7 +22,7 @@ const POLICY = `<?xml version="1.0" encoding="UTF-8"?>
</defaults> </defaults>
</action> </action>
<action id="com.quexten.goldwarden.usesshkey"> <action id="com.quexten.goldwarden.usesshkey">
<description>Use Bitwarden SSH Key</description> <description>Use SSH Key</description>
<message>Authenticate to use an SSH Key from your vault</message> <message>Authenticate to use an SSH Key from your vault</message>
<defaults> <defaults>
<allow_any>auth_self</allow_any> <allow_any>auth_self</allow_any>
@ -39,15 +30,6 @@ const POLICY = `<?xml version="1.0" encoding="UTF-8"?>
<allow_active>auth_self</allow_active> <allow_active>auth_self</allow_active>
</defaults> </defaults>
</action> </action>
<action id="com.quexten.goldwarden.modifyvault">
<description>Modify Bitwarden Vault</description>
<message>Authenticate to allow modification of your Bitvarden vault in Goldwarden</message>
<defaults>
<allow_any>auth_self</allow_any>
<allow_inactive>auth_self</allow_inactive>
<allow_active>auth_self</allow_active>
</defaults>
</action>
<action id="com.quexten.goldwarden.browserbiometrics"> <action id="com.quexten.goldwarden.browserbiometrics">
<description>Browser Biometrics</description> <description>Browser Biometrics</description>
<message>Authenticate to allow Goldwarden to unlock your browser.</message> <message>Authenticate to allow Goldwarden to unlock your browser.</message>
@ -68,16 +50,18 @@ func CheckBiometrics(approvalType Approval) bool {
authority, err := polkit.NewAuthority() authority, err := polkit.NewAuthority()
if err != nil { if err != nil {
log.Error("Failed to create polkit authority: %s", err.Error())
return false return false
} }
result, err := authority.CheckAuthorization( result, err := authority.CheckAuthorization(
approvalType.String(), approvalType.String(),
nil, nil,
polkit.CheckAuthorizationAllowUserInteraction, "", uint32(polkit.AuthenticationRequiredRetained), "",
) )
if err != nil { if err != nil {
log.Error("Failed to create polkit authority: %s", err.Error())
return false return false
} }
@ -85,3 +69,32 @@ func CheckBiometrics(approvalType Approval) bool {
return result.IsAuthorized return result.IsAuthorized
} }
func BiometricsWorking() bool {
if biometricsDisabled {
return false
}
authority, err := polkit.NewAuthority()
if err != nil {
return false
}
result, err := authority.EnumerateActions("en")
if err != nil {
return false
}
if len(result) == 0 {
return false
}
testFor := AccessVault
for _, action := range result {
if Approval(action.ActionID) == testFor {
return true
}
}
return false
}

View File

@ -1,15 +1,29 @@
package systemauth package systemauth
import ( import (
"fmt"
"math"
"time" "time"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets" "github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth/biometrics" "github.com/quexten/goldwarden/agent/systemauth/biometrics"
"github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/systemauth/pinentry"
"github.com/quexten/goldwarden/logging"
) )
var log = logging.GetLogger("Goldwarden", "Systemauth")
const tokenExpiry = 10 * time.Minute const tokenExpiry = 10 * time.Minute
type SessionType string
const (
AccessVault SessionType = "com.quexten.goldwarden.accessvault"
SSHKey SessionType = "com.quexten.goldwarden.usesshkey"
Pin SessionType = "com.quexten.goldwarden.pin" // this counts as all other permissions
)
var sessionStore = SessionStore{ var sessionStore = SessionStore{
Store: []Session{}, Store: []Session{},
} }
@ -19,26 +33,28 @@ type Session struct {
ParentPid int ParentPid int
GrandParentPid int GrandParentPid int
Expires time.Time Expires time.Time
sessionType SessionType
} }
type SessionStore struct { type SessionStore struct {
Store []Session Store []Session
} }
func (s *SessionStore) CreateSession(pid int, parentpid int, grandparentpid int) Session { func (s *SessionStore) CreateSession(pid int, parentpid int, grandparentpid int, sessionType SessionType) Session {
var session = Session{ var session = Session{
Pid: pid, Pid: pid,
ParentPid: parentpid, ParentPid: parentpid,
GrandParentPid: grandparentpid, GrandParentPid: grandparentpid,
Expires: time.Now().Add(tokenExpiry), Expires: time.Now().Add(tokenExpiry),
sessionType: sessionType,
} }
s.Store = append(s.Store, session) s.Store = append(s.Store, session)
return session return session
} }
func (s *SessionStore) VerifySession(ctx sockets.CallingContext) bool { func (s *SessionStore) verifySession(ctx sockets.CallingContext, sessionType SessionType) bool {
for _, session := range s.Store { for _, session := range s.Store {
if session.ParentPid == ctx.ParentProcessPid && session.GrandParentPid == ctx.GrandParentProcessPid { if session.ParentPid == ctx.ParentProcessPid && session.GrandParentPid == ctx.GrandParentProcessPid && (session.sessionType == sessionType || session.sessionType == Pin) {
if session.Expires.After(time.Now()) { if session.Expires.After(time.Now()) {
return true return true
} }
@ -47,34 +63,70 @@ func (s *SessionStore) VerifySession(ctx sockets.CallingContext) bool {
return false return false
} }
func GetApproval(title string, description string, requriesBiometrics bool) (bool, error) { // with session
approval, err := pinentry.GetApproval(title, description) func GetPermission(sessionType SessionType, ctx sockets.CallingContext, config *config.Config) (bool, error) {
if err != nil { log.Info("Checking permission for " + ctx.ProcessName + " with session type " + string(sessionType))
return false, err var actionDescription = ""
biometricsApprovalType := biometrics.AccessVault
switch sessionType {
case AccessVault:
actionDescription = "access the vault"
biometricsApprovalType = biometrics.AccessVault
case SSHKey:
actionDescription = "use an SSH key for signing"
biometricsApprovalType = biometrics.SSHKey
} }
if requriesBiometrics { var message = fmt.Sprintf("Do you want to authorize %s>%s>%s to %s? (This choice will be remembered for %d minutes)", ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName, actionDescription, int(math.Floor(tokenExpiry.Minutes())))
biometricsApproval := biometrics.CheckBiometrics(biometrics.AccessCredential)
if !biometricsApproval { if sessionStore.verifySession(ctx, sessionType) {
return false, nil log.Info("Permission granted from cached session")
} else {
if biometrics.BiometricsWorking() {
biometricsApproval := biometrics.CheckBiometrics(biometricsApprovalType)
if !biometricsApproval {
return false, nil
}
} else {
pin, err := pinentry.GetPassword("Enter PIN", "Biometrics is not available. Enter your pin to authorize this action. "+message)
if err != nil {
return false, err
}
if !config.VerifyPin(pin) {
return false, nil
}
} }
approval, err := pinentry.GetApproval("Goldwarden authorization", message)
if err != nil || !approval {
return false, err
}
log.Info("Permission granted, creating session")
sessionStore.CreateSession(ctx.ProcessPid, ctx.ParentProcessPid, ctx.GrandParentProcessPid, sessionType)
} }
return approval, nil return true, nil
} }
// no session
func CheckBiometrics(callingContext *sockets.CallingContext, approvalType biometrics.Approval) bool { func CheckBiometrics(callingContext *sockets.CallingContext, approvalType biometrics.Approval) bool {
if sessionStore.VerifySession(*callingContext) { var message = fmt.Sprintf("Do you want to grant %s>%s>%s one-time access your vault?", callingContext.GrandParentProcessName, callingContext.ParentProcessName, callingContext.ProcessName)
return true var bioApproval = biometrics.CheckBiometrics(approvalType)
} if !bioApproval {
var approval = biometrics.CheckBiometrics(approvalType)
if !approval {
return false return false
} }
sessionStore.CreateSession(callingContext.ProcessPid, callingContext.ParentProcessPid, callingContext.GrandParentProcessPid) approval, err := pinentry.GetApproval("Goldwarden authorization", message)
return true if err != nil {
log.Error(err.Error())
}
return approval
} }
func CreateSession(ctx sockets.CallingContext) { func CreatePinSession(ctx sockets.CallingContext) {
sessionStore.CreateSession(ctx.ProcessPid, ctx.ParentProcessPid, ctx.GrandParentProcessPid) sessionStore.CreateSession(ctx.ProcessPid, ctx.ParentProcessPid, ctx.GrandParentProcessPid, Pin)
}
func VerifyPinSession(ctx sockets.CallingContext) bool {
return sessionStore.verifySession(ctx, Pin)
} }

View File

@ -150,7 +150,7 @@ func StartUnixAgent(path string, runtimeConfig config.RuntimeConfig) error {
} }
if !runtimeConfig.DisableSSHAgent { if !runtimeConfig.DisableSSHAgent {
vaultAgent := ssh.NewVaultAgent(vault) vaultAgent := ssh.NewVaultAgent(vault, &cfg)
vaultAgent.SetUnlockRequestAction(func() bool { vaultAgent.SetUnlockRequestAction(func() bool {
err := cfg.TryUnlock(vault) err := cfg.TryUnlock(vault)
if err == nil { if err == nil {

View File

@ -6,7 +6,6 @@ import (
"github.com/quexten/goldwarden/agent/config" "github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/browserbiometrics" "github.com/quexten/goldwarden/browserbiometrics"
"github.com/quexten/goldwarden/client/setup"
"github.com/quexten/goldwarden/cmd" "github.com/quexten/goldwarden/cmd"
) )
@ -39,7 +38,6 @@ func main() {
User: os.Getenv("GOLDWARDEN_AUTH_USER"), User: os.Getenv("GOLDWARDEN_AUTH_USER"),
Password: os.Getenv("GOLDWARDEN_AUTH_PASSWORD"), Password: os.Getenv("GOLDWARDEN_AUTH_PASSWORD"),
Pin: os.Getenv("GOLDWARDEN_PIN"), Pin: os.Getenv("GOLDWARDEN_PIN"),
SessionToken: os.Getenv("GOLDWARDEN_SESSION_TOKEN"),
ConfigDirectory: configPath, ConfigDirectory: configPath,
} }
@ -57,9 +55,5 @@ func main() {
os.Setenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED", "true") os.Setenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED", "true")
} }
if !setup.VerifySetup(runtimeConfig) {
return
}
cmd.Execute(runtimeConfig) cmd.Execute(runtimeConfig)
} }