2023-09-12 18:56:35 +02:00
package systemauth
import (
2023-09-19 21:49:56 +02:00
"fmt"
"math"
2023-09-12 18:56:35 +02:00
"time"
2023-09-19 21:49:56 +02:00
"github.com/quexten/goldwarden/agent/config"
2023-09-12 18:56:35 +02:00
"github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth/biometrics"
"github.com/quexten/goldwarden/agent/systemauth/pinentry"
2023-09-19 21:49:56 +02:00
"github.com/quexten/goldwarden/logging"
2023-09-12 18:56:35 +02:00
)
2023-09-19 21:49:56 +02:00
var log = logging . GetLogger ( "Goldwarden" , "Systemauth" )
2023-09-12 18:56:35 +02:00
const tokenExpiry = 10 * time . Minute
2023-09-19 21:49:56 +02:00
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
)
2023-09-12 18:56:35 +02:00
var sessionStore = SessionStore {
Store : [ ] Session { } ,
}
type Session struct {
Pid int
ParentPid int
GrandParentPid int
Expires time . Time
2023-09-19 21:49:56 +02:00
sessionType SessionType
2023-09-12 18:56:35 +02:00
}
type SessionStore struct {
Store [ ] Session
}
2023-09-19 21:49:56 +02:00
func ( s * SessionStore ) CreateSession ( pid int , parentpid int , grandparentpid int , sessionType SessionType ) Session {
2023-09-12 18:56:35 +02:00
var session = Session {
Pid : pid ,
ParentPid : parentpid ,
GrandParentPid : grandparentpid ,
Expires : time . Now ( ) . Add ( tokenExpiry ) ,
2023-09-19 21:49:56 +02:00
sessionType : sessionType ,
2023-09-12 18:56:35 +02:00
}
s . Store = append ( s . Store , session )
return session
}
2023-09-19 21:49:56 +02:00
func ( s * SessionStore ) verifySession ( ctx sockets . CallingContext , sessionType SessionType ) bool {
2023-09-12 18:56:35 +02:00
for _ , session := range s . Store {
2023-09-19 21:49:56 +02:00
if session . ParentPid == ctx . ParentProcessPid && session . GrandParentPid == ctx . GrandParentProcessPid && ( session . sessionType == sessionType || session . sessionType == Pin ) {
2023-09-12 18:56:35 +02:00
if session . Expires . After ( time . Now ( ) ) {
return true
}
}
}
return false
}
2023-09-19 21:49:56 +02:00
// with session
func GetPermission ( sessionType SessionType , ctx sockets . CallingContext , config * config . Config ) ( bool , error ) {
log . Info ( "Checking permission for " + ctx . ProcessName + " with session type " + string ( sessionType ) )
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
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
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 ( ) ) ) )
if sessionStore . verifySession ( ctx , sessionType ) {
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
}
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
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 )
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
return true , nil
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
// no session
2023-09-12 18:56:35 +02:00
func CheckBiometrics ( callingContext * sockets . CallingContext , approvalType biometrics . Approval ) bool {
2023-09-19 21:49:56 +02:00
var message = fmt . Sprintf ( "Do you want to grant %s>%s>%s one-time access your vault?" , callingContext . GrandParentProcessName , callingContext . ParentProcessName , callingContext . ProcessName )
var bioApproval = biometrics . CheckBiometrics ( approvalType )
if ! bioApproval {
return false
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
approval , err := pinentry . GetApproval ( "Goldwarden authorization" , message )
if err != nil {
log . Error ( err . Error ( ) )
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
return approval
}
func CreatePinSession ( ctx sockets . CallingContext ) {
sessionStore . CreateSession ( ctx . ProcessPid , ctx . ParentProcessPid , ctx . GrandParentProcessPid , Pin )
2023-09-12 18:56:35 +02:00
}
2023-09-19 21:49:56 +02:00
func VerifyPinSession ( ctx sockets . CallingContext ) bool {
return sessionStore . verifySession ( ctx , Pin )
2023-09-12 18:56:35 +02:00
}