This commit is contained in:
github-actions[bot] 2024-11-06 19:37:30 +00:00 committed by GitHub
commit d98f6193fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 103 additions and 28 deletions

View File

@ -40,7 +40,7 @@ modules:
- cp -R ./* /app/bin
- chmod +x /app/bin/goldwarden_ui_main.py
- install -D ./com.quexten.Goldwarden.desktop /app/share/applications/com.quexten.Goldwarden.desktop
- install -D ./goldwarden.svg /app/share/icons/hicolor/scalable/apps/com.quexten.Goldwarden.svg
- install -D ./com.quexten.Goldwarden.svg /app/share/icons/hicolor/scalable/apps/com.quexten.Goldwarden.svg
- install -Dm644 ./com.quexten.Goldwarden.metainfo.xml -t /app/share/metainfo/
- blueprint-compiler batch-compile /app/bin/src/gui/.templates/ /app/bin/src/gui/ /app/bin/src/gui/*.blp
sources:

View File

@ -19,7 +19,7 @@ jobs:
run: sudo apt-get install -y libfido2-dev
- name: Build
run: go build -o goldwarden -v .
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: goldwarden
path: ./goldwarden
@ -37,7 +37,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Download daemon
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: goldwarden
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6

View File

@ -1,4 +1,4 @@
<img src="https://raw.githubusercontent.com/quexten/goldwarden/main/gui/goldwarden.svg" width=200>
<img src="https://raw.githubusercontent.com/quexten/goldwarden/main/gui/com.quexten.Goldwarden.svg" width=200>
# Goldwarden

View File

@ -98,6 +98,9 @@ func makeAuthenticatedHTTPRequest(ctx context.Context, req *http.Request, recv i
req.Header.Set("Authorization", "Bearer "+token)
}
req.Header.Set("device-type", deviceType())
req.Header.Set("User-Agent", "Goldwarden (github.com/quexten/goldwarden)")
req.Header.Set("Bitwarden-Client-Name", "goldwarden")
req.Header.Set("Bitwarden-Client-Version", "0.0.0")
res, err := httpClient.Do(req)
if err != nil {

View File

@ -76,7 +76,8 @@ type Cipher struct {
Login *LoginCipher `json:"login,omitempty"`
Notes *crypto.EncString `json:"notes,omitempty"`
SecureNote *SecureNoteCipher `json:"secureNote,omitempty"`
SSHKey *SSHKeyCipher `json:"sshKey,omitempty"`
Key *crypto.EncString `json:"key,omitempty"`
}
@ -88,8 +89,15 @@ const (
CipherCard = 3
CipherIdentity = 4
CipherNote = 2
CipherSSHKey = 5
)
type SSHKeyCipher struct {
PrivateKey crypto.EncString `json:"privateKey"`
PublicKey crypto.EncString `json:"publicKey"`
KeyFingerprint crypto.EncString `json:"keyFingerprint"`
}
type Card struct {
CardholderName crypto.EncString `json:"cardholderName"`
Brand crypto.EncString `json:"brand"`

View File

@ -59,6 +59,8 @@ func DoFullSync(ctx context.Context, vault *vault.Vault, config *config.Config,
vault.AddOrUpdateLogin(cipher)
case models.CipherNote:
vault.AddOrUpdateSecureNote(cipher)
case models.CipherSSHKey:
vault.AddOrUpdateSSHKey(cipher)
}
}

View File

@ -9,11 +9,16 @@ import (
"github.com/twpayne/go-pinentry"
)
func getPassword(title string, description string) (string, error) {
func getBinaryClientOption() (clientOption pinentry.ClientOption) {
binaryClientOption := pinentry.WithBinaryNameFromGnuPGAgentConf()
if runtime.GOOS == "darwin" {
binaryClientOption = pinentry.WithBinaryName("pinentry-mac")
}
return binaryClientOption
}
func getPassword(title string, description string) (string, error) {
binaryClientOption := getBinaryClientOption()
client, err := pinentry.NewClient(
binaryClientOption,
@ -49,8 +54,10 @@ func getApproval(title string, description string) (bool, error) {
return true, nil
}
binaryClientOption := getBinaryClientOption()
client, err := pinentry.NewClient(
pinentry.WithBinaryNameFromGnuPGAgentConf(),
binaryClientOption,
pinentry.WithGPGTTY(),
pinentry.WithTitle(title),
pinentry.WithDesc(description),

View File

@ -55,9 +55,12 @@ func (s *SessionStore) CreateSession(pid int, parentpid int, grandparentpid int,
func (s *SessionStore) verifySession(ctx sockets.CallingContext, sessionType SessionType) bool {
for _, session := range s.Store {
if session.ParentPid == ctx.ParentProcessPid && session.GrandParentPid == ctx.GrandParentProcessPid && session.sessionType == sessionType {
if session.Expires.After(time.Now()) {
return true
if session.sessionType == sessionType {
// only check for ancestor if the session is not a ssh session
if sessionType == SSHKey || (session.ParentPid == ctx.ParentProcessPid && session.GrandParentPid == ctx.GrandParentProcessPid) {
if session.Expires.After(time.Now()) {
return true
}
}
}
}

View File

@ -3,6 +3,8 @@ package vault
import (
"errors"
"strings"
"fmt"
"regexp"
"sync"
"github.com/quexten/goldwarden/cli/agent/bitwarden/crypto"
@ -17,6 +19,7 @@ type Vault struct {
Keyring *crypto.Keyring
logins map[string]models.Cipher
secureNotes map[string]models.Cipher
sshKeys map[string]models.Cipher
sshKeyNoteIDs []string
envCredentials map[string]string
lastSynced int64
@ -29,6 +32,7 @@ func NewVault(keyring *crypto.Keyring) *Vault {
Keyring: keyring,
logins: make(map[string]models.Cipher),
secureNotes: make(map[string]models.Cipher),
sshKeys: make(map[string]models.Cipher),
sshKeyNoteIDs: make([]string, 0),
envCredentials: make(map[string]string),
lastSynced: 0,
@ -90,6 +94,12 @@ func (vault *Vault) AddOrUpdateSecureNote(cipher models.Cipher) {
vault.unlockMutex()
}
func (vault *Vault) AddOrUpdateSSHKey(cipher models.Cipher) {
vault.lockMutex()
vault.sshKeys[cipher.ID.String()] = cipher
vault.unlockMutex()
}
func (vault *Vault) isEnv(cipher models.Cipher) (string, bool) {
if cipher.Type != models.CipherNote {
return "", false
@ -174,6 +184,26 @@ type SSHKey struct {
PublicKey string
}
func extractKeyMarker(text, pattern string) (string, string, error) {
re := regexp.MustCompile(pattern)
match := re.FindStringIndex(text)
if match != nil {
// Extract the matched text
extracted := re.FindString(text[match[0]:match[1]])
if match[0] == 0 {
// begin marker
return extracted, text[match[1]:], nil
} else if match[1] == len(strings.TrimRight(text, "\n\r ")) {
// end marker
return extracted, text[:match[0]], nil
}
return "", text, fmt.Errorf("Token found is neither at the beginning nor end: pattern: %s. match idx: %s", pattern, match)
}
return "", text, fmt.Errorf("No match found in pattern %s", pattern)
}
func (vault *Vault) GetSSHKeys() []SSHKey {
vault.lockMutex()
defer vault.unlockMutex()
@ -211,11 +241,19 @@ func (vault *Vault) GetSSHKeys() []SSHKey {
}
}
privateKey = strings.Replace(privateKey, "-----BEGIN OPENSSH PRIVATE KEY-----", "", 1)
privateKey = strings.Replace(privateKey, "-----END OPENSSH PRIVATE KEY-----", "", 1)
beginMarker, privateKey, err := extractKeyMarker(privateKey, `-----\w*BEGIN [a-zA-Z ]+\w*-----`)
if err != nil {
vaultLog.Error("Failed for note %s: %s", vault.secureNotes[id].Name, err.Error())
continue
}
endMarker, privateKey, err := extractKeyMarker(privateKey, `-----\w*END [a-zA-Z ]+\w*-----`)
if err != nil {
vaultLog.Error("Failed for note %s: %s", vault.secureNotes[id].Name, err.Error())
continue
}
pkParts := strings.Join(strings.Split(privateKey, " "), "\n")
privateKeyString := "-----BEGIN OPENSSH PRIVATE KEY-----" + pkParts + "-----END OPENSSH PRIVATE KEY-----"
privateKeyString := beginMarker + pkParts + endMarker
decryptedTitle, err := crypto.DecryptWith(vault.secureNotes[id].Name, key)
if err != nil {
@ -228,6 +266,20 @@ func (vault *Vault) GetSSHKeys() []SSHKey {
PublicKey: string(publicKey),
})
}
for id, _ := range vault.sshKeys {
key, _ := vault.sshKeys[id].GetKeyForCipher(*vault.Keyring)
privKey, _ := crypto.DecryptWith(vault.sshKeys[id].SSHKey.PrivateKey, key)
pubKey, _ := crypto.DecryptWith(vault.sshKeys[id].SSHKey.PublicKey, key)
name, _ := crypto.DecryptWith(vault.sshKeys[id].Name, key)
sshKeys = append(sshKeys, SSHKey{
Name: string(name),
Key: string(privKey),
PublicKey: string(pubKey),
})
}
return sshKeys
}

8
go.mod
View File

@ -14,20 +14,20 @@ require (
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/icza/gox v0.0.0-20230924165045-adcb03233bb5
github.com/icza/gox v0.2.0
github.com/keybase/client/go v0.0.0-20240424154521-52f30ea26cb1
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.3
github.com/rymdport/portal v0.2.6
github.com/spf13/cobra v1.8.1
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4
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.25.0
golang.org/x/crypto v0.28.0
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
golang.org/x/sys v0.22.0
golang.org/x/sys v0.26.0
)
require (

20
go.sum
View File

@ -36,8 +36,8 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/icza/gox v0.0.0-20230924165045-adcb03233bb5 h1:K7KEFpKgVcjj98jOu2Z3xMBTtTwfYVT90Zmo3ZuWmbE=
github.com/icza/gox v0.0.0-20230924165045-adcb03233bb5/go.mod h1:VbcN86fRkkUMPX2ufM85Um8zFndLZswoIW1eYtpAcVk=
github.com/icza/gox v0.2.0 h1:+0N8PCt9/QSx+k0dqe/wdlXJNR/haaPsPwrTJTNDeyk=
github.com/icza/gox v0.2.0/go.mod h1:rVecw5Q6POJAWBcXgCZdAtwK/hmoNehxCkAP3sMnOIc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/keybase/backoff v1.0.1-0.20160517061000-726b63b835ec h1:D6qL2WCnAuxucGbmL+mDW8IKRK1pex+R1fw5rKa9nXc=
@ -84,8 +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/rymdport/portal v0.2.6 h1:HWmU3gORu7vWcpr7VSwUS2Xx1HtJXVcUuTqEZcMEsIg=
github.com/rymdport/portal v0.2.6/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -106,8 +106,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU
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.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
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,10 +118,10 @@ 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.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
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=

View File

@ -102,7 +102,7 @@ modules:
- cp -R ./gui/* /app/bin
- chmod +x /app/bin/goldwarden_ui_main.py
- install -D ./gui/com.quexten.Goldwarden.desktop /app/share/applications/com.quexten.Goldwarden.desktop
- install -D ./gui/goldwarden.svg /app/share/icons/hicolor/scalable/apps/com.quexten.Goldwarden.svg
- install -D ./gui/com.quexten.Goldwarden.svg /app/share/icons/hicolor/scalable/apps/com.quexten.Goldwarden.svg
- install -Dm644 ./gui/com.quexten.Goldwarden.metainfo.xml -t /app/share/metainfo/
- blueprint-compiler batch-compile /app/bin/src/gui/.templates/ /app/bin/src/gui/ /app/bin/src/gui/*.blp
sources:

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB