diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 56e3057..adc3935 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,7 +114,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} build_macos_x86_64: - runs-on: macos-latest + runs-on: macos-13 steps: - name: Checkout uses: actions/checkout@v1 diff --git a/cli/agent/actions/ssh.go b/cli/agent/actions/ssh.go index 8dc9677..647be9e 100644 --- a/cli/agent/actions/ssh.go +++ b/cli/agent/actions/ssh.go @@ -16,12 +16,24 @@ import ( func handleAddSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext *sockets.CallingContext) (response messages.IPCMessage, err error) { req := messages.ParsePayload(msg).(messages.CreateSSHKeyRequest) - cipher, publicKey := ssh.NewSSHKeyCipher(req.Name, vault.Keyring) + cipher, publicKey, err := ssh.NewSSHKeyCipher(req.Name, vault.Keyring) + if err != nil { + response, err = messages.IPCMessageFromPayload(messages.ActionResponse{ + Success: false, + Message: err.Error(), + }) + return + } + _, err = messages.IPCMessageFromPayload(messages.ActionResponse{ Success: true, }) if err != nil { - panic(err) + response, err = messages.IPCMessageFromPayload(messages.ActionResponse{ + Success: false, + Message: err.Error(), + }) + return } token, err := cfg.GetToken() @@ -56,7 +68,49 @@ func handleListSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vau return } +func handleImportSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext *sockets.CallingContext) (response messages.IPCMessage, err error) { + req := messages.ParsePayload(msg).(messages.ImportSSHKeyRequest) + + cipher, _, err := ssh.SSHKeyCipherFromKey(req.Name, req.Key, vault.Keyring) + if err != nil { + response, err = messages.IPCMessageFromPayload(messages.ActionResponse{ + Success: false, + Message: err.Error(), + }) + return + } + + _, err = messages.IPCMessageFromPayload(messages.ActionResponse{ + Success: true, + }) + if err != nil { + response, err = messages.IPCMessageFromPayload(messages.ActionResponse{ + Success: false, + Message: err.Error(), + }) + return + } + + token, err := cfg.GetToken() + if err != nil { + actionsLog.Warn(err.Error()) + } + ctx := context.WithValue(context.TODO(), bitwarden.AuthToken{}, token.AccessToken) + postedCipher, err := bitwarden.PostCipher(ctx, cipher, cfg) + if err == nil { + vault.AddOrUpdateSecureNote(postedCipher) + } else { + actionsLog.Warn("Error posting ssh key cipher: " + err.Error()) + } + + response, err = messages.IPCMessageFromPayload(messages.ImportSSHKeyResponse{ + Success: true, + }) + return +} + func init() { AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.CreateSSHKeyRequest{}), ensureEverything(systemauth.SSHKey, handleAddSSH)) AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.GetSSHKeysRequest{}), ensureIsNotLocked(ensureIsLoggedIn(handleListSSH))) + AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.ImportSSHKeyRequest{}), ensureEverything(systemauth.SSHKey, handleImportSSH)) } diff --git a/cli/agent/bitwarden/websocket.go b/cli/agent/bitwarden/websocket.go index 551e287..f151c69 100644 --- a/cli/agent/bitwarden/websocket.go +++ b/cli/agent/bitwarden/websocket.go @@ -255,12 +255,11 @@ func parseMessageTypeFromMessagePack(messagePack []byte) (int8, string, bool) { return 0, "", false } if len(value) < 5 { - websocketLog.Warn("Invalid message received, length too short") return 0, "", false } value, success := value[4].([]interface{}) if len(value) < 1 || !success { - websocketLog.Warn("Invalid message received, length too short") + websocketLog.Warn("Invalid message received, value length less than 1") return 0, "", false } value1, success := value[0].(map[string]interface{}) diff --git a/cli/agent/ssh/keys.go b/cli/agent/ssh/keys.go index 5bf11ac..1af9139 100644 --- a/cli/agent/ssh/keys.go +++ b/cli/agent/ssh/keys.go @@ -12,8 +12,55 @@ import ( "golang.org/x/crypto/ssh" ) -func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, string) { +// todo refactor to share code +func SSHKeyCipherFromKey(name string, privateKey string, keyring *crypto.Keyring) (models.Cipher, string, error) { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { + return models.Cipher{}, "", err + } + pubKey := signer.PublicKey() + encryptedName, _ := crypto.EncryptWith([]byte(name), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedPublicKeyKey, _ := crypto.EncryptWith([]byte("public-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedPublicKeyValue, _ := crypto.EncryptWith([]byte(string(ssh.MarshalAuthorizedKey(pubKey))), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedCustomTypeKey, _ := crypto.EncryptWith([]byte("custom-type"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedCustomTypeValue, _ := crypto.EncryptWith([]byte("ssh-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedPrivateKeyKey, _ := crypto.EncryptWith([]byte("private-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + encryptedPrivateKeyValue, _ := crypto.EncryptWith([]byte(privateKey), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey()) + + cipher := models.Cipher{ + Type: models.CipherNote, + Name: encryptedName, + Notes: &encryptedPublicKeyValue, + ID: nil, + Favorite: false, + OrganizationID: nil, + SecureNote: &models.SecureNoteCipher{ + Type: 0, + }, + Fields: []models.Field{ + { + Type: 0, + Name: encryptedCustomTypeKey, + Value: encryptedCustomTypeValue, + }, + { + Type: 0, + Name: encryptedPublicKeyKey, + Value: encryptedPublicKeyValue, + }, + { + Type: 1, + Name: encryptedPrivateKeyKey, + Value: encryptedPrivateKeyValue, + }, + }, + } + + return cipher, string(ssh.MarshalAuthorizedKey(pubKey)), nil +} + +func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, string, error) { var reader io.Reader = rand.Reader pub, priv, err := ed25519.GenerateKey(reader) @@ -72,5 +119,5 @@ func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, strin }, } - return cipher, string(ssh.MarshalAuthorizedKey(publicKey)) + return cipher, string(ssh.MarshalAuthorizedKey(publicKey)), nil } diff --git a/cli/agent/systemauth/pinentry/go-pinentry.go b/cli/agent/systemauth/pinentry/go-pinentry.go index 673950a..648a7e3 100644 --- a/cli/agent/systemauth/pinentry/go-pinentry.go +++ b/cli/agent/systemauth/pinentry/go-pinentry.go @@ -1,16 +1,22 @@ -//go:build freebsd || linux +//go:build freebsd || linux || darwin package pinentry import ( "errors" + "runtime" "github.com/twpayne/go-pinentry" ) func getPassword(title string, description string) (string, error) { + binaryClientOption := pinentry.WithBinaryNameFromGnuPGAgentConf() + if runtime.GOOS == "darwin" { + binaryClientOption = pinentry.WithBinaryName("pinentry-mac") + } + client, err := pinentry.NewClient( - pinentry.WithBinaryNameFromGnuPGAgentConf(), + binaryClientOption, pinentry.WithGPGTTY(), pinentry.WithTitle(title), pinentry.WithDesc(description), diff --git a/cli/agent/systemauth/pinentry/keybase-pinentry.go b/cli/agent/systemauth/pinentry/keybase-pinentry.go index 0071fdd..a3486de 100644 --- a/cli/agent/systemauth/pinentry/keybase-pinentry.go +++ b/cli/agent/systemauth/pinentry/keybase-pinentry.go @@ -1,4 +1,4 @@ -//go:build windows || darwin +//go:build windows package pinentry diff --git a/cli/cmd/ssh.go b/cli/cmd/ssh.go index d1f18a4..f50927c 100644 --- a/cli/cmd/ssh.go +++ b/cli/cmd/ssh.go @@ -1,6 +1,7 @@ package cmd import ( + "bytes" "fmt" "os" @@ -18,12 +19,12 @@ var sshCmd = &cobra.Command{ }, } -// runCmd represents the run command +// sshAddCmd represents the ssh add command var sshAddCmd = &cobra.Command{ Use: "add", - Short: "Runs a command with environment variables from your vault", - Long: `Runs a command with environment variables from your vault. - The variables are stored as a secure note. Consult the documentation for more information.`, + Short: "Creates a new SSH key and adds it to the SSH Agent.", + Long: `Creates a new SSH key and adds it to the SSH Agent. + The key is stored as a secure note. Consult the documentation for more information.`, Run: func(cmd *cobra.Command, args []string) { err := loginIfRequired() if err != nil { @@ -92,6 +93,59 @@ var listSSHCmd = &cobra.Command{ }, } +var importSSHCmd = &cobra.Command{ + Use: "import", + Short: "Imports an SSH key into your vault", + Long: `Imports an SSH key into your vault.`, + Run: func(cmd *cobra.Command, args []string) { + filename := args[0] + fmt.Println("Importing SSH key from " + filename) + + name, _ := cmd.Flags().GetString("name") + if name == "" { + name = "Imported SSH Key" + } + + if _, err := os.Stat(filename); os.IsNotExist(err) { + fmt.Println("Error: File does not exist") + return + } + + file, err := os.Open(filename) + if err != nil { + fmt.Println("Error: " + err.Error()) + return + } + + buf := new(bytes.Buffer) + buf.ReadFrom(file) + key := buf.String() + + result, err := commandClient.SendToAgent(messages.ImportSSHKeyRequest{ + Key: key, + Name: name, + }) + if err != nil { + handleSendToAgentError(err) + return + } + + switch result.(type) { + case messages.ImportSSHKeyResponse: + response := result.(messages.ImportSSHKeyResponse) + if response.Success { + fmt.Println("Success") + } else { + fmt.Println("Error: " + response.ErrorMsg) + } + return + case messages.ActionResponse: + fmt.Println("Error: " + result.(messages.ActionResponse).Message) + return + } + }, +} + func init() { rootCmd.AddCommand(sshCmd) sshCmd.AddCommand(sshAddCmd) @@ -99,4 +153,6 @@ func init() { _ = sshAddCmd.MarkFlagRequired("name") sshAddCmd.PersistentFlags().Bool("clipboard", false, "Copy the public key to the clipboard") sshCmd.AddCommand(listSSHCmd) + importSSHCmd.PersistentFlags().String("name", "", "") + sshCmd.AddCommand(importSSHCmd) } diff --git a/cli/ipc/messages/sshkeys.go b/cli/ipc/messages/sshkeys.go index 0339a38..d6860f8 100644 --- a/cli/ipc/messages/sshkeys.go +++ b/cli/ipc/messages/sshkeys.go @@ -17,6 +17,16 @@ type GetSSHKeysResponse struct { Keys []string } +type ImportSSHKeyRequest struct { + Key string + Name string +} + +type ImportSSHKeyResponse struct { + Success bool + ErrorMsg string +} + func init() { registerPayloadParser(func(payload []byte) (interface{}, error) { var req CreateSSHKeyRequest @@ -53,4 +63,22 @@ func init() { } return req, nil }, GetSSHKeysResponse{}) + + registerPayloadParser(func(payload []byte) (interface{}, error) { + var req ImportSSHKeyRequest + err := json.Unmarshal(payload, &req) + if err != nil { + panic("Unmarshal: " + err.Error()) + } + return req, nil + }, ImportSSHKeyRequest{}) + + registerPayloadParser(func(payload []byte) (interface{}, error) { + var req ImportSSHKeyResponse + err := json.Unmarshal(payload, &req) + if err != nil { + panic("Unmarshal: " + err.Error()) + } + return req, nil + }, ImportSSHKeyResponse{}) } diff --git a/go.mod b/go.mod index d597561..0925e33 100644 --- a/go.mod +++ b/go.mod @@ -19,15 +19,15 @@ require ( github.com/lox/go-touchid v0.0.0-20170712105233-619cc8e578d0 github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a github.com/mitchellh/go-ps v1.0.0 - github.com/rymdport/portal v0.2.2 + github.com/rymdport/portal v0.2.3 github.com/spf13/cobra v1.8.0 github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 - github.com/tink-crypto/tink-go/v2 v2.1.0 + github.com/tink-crypto/tink-go/v2 v2.2.0 github.com/twpayne/go-pinentry v0.3.0 github.com/vmihailenco/msgpack/v5 v5.4.1 - golang.org/x/crypto v0.22.0 + golang.org/x/crypto v0.23.0 golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f - golang.org/x/sys v0.19.0 + golang.org/x/sys v0.20.0 ) require ( @@ -56,5 +56,3 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect ) - -replace github.com/rymdport/portal => github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5 diff --git a/go.sum b/go.sum index 92f5b34..2cf9e1c 100644 --- a/go.sum +++ b/go.sum @@ -76,8 +76,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5 h1:roVJ7WlvNo3R4NfVLysq3siLrVZgotg/JZkZ1dQEZ5k= -github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM= github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI= github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas= @@ -86,6 +84,8 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rymdport/portal v0.2.3 h1:5RoAuMy5wNzEzITwK+9YpMQLU5m7F7IYfmPwN/aVpUk= +github.com/rymdport/portal v0.2.3/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -98,16 +98,16 @@ github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG0 github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 h1:Gz0rz40FvFVLTBk/K8UNAenb36EbDSnh+q7Z9ldcC8w= github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4/go.mod h1:phI29ccmHQBc+wvroosENp1IF9195449VDnFDhJ4rJU= -github.com/tink-crypto/tink-go/v2 v2.1.0 h1:QXFBguwMwTIaU17EgZpEJWsUSc60b1BAGTzBIoMdmok= -github.com/tink-crypto/tink-go/v2 v2.1.0/go.mod h1:y1TnYFt1i2eZVfx4OGc+C+EMp4CoKWAw2VSEuoicHHI= +github.com/tink-crypto/tink-go/v2 v2.2.0 h1:L2Da0F2Udh2agtKztdr69mV/KpnY3/lGTkMgLTVIXlA= +github.com/tink-crypto/tink-go/v2 v2.2.0/go.mod h1:JJ6PomeNPF3cJpfWC0lgyTES6zpJILkAX0cJNwlS3xU= github.com/twpayne/go-pinentry v0.3.0 h1:Rr+fEOZXmeItOb4thjeVaBWJKB9Xa/eojolycyF/26c= github.com/twpayne/go-pinentry v0.3.0/go.mod h1:iOIZD+9np/2V24OdCGos7Y1/xX90wc6VEAZsgb+r9D4= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= @@ -118,12 +118,12 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/gui/goldwarden_ui_main.py b/gui/goldwarden_ui_main.py index d6df4d2..e739a28 100755 --- a/gui/goldwarden_ui_main.py +++ b/gui/goldwarden_ui_main.py @@ -1,4 +1,12 @@ #!/usr/bin/env python3 -import src.linux.main as linux_main -linux_main.main() \ No newline at end of file +import platform + +if platform.system() == 'Darwin': + import src.macos.main as macos_main + macos_main.main() +elif platform.system() == 'Linux': + import src.linux.main as linux_main + linux_main.main() +else: + print("Unsupported OS " + platform.system() + "... exiting...") \ No newline at end of file diff --git a/gui/src/gui/quickaccess.py b/gui/src/gui/quickaccess.py index 4030814..3a08268 100644 --- a/gui/src/gui/quickaccess.py +++ b/gui/src/gui/quickaccess.py @@ -1,10 +1,10 @@ import gi gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') -gi.require_version('Notify', '0.7') +# gi.require_version('Notify', '0.7') import gc import time -from gi.repository import Gtk, Adw, GLib, Notify, Gdk +from gi.repository import Gtk, Adw, GLib, Gdk from ..services import goldwarden from ..services.autotype import autotype from threading import Thread @@ -12,7 +12,6 @@ from .resource_loader import load_template import sys import os from ..services import totp -Notify.init("Goldwarden") class GoldwardenQuickAccessApp(Adw.Application): def __init__(self, **kwargs): @@ -115,8 +114,8 @@ class GoldwardenQuickAccessApp(Adw.Application): def run_autotype(self, text): def perform_autotype(text): - self.window.hide() - time.sleep(0.1) + GLib.idle_add(self.window.hide) + time.sleep(2) autotype.autotype(text) time.sleep(0.1) os._exit(0) @@ -148,7 +147,7 @@ class GoldwardenQuickAccessApp(Adw.Application): self.filtered_logins = self.filtered_logins[0:7] def render_list(self): - if len(self.filtered_logins) > 1: + if len(self.filtered_logins) > 0: self.results_list.set_visible(True) while self.results_list.get_first_child() != None: self.results_list.remove(self.results_list.get_first_child()) diff --git a/gui/src/gui/settings.py b/gui/src/gui/settings.py index ab88cd2..fc38fa2 100644 --- a/gui/src/gui/settings.py +++ b/gui/src/gui/settings.py @@ -101,8 +101,7 @@ class GoldwardenSettingsApp(Adw.Application): if status == None: is_daemon_running = goldwarden.is_daemon_running() if not is_daemon_running: - self.status_row.set_subtitle("Daemon not running") - self.vault_status_icon.set_icon("dialog-error", "error") + print("Daemon not running") return logged_in = status["loggedIn"] diff --git a/gui/src/linux/flatpak/status.py b/gui/src/linux/flatpak/status.py index 6c1aaf9..44391e3 100644 --- a/gui/src/linux/flatpak/status.py +++ b/gui/src/linux/flatpak/status.py @@ -7,6 +7,7 @@ gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') from gi.repository import GLib, Gio import sys +from threading import Timer def set_status(message): bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) @@ -29,9 +30,13 @@ def set_status(message): sys.exit(0) except Exception as e: print(e) + sys.exit(0) if len(sys.argv) > 1: set_status(sys.argv[1]) +thread = Timer(10, sys.exit, [0]) +thread.start() + loop = GLib.MainLoop() loop.run() diff --git a/gui/src/macos/main.py b/gui/src/macos/main.py new file mode 100644 index 0000000..cf8f94e --- /dev/null +++ b/gui/src/macos/main.py @@ -0,0 +1,30 @@ +import sys +import subprocess +import os +import secrets +from src.services import goldwarden +from src.services import pinentry +import time + +root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir)) + +def main(): + token = secrets.token_hex(32) + if not os.environ.get("GOLDWARDEN_DAEMON_AUTH_TOKEN") == None: + token = os.environ["GOLDWARDEN_DAEMON_AUTH_TOKEN"] + print("Starting Goldwarden GUI") + goldwarden.run_daemon_background(token) + time.sleep(1) + #pinentry.daemonize() + if not "--hidden" in sys.argv: + p = subprocess.Popen(["python3", "-m", "src.gui.settings"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=root_path, start_new_session=True) + p.stdin.write(f"{token}\n".encode()) + p.stdin.flush() + # print stdout + while True: + line = p.stderr.readline() + if not line: + break + print(line.decode().strip()) + while True: + time.sleep(60) \ No newline at end of file diff --git a/gui/src/services/autotype/libportal_autotype.py b/gui/src/services/autotype/libportal_autotype.py index e5de665..55faf33 100644 --- a/gui/src/services/autotype/libportal_autotype.py +++ b/gui/src/services/autotype/libportal_autotype.py @@ -1,5 +1,5 @@ from ..goldwarden import autotype -def libportal_autotype(text): +def autotype_libportal(text): print("autotypeing with libportal") goldwarden.autotype(text) \ No newline at end of file diff --git a/gui/src/services/autotype/pyautogui_autotype.py b/gui/src/services/autotype/pyautogui_autotype.py index 3b8057a..0a9214b 100644 --- a/gui/src/services/autotype/pyautogui_autotype.py +++ b/gui/src/services/autotype/pyautogui_autotype.py @@ -2,4 +2,7 @@ import pyautogui def autotype_pyautogui(text): print("autotypeing with pyautogui") - pyautogui.write(text, interval=0.02) \ No newline at end of file + pyautogui.write(text, interval=0.02) + +if __name__ == "__main__": + autotype_pyautogui("hello world") \ No newline at end of file