예제 #1
0
func (s *ssProvider) Set(c, u, p string) error {
	var item, prompt dbus.ObjectPath
	properties := map[string]dbus.Variant{
		"org.freedesktop.Secret.Item.Label": dbus.MakeVariant(fmt.Sprintf("%s - %s", u, c)),
		"org.freedesktop.Secret.Item.Attributes": dbus.MakeVariant(map[string]string{
			"username": u,
			"service":  c,
		}),
	}

	session, err := s.openSession()
	if err != nil {
		return err
	}
	defer session.Call(fmt.Sprint(ssSessionIface, "Close"), 0)
	s.unlock(ssCollectionPath)
	collection := s.Object(ssServiceName, ssCollectionPath)

	secret := newSSSecret(session.Path(), p)
	// the bool is "replace"
	err = collection.Call(fmt.Sprint(ssCollectionIface, "CreateItem"), 0, properties, secret, true).Store(&item, &prompt)
	if err != nil {
		return fmt.Errorf("keyring/dbus: CreateItem error: %s", err)
	}
	if prompt != "/" {
		s.Object(ssServiceName, prompt).Call(fmt.Sprint(ssPromptIface, "Prompt"), 0, "unlock")
	}
	return nil
}
예제 #2
0
// The first argument is the Label for the collection, and the second is an (optional) alias.
func (s Service) CreateCollection(label, alias string) (Collection, error) {
	// spec: CreateCollection(IN Dict<String,Variant> properties, IN String alias, OUT ObjectPath collection, OUT ObjectPath prompt);
	var collectionPath, promptPath dbus.ObjectPath
	conn, err := dbus.SessionBus()
	if err != nil {
		return Collection{}, err
	}
	properties := map[string]dbus.Variant{
		_CollectionLabel: dbus.MakeVariant(label),
	}
	call := s.Call(_ServiceCreateCollection, 0, properties, alias)
	if call.Err != nil {
		return Collection{}, call.Err
	}
	err = call.Store(&collectionPath, &promptPath)
	if err != nil {
		return Collection{}, err
	}
	if dbus.ObjectPath("/") != collectionPath {
		return Collection{conn.Object(ServiceName, collectionPath)}, nil
	}
	v, err := checkPrompt(promptPath)
	if err != nil {
		return Collection{}, err
	}
	return Collection{conn.Object(ServiceName, dbus.ObjectPath(v.Value().(string)))},
		fmt.Errorf("unable to create collection")
}
예제 #3
0
// First argument is the algorithm used. "plain" (AlgoPlain) and
// "dh-ietf1024-sha256-aes128-cbc-pkcs7" (AlgoDH) are supported.
//
// The dbus api has the caller supply their DH public key and returns
// the other side's public key, but this implementation generates a
// new keypair, does the exchange, derives the encryption key, and then
// stores it in the returned Session.
func (s Service) OpenSession(algo string, args ...interface{}) (Session, error) {
	// spec: OpenSession(IN String algorithm, IN Variant input, OUT Variant output, OUT ObjectPath result);
	var ret Session
	conn, err := dbus.SessionBus()
	if err != nil {
		return ret, err
	}
	switch algo {
	case AlgoPlain:
		var discard dbus.Variant
		var sessionPath dbus.ObjectPath
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant("")).Store(&discard, &sessionPath)
		if err != nil {
			return ret, err
		}
		ret = Session{conn.Object(ServiceName, sessionPath), algo, nil}
	case AlgoDH:
		// see http://standards.freedesktop.org/secret-service/ch07s03.html
		var sessionPath dbus.ObjectPath
		var srvReply dbus.Variant
		var srvPub []byte
		symKey := make([]byte, aes.BlockSize)
		grp, err := dhkx.GetGroup(2)
		if err != nil {
			return ret, err
		}
		privKey, err := grp.GeneratePrivateKey(rand.Reader)
		if err != nil {
			return ret, err
		}
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant(privKey.Bytes())).Store(&srvReply, &sessionPath)
		if err != nil {
			return ret, err
		}
		srvPub = srvReply.Value().([]byte)
		sharedKey, err := grp.ComputeKey(dhkx.NewPublicKey(srvPub), privKey)
		if err != nil {
			return ret, err
		}
		_, err = io.ReadFull(hkdf.New(sha256.New, sharedKey.Bytes(), nil, nil), symKey)
		ret = Session{conn.Object(ServiceName, sessionPath), algo, symKey}
	default:
		err = InvalidAlgorithm
	}
	return ret, err
}
예제 #4
0
// This is used to open a seassion for every get/set. Alternative might be to
// defer() the call to close when constructing the ssProvider
func (s *ssProvider) openSession() (*dbus.Object, error) {
	var disregard dbus.Variant
	var sessionPath dbus.ObjectPath
	method := fmt.Sprint(ssServiceIface, "OpenSession")
	err := s.srv.Call(method, 0, "plain", dbus.MakeVariant("")).Store(&disregard, &sessionPath)
	if err != nil {
		return nil, err
	}
	return s.Object(ssServiceName, sessionPath), nil
}
예제 #5
0
func (c Collection) CreateItem(label string, attr map[string]string, s Secret, replace bool) (Item, error) {
	// spec: CreateItem(IN Dict<String,Variant> properties, IN Secret secret, IN Boolean replace, OUT ObjectPath item, OUT ObjectPath prompt);
	i := Item{}
	conn, err := dbus.SessionBus()
	if err != nil {
		return i, err
	}

	prop := make(map[string]dbus.Variant)
	prop[_ItemLabel] = dbus.MakeVariant(label)
	prop[_ItemAttributes] = dbus.MakeVariant(attr)

	call := c.Call(_CollectionCreateItem, 0, prop, s, replace)
	if call.Err != nil {
		return i, call.Err
	}
	var newItem dbus.ObjectPath
	call.Store(&newItem)

	i = Item{conn.Object(ServiceName, newItem)}

	return i, nil
}