| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- package keychainlinker
- import (
- "fmt"
- "strconv"
- "github.com/godbus/dbus/v5"
- "github.com/godbus/dbus/v5/introspect"
- )
- type CacheItem struct {
- Secret SecretStruct
- Label string
- LookupProps map[string]string
- }
- type Collection struct {
- /*
- Implying the org.freedesktop.Secret.Collection interface as per the v0.2 spec:
- https://specifications.freedesktop.org/secret-service-spec/latest-single/#org.freedesktop.Secret.Collection
- */
- Items []dbus.ObjectPath // items in the collection
- Cache map[dbus.ObjectPath]CacheItem // memory cache for the collection. Will be removed later
- PathCount int
- PathBase string
- Private string // specifies whether the collection is private or not
- Label string // The displayable label of this collection.
- Locked string // Whether the collection is locked and must be authenticated by the client application.
- Created uint64 // The unix time when the collection was created.
- Modified uint64 // The unix time when the collection was last modified.
- }
- func (c *Collection) GetAll(iface string) (map[string]dbus.Variant, *dbus.Error) {
- if iface == "org.freedesktop.Secret.Collection" {
- return map[string]dbus.Variant{
- "Label": dbus.MakeVariant(c.Label),
- "Locked": dbus.MakeVariant(c.Locked),
- "Created": dbus.MakeVariant(c.Created),
- "Modified": dbus.MakeVariant(c.Modified),
- "Items": dbus.MakeVariant(c.Items),
- }, nil
- }
- return nil, dbus.MakeFailedError(fmt.Errorf("no such interface"))
- }
- /*
- Create a path to assign the secret
- */
- func (c *Collection) pathBuilder() dbus.ObjectPath {
- return dbus.ObjectPath(c.PathBase + "/" + strconv.Itoa(c.PathCount+1))
- }
- // deletes the collection, returning an object path tied to a prompt incase it is necessary.
- func (c *Collection) Delete() (dbus.ObjectPath, *dbus.Error) {
- return dbus.ObjectPath("prompt"), nil
- }
- /*
- Searches the collection for matching items
- :param attr: the attributes to attempt to match to a key in the collection
- */
- func (c *Collection) SearchItems(attr map[string]string) ([]dbus.ObjectPath, *dbus.Error) {
- fmt.Println("recv call for SearchItems")
- matched := []dbus.ObjectPath{}
- for path, sec := range c.Cache {
- secretAttr := sec.LookupProps
- var passedLookup bool
- passedLookup = false
- for k, v := range attr {
- got, ok := secretAttr[k]
- if !ok {
- continue
- }
- if got == v {
- passedLookup = true
- continue
- }
- }
- if passedLookup {
- matched = append(matched, path)
- }
- }
- return matched, nil
- }
- /*
- Creates a new item in the collection with the properties defined in 'props'.
- Returns the items dbus object path, as well as a path to a dbus prompt incase it is required to edit
- :param props: a map of properties to assign to the item. Will be used to match during lookups
- :param secret: the secret to encode into the collection
- :param replace: replace secret if a matching one is found in the store
- */
- func (c *Collection) CreateItem(props map[string]dbus.Variant, secret SecretStruct, replace bool) (dbus.ObjectPath, dbus.ObjectPath, *dbus.Error) {
- v := props["org.freedesktop.Secret.Item.Attributes"]
- attrs, ok := v.Value().(map[string]string)
- if !ok {
- return dbus.ObjectPath("/"), dbus.ObjectPath("/"), &dbus.ErrMsgNoObject
- }
- label, ok := props["org.freedesktop.Secret.Item.Label"].Value().(string)
- if !ok {
- // no label found
- label = ""
- }
- if !replace {
- // implement the the replace option
- }
- path := c.pathBuilder()
- c.Cache[path] = CacheItem{
- LookupProps: attrs,
- Label: label,
- Secret: secret,
- }
- return path, dbus.ObjectPath("/"), nil
- }
- // implementing method to read the object property
- func (c *Collection) Get(iface, property string) (dbus.Variant, *dbus.Error) {
- if iface != "org/freedesktop/secret/service" {
- return dbus.Variant{}, dbus.MakeFailedError(dbus.ErrMsgUnknownInterface)
- }
- switch property {
- case "Items":
- return dbus.MakeVariant(c.Items), nil
- case "Label":
- return dbus.MakeVariant(c.Label), nil
- case "Locked":
- return dbus.MakeVariant(c.Locked), nil
- case "Created":
- return dbus.MakeVariant(c.Created), nil
- case "Modified":
- return dbus.MakeVariant(c.Modified), nil
- default:
- return dbus.Variant{}, dbus.MakeFailedError(dbus.ErrMsgUnknownMethod)
- }
- }
- // implementing method to read the object property
- func (c *Collection) Set(iface, property string, value dbus.Variant) *dbus.Error {
- if iface != "org/freedesktop/secret/service" {
- return dbus.MakeFailedError(dbus.ErrMsgUnknownInterface)
- }
- switch property {
- case "Label":
- label, ok := value.Value().(string)
- if !ok {
- return dbus.MakeFailedError(dbus.ErrMsgInvalidArg)
- }
- c.Label = label
- return nil
- default:
- return dbus.MakeFailedError(dbus.ErrMsgUnknownMethod)
- }
- }
- var CollectionNode = introspect.Node{
- Name: "/org/freedesktop/secrets/collection/default", // or your collection path
- Interfaces: []introspect.Interface{
- {
- Name: "org.freedesktop.Secret.Collection",
- Methods: []introspect.Method{
- {
- Name: "CreateItem",
- Args: []introspect.Arg{
- {Name: "properties", Type: "a{sv}", Direction: "in"},
- {Name: "secret", Type: "v", Direction: "in"},
- {Name: "replace", Type: "b", Direction: "in"},
- {Name: "item", Type: "o", Direction: "out"},
- {Name: "prompt", Type: "o", Direction: "out"},
- },
- },
- {
- Name: "SearchItems",
- Args: []introspect.Arg{
- {Name: "attributes", Type: "a{ss}", Direction: "in"},
- {Name: "unlocked", Type: "ao", Direction: "out"},
- {Name: "locked", Type: "ao", Direction: "out"},
- },
- },
- {
- Name: "Delete",
- Args: []introspect.Arg{
- {Name: "prompt", Type: "o", Direction: "out"},
- },
- },
- },
- Properties: []introspect.Property{
- {Name: "Items", Type: "ao", Access: "read"},
- {Name: "Label", Type: "s", Access: "readwrite"},
- {Name: "Locked", Type: "b", Access: "read"},
- {Name: "Created", Type: "t", Access: "read"},
- {Name: "Modified", Type: "t", Access: "read"},
- },
- },
- {
- Name: "org.freedesktop.DBus.Introspectable",
- Methods: []introspect.Method{
- {
- Name: "Introspect",
- Args: []introspect.Arg{
- {Name: "data", Type: "s", Direction: "out"},
- },
- },
- },
- },
- },
- }
|