Skip to content

Commit

Permalink
🧹 Compare only attributes we may have added (#10)
Browse files Browse the repository at this point in the history
When retrieving secrets that match the attributes we have, ignore any
attributes that we would not have added ourselves. It is conceivable
that another service or the user adds additional attributes to a secret
for their own purposes. We only care about exactly matching the
attributes we would have added ourselves, so do just that.

While we're here, tidy up the `SecretService.Store()` method and upgrade
the `gh` command managed by hermit.

This merges the following commits:
* Compare only attributes we may have added
* Tidy up SecretService.Store
* hermit: Upgrade gh

     bin/{.gh-2.54.0.pkg => .gh-2.55.0.pkg} |  0
     bin/gh                                 |  2 +-
     dbus.go                                | 40 ++++++++++++++------------
     main.go                                |  5 ++++
     4 files changed, 27 insertions(+), 20 deletions(-)

Pull-request: #10
  • Loading branch information
camh- committed Sep 6, 2024
2 parents c5af047 + 888170e commit c9d42e7
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 20 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion bin/gh
40 changes: 21 additions & 19 deletions dbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ func (ss *SecretService) Get(attrs map[string]string) (string, error) {
// the secret could not be created, an error is returned.
func (ss *SecretService) Store(label string, attrs map[string]string, secret string) error {
path := dbus.ObjectPath("/org/freedesktop/secrets/aliases/default")
// Try to unlock the collection first. Will be a no-op if it is not locked
// but if it is locked, we'll prompt the user to unlock it.
if _, err := ss.unlockObject(path); err != nil {
return err
}

collection := ss.conn.Object("org.freedesktop.secrets", path)
props := map[string]dbus.Variant{
"org.freedesktop.Secret.Item.Label": dbus.MakeVariant(label),
Expand All @@ -223,22 +229,17 @@ func (ss *SecretService) Store(label string, attrs map[string]string, secret str
return err
}

// Try to unlock the collection first. Will be a no-op if it is not locked
// but if it is locked, we'll prompt the user to unlock it.
if _, err := ss.unlockObject(path); err != nil {
return err
}

var itemPath, promptPath dbus.ObjectPath
call := collection.Call("org.freedesktop.Secret.Collection.CreateItem", 0, props, &sec, true)
if err := call.Store(&itemPath, &promptPath); err != nil {
return fmt.Errorf("couldn't create secret: %w", err)
}

if promptPath != noPrompt {
return ss.prompt(promptPath)
if promptPath == noPrompt {
return nil
}
return nil

return ss.prompt(promptPath)
}

// Delete removes a secret matching the given attributes. If expectedPassword
Expand Down Expand Up @@ -420,10 +421,13 @@ func (ss *SecretService) getSecret(itemPath dbus.ObjectPath) (secret Secret, err
return
}

// attrsMatch returns true if the given items have exactly the given
// attributes. If the item has extra or fewer attributes, or any values are
// different, false is returned. If the attributes of the item could be
// retrieved an error is returned.
// attrsMatch compares a map of attributes against the attributes of an item.
// Only the attributes that we may put on an item are compared. If there are
// other attributes added by other parties, they are ignored.
//
// attrsMatch returns true if all the attributes we care about match, or false
// if any differ. If the item attributes could not be retrieved, an eror is
// returned.
func (ss *SecretService) attrsMatch(attrs map[string]string, itemPath dbus.ObjectPath) (bool, error) {
item := ss.conn.Object("org.freedesktop.secrets", itemPath)
prop, err := item.GetProperty("org.freedesktop.Secret.Item.Attributes")
Expand All @@ -436,12 +440,10 @@ func (ss *SecretService) attrsMatch(attrs map[string]string, itemPath dbus.Objec
return false, fmt.Errorf("item attributes property is not a map: %v", itemPath)
}

if len(itemAttrs) != len(attrs) {
return false, nil
}
for k, v1 := range attrs {
v2, ok := itemAttrs[k]
if !ok || v1 != v2 {
for _, attr := range ourAttrs {
v1, ok1 := attrs[attr]
v2, ok2 := itemAttrs[attr]
if ok1 != ok2 || (ok1 && v1 != v2) {
return false, nil
}
}
Expand Down
5 changes: 5 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ func makeLabel(gc *GitCredential) string {
return label
}

// ourAttrs is a slice of attribute names we use on secrets stored in the
// Secret Service. It can be used to filter out attributes added/managed by
// others.
var ourAttrs = []string{"xdg:schema", "user", "protocol", "server", "port", "object"}

// makeAttrs maps the fields of GitCredentials to secret service attribues. The
// [mapping] is taken from git-credential-libsecret to be compatible with it.
//
Expand Down

0 comments on commit c9d42e7

Please sign in to comment.