Refactor platform abstractions
This commit is contained in:
parent
5490eb2cb1
commit
a566d71223
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
8
agent/systemauth/biometrics/windows.go
Normal file
8
agent/systemauth/biometrics/windows.go
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build windows
|
||||
|
||||
package biometrics
|
||||
|
||||
func CheckBiometrics(approvalType Approval) bool {
|
||||
log.Info("Biometrics undefined on windows... skipping")
|
||||
return true
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
package systemauth
|
||||
//go:build linux || freebsd
|
||||
|
||||
package pinentry
|
||||
|
||||
import (
|
||||
"errors"
|
@ -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() {
|
13
agent/systemauth/pinentry/unimplemented.go
Normal file
13
agent/systemauth/pinentry/unimplemented.go
Normal file
@ -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")
|
||||
}
|
@ -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)
|
||||
|
13
autofill/autotype/uinputautotype.go
Normal file
13
autofill/autotype/uinputautotype.go
Normal file
@ -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)
|
||||
}
|
7
autofill/autotype/unimplemented.go
Normal file
7
autofill/autotype/unimplemented.go
Normal file
@ -0,0 +1,7 @@
|
||||
//go:build !linux
|
||||
|
||||
package autotype
|
||||
|
||||
func TypeString(text string, layout string) error {
|
||||
return errors.New("Not implemented")
|
||||
}
|
6
go.mod
6
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 (
|
||||
|
8
go.sum
8
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=
|
||||
|
Loading…
x
Reference in New Issue
Block a user