From 07372e614fb45baa337eaca014ed232b7b196200 Mon Sep 17 00:00:00 2001 From: Ulrich Kautz Date: Thu, 15 Feb 2018 13:37:57 +0100 Subject: [PATCH 1/2] Fallback to default secret object path The object path `/org/freedesktop/secrets/collection/login` is not necessarily available. The D-Bus API reference from freedesktop.org specifies `/org/freedesktop/secrets/aliases/default`, which is commonly used. See: https://specifications.freedesktop.org/secret-service/ch12.html This patch tries to accommodate both scenarios, by first checking whether the "old form" is available. If so it will be used as before, if not it will fall back to the alias. --- keyring_linux.go | 5 ++-- secret_service/secret_service.go | 44 +++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/keyring_linux.go b/keyring_linux.go index 39e1060..4148bd3 100644 --- a/keyring_linux.go +++ b/keyring_linux.go @@ -2,7 +2,6 @@ package keyring import ( "fmt" - "github.com/godbus/dbus" "github.com/zalando/go-keyring/secret_service" ) @@ -31,7 +30,7 @@ func (s secretServiceProvider) Set(service, user, pass string) error { secret := ss.NewSecret(session.Path(), pass) - collection := svc.GetCollection("login") + collection := svc.GetLoginCollection() err = svc.Unlock(collection.Path()) if err != nil { @@ -50,7 +49,7 @@ func (s secretServiceProvider) Set(service, user, pass string) error { // findItem looksup an item by service and user. func (s secretServiceProvider) findItem(svc *ss.SecretService, service, user string) (dbus.ObjectPath, error) { - collection := svc.GetCollection("login") + collection := svc.GetLoginCollection() search := map[string]string{ "username": user, diff --git a/secret_service/secret_service.go b/secret_service/secret_service.go index 7be3866..8f4a8fd 100644 --- a/secret_service/secret_service.go +++ b/secret_service/secret_service.go @@ -7,15 +7,17 @@ import ( ) const ( - serviceName = "org.freedesktop.secrets" - servicePath = "/org/freedesktop/secrets" - serviceInterface = "org.freedesktop.Secret.Service" - collectionInterface = "org.freedesktop.Secret.Collection" - itemInterface = "org.freedesktop.Secret.Item" - sessionInterface = "org.freedesktop.Secret.Session" - promptInterface = "org.freedesktop.Secret.Prompt" - - collectionBasePath = "/org/freedesktop/secrets/collection/" + serviceName = "org.freedesktop.secrets" + servicePath = "/org/freedesktop/secrets" + serviceInterface = "org.freedesktop.Secret.Service" + collectionInterface = "org.freedesktop.Secret.Collection" + collectionsInterface = "org.freedesktop.Secret.Service.Collections" + itemInterface = "org.freedesktop.Secret.Item" + sessionInterface = "org.freedesktop.Secret.Session" + promptInterface = "org.freedesktop.Secret.Prompt" + + loginCollectionAlias = "/org/freedesktop/secrets/aliases/default" + collectionBasePath = "/org/freedesktop/secrets/collection/" ) // Secret defines a org.freedesk.Secret.Item secret struct. @@ -67,11 +69,35 @@ func (s *SecretService) OpenSession() (dbus.BusObject, error) { return s.Object(serviceName, sessionPath), nil } +// GetCollections returns list of available collections +func (s *SecretService) CheckCollectionPath(path dbus.ObjectPath) (bool, error) { + obj := s.Conn.Object(serviceName, servicePath) + val, err := obj.GetProperty(collectionsInterface) + if err != nil { + return false, err + } + paths := val.Value().([]dbus.ObjectPath) + for _, p := range paths { + if p == path { + return true, nil + } + } + return false, nil +} + // GetCollection returns a collection from a name. func (s *SecretService) GetCollection(name string) dbus.BusObject { return s.Object(serviceName, dbus.ObjectPath(collectionBasePath+name)) } +func (s *SecretService) GetLoginCollection() dbus.BusObject { + path := dbus.ObjectPath(collectionBasePath + "login") + if ok, err := s.CheckCollectionPath(path); err != nil || !ok { + path = dbus.ObjectPath(loginCollectionAlias) + } + return s.Object(serviceName, path) +} + // Unlock unlocks a collection. func (s *SecretService) Unlock(collection dbus.ObjectPath) error { var unlocked []dbus.ObjectPath From 5a3c137d50b7b1f83c8eb5b62edd67139d4046f9 Mon Sep 17 00:00:00 2001 From: Ulrich Kautz Date: Tue, 20 Feb 2018 17:49:21 +0100 Subject: [PATCH 2/2] Stopped being lazy, added documentation --- secret_service/secret_service.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/secret_service/secret_service.go b/secret_service/secret_service.go index 8f4a8fd..2a0791a 100644 --- a/secret_service/secret_service.go +++ b/secret_service/secret_service.go @@ -3,6 +3,7 @@ package ss import ( "fmt" + "errors" "github.com/godbus/dbus" ) @@ -69,20 +70,21 @@ func (s *SecretService) OpenSession() (dbus.BusObject, error) { return s.Object(serviceName, sessionPath), nil } -// GetCollections returns list of available collections -func (s *SecretService) CheckCollectionPath(path dbus.ObjectPath) (bool, error) { +// CheckCollectionPath accepts dbus path and returns nil if the path is found +// in the collection interface (and can be used). +func (s *SecretService) CheckCollectionPath(path dbus.ObjectPath) error { obj := s.Conn.Object(serviceName, servicePath) val, err := obj.GetProperty(collectionsInterface) if err != nil { - return false, err + return err } paths := val.Value().([]dbus.ObjectPath) for _, p := range paths { if p == path { - return true, nil + return nil } } - return false, nil + return errors.New("path not found") } // GetCollection returns a collection from a name. @@ -90,9 +92,10 @@ func (s *SecretService) GetCollection(name string) dbus.BusObject { return s.Object(serviceName, dbus.ObjectPath(collectionBasePath+name)) } +// GetLoginCollection decides and returns the dbus collection to be used for login. func (s *SecretService) GetLoginCollection() dbus.BusObject { path := dbus.ObjectPath(collectionBasePath + "login") - if ok, err := s.CheckCollectionPath(path); err != nil || !ok { + if err := s.CheckCollectionPath(path); err != nil { path = dbus.ObjectPath(loginCollectionAlias) } return s.Object(serviceName, path)