From a566d712239cd55d0ac69081a691af655c59be8b Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 12 Sep 2023 02:54:46 +0200 Subject: [PATCH] Refactor platform abstractions --- agent/actions/browserbiometrics.go | 4 ++-- agent/actions/getclicredentials.go | 4 ++-- agent/actions/logins.go | 6 +++--- agent/actions/vault.go | 4 ++-- agent/bitwarden/auth.go | 4 ++-- agent/bitwarden/twofactor/fido2twofactor.go | 4 ++-- agent/bitwarden/twofactor/twofactor.go | 6 +++--- agent/bitwarden/websocket.go | 4 ++-- agent/config/config.go | 4 ++-- agent/sockets/callingcontext.go | 1 + agent/ssh/ssh.go | 4 ++-- agent/systemauth/biometrics/touchid.go | 10 +++++++--- agent/systemauth/biometrics/windows.go | 8 ++++++++ .../{pinentry.go => pinentry/go-pinentry.go} | 4 +++- .../{systemauth.go => pinentry/pinentry.go} | 5 ++--- agent/systemauth/pinentry/unimplemented.go | 13 +++++++++++++ autofill/autofill.go | 14 +++++++------- autofill/{ => autotype}/uinput/dvorak.go | 0 autofill/{ => autotype}/uinput/qwerty.go | 0 autofill/{ => autotype}/uinput/uinput.go | 0 autofill/autotype/uinputautotype.go | 13 +++++++++++++ autofill/autotype/unimplemented.go | 7 +++++++ go.mod | 6 +++--- go.sum | 8 ++++++++ 24 files changed, 94 insertions(+), 39 deletions(-) create mode 100644 agent/systemauth/biometrics/windows.go rename agent/systemauth/{pinentry.go => pinentry/go-pinentry.go} (96%) rename agent/systemauth/{systemauth.go => pinentry/pinentry.go} (72%) create mode 100644 agent/systemauth/pinentry/unimplemented.go rename autofill/{ => autotype}/uinput/dvorak.go (100%) rename autofill/{ => autotype}/uinput/qwerty.go (100%) rename autofill/{ => autotype}/uinput/uinput.go (100%) create mode 100644 autofill/autotype/uinputautotype.go create mode 100644 autofill/autotype/unimplemented.go diff --git a/agent/actions/browserbiometrics.go b/agent/actions/browserbiometrics.go index e3eeb28..68d3cd3 100644 --- a/agent/actions/browserbiometrics.go +++ b/agent/actions/browserbiometrics.go @@ -6,14 +6,14 @@ import ( "github.com/quexten/goldwarden/agent/config" "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/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/ipc" ) func handleGetBiometricsKey(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx sockets.CallingContext) (response interface{}, err error) { - if approved, err := systemauth.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{ Success: false, Message: "not approved", diff --git a/agent/actions/getclicredentials.go b/agent/actions/getclicredentials.go index 7940bba..1dcf318 100644 --- a/agent/actions/getclicredentials.go +++ b/agent/actions/getclicredentials.go @@ -5,8 +5,8 @@ import ( "github.com/quexten/goldwarden/agent/config" "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/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/ipc" ) @@ -14,7 +14,7 @@ import ( func handleGetCliCredentials(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx sockets.CallingContext) (response interface{}, err error) { req := request.ParsedPayload().(ipc.GetCLICredentialsRequest) - if approved, err := systemauth.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access credentials for %s", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName, req.ApplicationName)); err != nil || !approved { + if approved, err := pinentry.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access credentials for %s", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName, req.ApplicationName)); err != nil || !approved { response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{ Success: false, Message: "not approved", diff --git a/agent/actions/logins.go b/agent/actions/logins.go index 0efd364..f62728b 100644 --- a/agent/actions/logins.go +++ b/agent/actions/logins.go @@ -10,8 +10,8 @@ import ( "github.com/quexten/goldwarden/agent/bitwarden/crypto" "github.com/quexten/goldwarden/agent/config" "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/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/ipc" ) @@ -83,7 +83,7 @@ func handleGetLoginCipher(request ipc.IPCMessage, cfg *config.Config, vault *vau } } - if approved, err := systemauth.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access credentials for user %s on entry %s", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName, decryptedLogin.Username, decryptedLogin.Name)); err != nil || !approved { + if approved, err := pinentry.GetApproval("Approve Credential Access", fmt.Sprintf("%s on %s>%s>%s is trying to access credentials for user %s on entry %s", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName, decryptedLogin.Username, decryptedLogin.Name)); err != nil || !approved { response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{ Success: false, Message: "not approved", @@ -101,7 +101,7 @@ func handleGetLoginCipher(request ipc.IPCMessage, cfg *config.Config, vault *vau } func handleListLoginsRequest(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx sockets.CallingContext) (response interface{}, err error) { - if approved, err := systemauth.GetApproval("Approve List Credentials", fmt.Sprintf("%s on %s>%s>%s is trying to list credentials (name & username)", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName)); err != nil || !approved { + if approved, err := pinentry.GetApproval("Approve List Credentials", fmt.Sprintf("%s on %s>%s>%s is trying to list credentials (name & username)", ctx.UserName, ctx.GrandParentProcessName, ctx.ParentProcessName, ctx.ProcessName)); err != nil || !approved { response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{ Success: false, Message: "not approved", diff --git a/agent/actions/vault.go b/agent/actions/vault.go index 3c3ceb1..98b4a49 100644 --- a/agent/actions/vault.go +++ b/agent/actions/vault.go @@ -8,8 +8,8 @@ import ( "github.com/quexten/goldwarden/agent/bitwarden/crypto" "github.com/quexten/goldwarden/agent/config" "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/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/ipc" ) @@ -140,7 +140,7 @@ func handleWipeVault(request ipc.IPCMessage, cfg *config.Config, vault *vault.Va } func handleUpdateVaultPin(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext sockets.CallingContext) (response interface{}, err error) { - pin, err := systemauth.GetPassword("Pin Change", "Enter your desired pin") + pin, err := pinentry.GetPassword("Pin Change", "Enter your desired pin") if err != nil { response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{ Success: false, diff --git a/agent/bitwarden/auth.go b/agent/bitwarden/auth.go index 4db0a16..15f3617 100644 --- a/agent/bitwarden/auth.go +++ b/agent/bitwarden/auth.go @@ -18,7 +18,7 @@ import ( "github.com/quexten/goldwarden/agent/bitwarden/crypto" "github.com/quexten/goldwarden/agent/bitwarden/twofactor" "github.com/quexten/goldwarden/agent/config" - "github.com/quexten/goldwarden/agent/systemauth" + "github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/logging" "golang.org/x/crypto/pbkdf2" @@ -76,7 +76,7 @@ func LoginWithMasterpassword(ctx context.Context, email string, cfg *config.Conf var masterKey crypto.MasterKey var hashedPassword string - password, err := systemauth.GetPassword("Bitwarden Password", "Enter your Bitwarden password") + password, err := pinentry.GetPassword("Bitwarden Password", "Enter your Bitwarden password") if err != nil { return LoginResponseToken{}, crypto.MasterKey{}, "", err } diff --git a/agent/bitwarden/twofactor/fido2twofactor.go b/agent/bitwarden/twofactor/fido2twofactor.go index 1cdf7e3..8d8f931 100644 --- a/agent/bitwarden/twofactor/fido2twofactor.go +++ b/agent/bitwarden/twofactor/fido2twofactor.go @@ -11,7 +11,7 @@ import ( "github.com/keys-pub/go-libfido2" "github.com/quexten/goldwarden/agent/config" - "github.com/quexten/goldwarden/agent/systemauth" + "github.com/quexten/goldwarden/agent/systemauth/pinentry" ) const isFido2Enabled = true @@ -61,7 +61,7 @@ func Fido2TwoFactor(challengeB64 string, credentials []string, config *config.Co clientDataHash := sha256.Sum256([]byte(clientDataJson)) clientDataJson = base64.URLEncoding.EncodeToString([]byte(clientDataJson)) - pin, err := systemauth.GetPassword("Fido2 PIN", "Enter your token's PIN") + pin, err := pinentry.GetPassword("Fido2 PIN", "Enter your token's PIN") if err != nil { twofactorLog.Fatal(err.Error()) } diff --git a/agent/bitwarden/twofactor/twofactor.go b/agent/bitwarden/twofactor/twofactor.go index 699c58f..2686ff4 100644 --- a/agent/bitwarden/twofactor/twofactor.go +++ b/agent/bitwarden/twofactor/twofactor.go @@ -6,7 +6,7 @@ import ( "strconv" "github.com/quexten/goldwarden/agent/config" - "github.com/quexten/goldwarden/agent/systemauth" + "github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/logging" ) @@ -33,11 +33,11 @@ func PerformSecondFactor(resp *TwoFactorResponse, cfg *config.Config) (TwoFactor } } if _, isInMap := resp.TwoFactorProviders2[Authenticator]; isInMap { - token, err := systemauth.GetPassword("Authenticator Second Factor", "Enter your two-factor auth code") + token, err := pinentry.GetPassword("Authenticator Second Factor", "Enter your two-factor auth code") return Authenticator, []byte(token), err } if _, isInMap := resp.TwoFactorProviders2[Email]; isInMap { - token, err := systemauth.GetPassword("Email Second Factor", "Enter your two-factor auth code") + token, err := pinentry.GetPassword("Email Second Factor", "Enter your two-factor auth code") return Email, []byte(token), err } diff --git a/agent/bitwarden/websocket.go b/agent/bitwarden/websocket.go index df4e3ef..b34c2a7 100644 --- a/agent/bitwarden/websocket.go +++ b/agent/bitwarden/websocket.go @@ -13,8 +13,8 @@ import ( "github.com/gorilla/websocket" "github.com/quexten/goldwarden/agent/bitwarden/models" "github.com/quexten/goldwarden/agent/config" - "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/vault" "github.com/quexten/goldwarden/logging" "github.com/vmihailenco/msgpack/v5" @@ -179,7 +179,7 @@ func connectToWebsocket(ctx context.Context, vault *vault.Vault, cfg *config.Con } websocketLog.Info("AuthRequest details " + authRequest.RequestIpAddress + " " + authRequest.RequestDeviceType) - if approved, err := systemauth.GetApproval("Paswordless Login Request", "Do you want to allow "+authRequest.RequestIpAddress+" ("+authRequest.RequestDeviceType+") to login to your account?"); err != nil || !approved { + 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 { websocketLog.Info("AuthRequest denied") break } diff --git a/agent/config/config.go b/agent/config/config.go index 6b080ec..d8054a7 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -13,7 +13,7 @@ import ( "github.com/awnumar/memguard" "github.com/google/uuid" "github.com/quexten/goldwarden/agent/bitwarden/crypto" - "github.com/quexten/goldwarden/agent/systemauth" + "github.com/quexten/goldwarden/agent/systemauth/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/tink-crypto/tink-go/v2/aead/subtle" "golang.org/x/crypto/argon2" @@ -395,7 +395,7 @@ func ReadConfig(rtCfg RuntimeConfig) (Config, error) { } func (cfg *Config) TryUnlock(vault *vault.Vault) error { - pin, err := systemauth.GetPassword("Unlock Goldwarden", "Enter the vault PIN") + pin, err := pinentry.GetPassword("Unlock Goldwarden", "Enter the vault PIN") if err != nil { return err } diff --git a/agent/sockets/callingcontext.go b/agent/sockets/callingcontext.go index 3afa345..858799a 100644 --- a/agent/sockets/callingcontext.go +++ b/agent/sockets/callingcontext.go @@ -27,6 +27,7 @@ func GetCallingContext(connection net.Conn) CallingContext { if err != nil { panic(err) } + parentProcess, err := gops.FindProcess(ppid) if err != nil { panic(err) diff --git a/agent/ssh/ssh.go b/agent/ssh/ssh.go index 0dcf313..b7ff1ad 100644 --- a/agent/ssh/ssh.go +++ b/agent/ssh/ssh.go @@ -9,8 +9,8 @@ import ( "os" "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/pinentry" "github.com/quexten/goldwarden/agent/vault" "github.com/quexten/goldwarden/logging" "golang.org/x/crypto/ssh" @@ -95,7 +95,7 @@ func (vaultAgent vaultAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signatur message := fmt.Sprintf("%s on %s>%s>%s is requesting signage with key %s", vaultAgent.context.UserName, vaultAgent.context.GrandParentProcessName, vaultAgent.context.ParentProcessName, vaultAgent.context.ProcessName, sshKey.Name) - if approved, err := systemauth.GetApproval("SSH Key Signing Request", message); err != nil || !approved { + if approved, err := pinentry.GetApproval("SSH Key Signing Request", message); err != nil || !approved { log.Info("Sign Request for key: %s denied", sshKey.Name) return nil, errors.New("Approval not given") } diff --git a/agent/systemauth/biometrics/touchid.go b/agent/systemauth/biometrics/touchid.go index 5d40a26..871310b 100644 --- a/agent/systemauth/biometrics/touchid.go +++ b/agent/systemauth/biometrics/touchid.go @@ -2,17 +2,21 @@ package biometrics +import ( + touchid "github.com/lox/go-touchid" +) + func CheckBiometrics(approvalType Approval) bool { ok, err := touchid.Authenticate(approvalType.String()) if err != nil { - log.Fatal(err) + log.Error(err) } if ok { - log.Printf("Authenticated") + log.Info("Authenticated") return true } else { - log.Fatal("Failed to authenticate") + log.Error("Failed to authenticate") return false } } diff --git a/agent/systemauth/biometrics/windows.go b/agent/systemauth/biometrics/windows.go new file mode 100644 index 0000000..8bcc1c4 --- /dev/null +++ b/agent/systemauth/biometrics/windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package biometrics + +func CheckBiometrics(approvalType Approval) bool { + log.Info("Biometrics undefined on windows... skipping") + return true +} diff --git a/agent/systemauth/pinentry.go b/agent/systemauth/pinentry/go-pinentry.go similarity index 96% rename from agent/systemauth/pinentry.go rename to agent/systemauth/pinentry/go-pinentry.go index 26096b8..dea2c0b 100644 --- a/agent/systemauth/pinentry.go +++ b/agent/systemauth/pinentry/go-pinentry.go @@ -1,4 +1,6 @@ -package systemauth +//go:build linux || freebsd + +package pinentry import ( "errors" diff --git a/agent/systemauth/systemauth.go b/agent/systemauth/pinentry/pinentry.go similarity index 72% rename from agent/systemauth/systemauth.go rename to agent/systemauth/pinentry/pinentry.go index 9afad16..088e1f0 100644 --- a/agent/systemauth/systemauth.go +++ b/agent/systemauth/pinentry/pinentry.go @@ -1,4 +1,4 @@ -package systemauth +package pinentry import ( "os" @@ -6,8 +6,7 @@ import ( "github.com/quexten/goldwarden/logging" ) -var log = logging.GetLogger("Goldwarden", "Systemauth") - +var log = logging.GetLogger("Goldwarden", "Pinentry") var systemAuthDisabled = false func init() { diff --git a/agent/systemauth/pinentry/unimplemented.go b/agent/systemauth/pinentry/unimplemented.go new file mode 100644 index 0000000..01757ba --- /dev/null +++ b/agent/systemauth/pinentry/unimplemented.go @@ -0,0 +1,13 @@ +//go:build !linux && !freebsd + +package pinentry + +func GetPassword(title string, description string) (string, error) { + log.Info("Asking for password is not implemented on this platform") + return "", errors.New("Not implemented") +} + +func GetApproval(title string, description string) (bool, error) { + log.Info("Asking for approval is not implemented on this platform") + return true, errors.New("Not implemented") +} diff --git a/autofill/autofill.go b/autofill/autofill.go index c0520df..6c9a802 100644 --- a/autofill/autofill.go +++ b/autofill/autofill.go @@ -6,7 +6,7 @@ import ( "errors" "github.com/atotto/clipboard" - "github.com/quexten/goldwarden/autofill/uinput" + "github.com/quexten/goldwarden/autofill/autotype" "github.com/quexten/goldwarden/client" "github.com/quexten/goldwarden/ipc" ) @@ -72,14 +72,14 @@ func Run(layout string, useCopyPaste bool, client client.Client) { if useCopyPaste { clipboard.WriteAll(string(login.Username)) - uinput.Paste(layout) - uinput.TypeString(string(uinput.KeyTab), layout) + autotype.Paste(layout) + autotype.TypeString("\t", layout) clipboard.WriteAll(login.Password) - uinput.Paste(layout) + autotype.Paste(layout) } else { - uinput.TypeString(string(login.Username), layout) - uinput.TypeString(string(uinput.KeyTab), layout) - uinput.TypeString(string(login.Password), layout) + autotype.TypeString(string(login.Username), layout) + autotype.TypeString("\t", layout) + autotype.TypeString(string(login.Password), layout) } clipboard.WriteAll(login.TwoFactorCode) diff --git a/autofill/uinput/dvorak.go b/autofill/autotype/uinput/dvorak.go similarity index 100% rename from autofill/uinput/dvorak.go rename to autofill/autotype/uinput/dvorak.go diff --git a/autofill/uinput/qwerty.go b/autofill/autotype/uinput/qwerty.go similarity index 100% rename from autofill/uinput/qwerty.go rename to autofill/autotype/uinput/qwerty.go diff --git a/autofill/uinput/uinput.go b/autofill/autotype/uinput/uinput.go similarity index 100% rename from autofill/uinput/uinput.go rename to autofill/autotype/uinput/uinput.go diff --git a/autofill/autotype/uinputautotype.go b/autofill/autotype/uinputautotype.go new file mode 100644 index 0000000..5a32c46 --- /dev/null +++ b/autofill/autotype/uinputautotype.go @@ -0,0 +1,13 @@ +//go:build linux + +package autotype + +import "github.com/quexten/goldwarden/autofill/autotype/uinput" + +func TypeString(text string, layout string) error { + return uinput.TypeString(text, layout) +} + +func Paste(layout string) error { + return uinput.Paste(layout) +} diff --git a/autofill/autotype/unimplemented.go b/autofill/autotype/unimplemented.go new file mode 100644 index 0000000..a7d8c73 --- /dev/null +++ b/autofill/autotype/unimplemented.go @@ -0,0 +1,7 @@ +//go:build !linux + +package autotype + +func TypeString(text string, layout string) error { + return errors.New("Not implemented") +} diff --git a/go.mod b/go.mod index cb6c973..f2b49dc 100644 --- a/go.mod +++ b/go.mod @@ -19,9 +19,9 @@ require ( github.com/tink-crypto/tink-go/v2 v2.0.0 github.com/twpayne/go-pinentry v0.2.0 github.com/vmihailenco/msgpack/v5 v5.3.5 - golang.org/x/crypto v0.11.0 + golang.org/x/crypto v0.13.0 golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 - golang.org/x/sys v0.10.0 + golang.org/x/sys v0.12.0 ) require ( @@ -38,7 +38,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91 // indirect golang.org/x/image v0.5.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/text v0.13.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 151ec3b..5e48980 100644 --- a/go.sum +++ b/go.sum @@ -105,12 +105,15 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91 h1:ryT6Nf0R83ZgD8WnFFdfI8wCeyqgdXWN4+CkFVNPAT0= @@ -141,15 +144,20 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=