├── .gitignore
├── .idea
├── .gitignore
├── .name
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── misc.xml
├── modules.xml
├── pass-fdo-secrets.iml
└── vcs.xml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── TODO.md
├── adaptors
├── collectionadaptor.h
├── itemadaptor.h
├── promptadaptor.h
├── secretsadaptor.h
└── sessionadaptor.h
├── impl
├── Collection.cpp
├── Collection.h
├── CollectionProxy.cpp
├── CollectionProxy.h
├── Item.cpp
├── Item.h
├── ItemProxy.cpp
├── ItemProxy.h
├── SecretService.cpp
├── SecretService.h
├── Session.cpp
├── Session.h
└── sessions
│ ├── Plain.cpp
│ ├── Plain.h
│ └── sessions.h
├── include
├── nanoid
│ ├── crypto_random.h
│ ├── nanoid.h
│ └── settings.h
├── rapidjson
│ ├── allocators.h
│ ├── cursorstreamwrapper.h
│ ├── document.h
│ ├── encodedstream.h
│ ├── encodings.h
│ ├── error
│ │ ├── en.h
│ │ └── error.h
│ ├── filereadstream.h
│ ├── filewritestream.h
│ ├── fwd.h
│ ├── internal
│ │ ├── biginteger.h
│ │ ├── clzll.h
│ │ ├── diyfp.h
│ │ ├── dtoa.h
│ │ ├── ieee754.h
│ │ ├── itoa.h
│ │ ├── meta.h
│ │ ├── pow10.h
│ │ ├── regex.h
│ │ ├── stack.h
│ │ ├── strfunc.h
│ │ ├── strtod.h
│ │ └── swap.h
│ ├── istreamwrapper.h
│ ├── memorybuffer.h
│ ├── memorystream.h
│ ├── msinttypes
│ │ ├── inttypes.h
│ │ └── stdint.h
│ ├── ostreamwrapper.h
│ ├── pointer.h
│ ├── prettywriter.h
│ ├── rapidjson.h
│ ├── reader.h
│ ├── schema.h
│ ├── stream.h
│ ├── stringbuffer.h
│ └── writer.h
└── subprocess.h
├── install
├── arch
│ └── PKGBUILD
├── pass-secrets.service.in
└── si.nullob.pass-secrets.service.in
├── interop
├── DocumentHelper.cpp
├── DocumentHelper.h
├── PassCollection.cpp
├── PassCollection.h
├── PassItem.cpp
├── PassItem.h
├── PassStore.cpp
└── PassStore.h
├── introspection
├── collection.xml
├── item.xml
├── prompt.xml
├── secrets.xml
└── session.xml
├── main.cpp
└── nanoid_cpp
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── src
└── nanoid
│ ├── crypto_random.cpp
│ └── nanoid.cpp
└── tests
└── unit_tests.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 |
4 | # User-specific stuff
5 | .idea/**/workspace.xml
6 | .idea/**/tasks.xml
7 | .idea/**/usage.statistics.xml
8 | .idea/**/dictionaries
9 | .idea/**/shelf
10 |
11 | build/
12 |
13 | # Generated files
14 | .idea/**/contentModel.xml
15 |
16 | # Sensitive or high-churn files
17 | .idea/**/dataSources/
18 | .idea/**/dataSources.ids
19 | .idea/**/dataSources.local.xml
20 | .idea/**/sqlDataSources.xml
21 | .idea/**/dynamic.xml
22 | .idea/**/uiDesigner.xml
23 | .idea/**/dbnavigator.xml
24 |
25 | # Gradle
26 | .idea/**/gradle.xml
27 | .idea/**/libraries
28 |
29 | # Gradle and Maven with auto-import
30 | # When using Gradle or Maven with auto-import, you should exclude module files,
31 | # since they will be recreated, and may cause churn. Uncomment if using
32 | # auto-import.
33 | # .idea/artifacts
34 | # .idea/compiler.xml
35 | # .idea/jarRepositories.xml
36 | # .idea/modules.xml
37 | # .idea/*.iml
38 | # .idea/modules
39 | # *.iml
40 | # *.ipr
41 |
42 | # CMake
43 | cmake-build-*/
44 |
45 | # Mongo Explorer plugin
46 | .idea/**/mongoSettings.xml
47 |
48 | # File-based project format
49 | *.iws
50 |
51 | # IntelliJ
52 | out/
53 |
54 | # mpeltonen/sbt-idea plugin
55 | .idea_modules/
56 |
57 | # JIRA plugin
58 | atlassian-ide-plugin.xml
59 |
60 | # Cursive Clojure plugin
61 | .idea/replstate.xml
62 |
63 | # Crashlytics plugin (for Android Studio and IntelliJ)
64 | com_crashlytics_export_strings.xml
65 | crashlytics.properties
66 | crashlytics-build.properties
67 | fabric.properties
68 |
69 | # Editor-based Rest Client
70 | .idea/httpRequests
71 |
72 | # Android studio 3.1+ serialized cache file
73 | .idea/caches/build_file_checksums.ser
74 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | pass-secrets
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/pass-fdo-secrets.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 |
3 | if (NOT DEFINED CMAKE_INSTALL_PREFIX)
4 | set (CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Install to /usr/local" FORCE)
5 | endif()
6 |
7 | configure_file(install/si.nullob.pass-secrets.service.in si.nullob.pass-secrets.service)
8 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/si.nullob.pass-secrets.service DESTINATION share/dbus-1/services)
9 |
10 | configure_file(install/pass-secrets.service.in pass-secrets.service)
11 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pass-secrets.service DESTINATION lib/systemd/user)
12 |
13 | project(pass-secrets)
14 |
15 | set(CMAKE_CXX_STANDARD 17)
16 |
17 | include_directories("include")
18 | add_subdirectory("nanoid_cpp")
19 |
20 | find_package(sdbus-c++ REQUIRED)
21 |
22 | add_executable(pass-secrets main.cpp impl/SecretService.cpp impl/SecretService.h impl/Session.cpp impl/Session.h interop/PassStore.cpp interop/PassStore.h interop/PassCollection.cpp interop/PassCollection.h interop/PassItem.cpp interop/PassItem.h interop/DocumentHelper.h interop/DocumentHelper.cpp impl/Collection.cpp impl/Collection.h impl/Item.cpp impl/Item.h impl/CollectionProxy.cpp impl/CollectionProxy.h impl/ItemProxy.cpp impl/ItemProxy.h impl/sessions/Plain.cpp impl/sessions/Plain.h impl/sessions/sessions.h)
23 | target_link_libraries(pass-secrets PRIVATE SDBusCpp::sdbus-c++ nanoid)
24 | target_compile_definitions(pass-secrets PRIVATE RAPIDJSON_HAS_STDSTRING)
25 | install(TARGETS pass-secrets RUNTIME)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pass-secrets
2 | CLI Application that provides the Freedesktop Secret Service using Pass as its backend!
3 |
4 | ## Status
5 | Currently working to store secrets with protonmail-bridge. I have not done tests with other applications; if it doesn't work, please open an issue!
6 |
7 | ## How to build
8 | pass-secrets requires pass and sdbus-c++ to be installed on your machine. Rapidjson and nanoid are included in the repo.
9 |
10 | ```
11 | cd pass-secrets
12 | mkdir build
13 | cd build
14 | cmake ..
15 | make
16 | ```
17 |
18 | You can then install with `sudo make install` and uninstall with `sudo xargs rm < install_manifest.txt`. This will by default install a systemd user service that can be dbus-activated when enabled.
19 |
20 | ```
21 | sudo make install
22 | systemctl --user enable pass-secrets
23 | ```
24 |
25 | Alternatively, you can run it in the background in your bashrc/xinitrc.
26 | ```
27 | ...
28 | /usr/local/bin/pass-secrets &
29 | ...
30 | ```
31 |
32 | If you're running pass-secrets on a BSD, or possibly a non-systemd Linux system, you'll need to start a DBus session bus before starting pass-secrets. For instance, your ~/.bash_profile could contain:
33 |
34 | ```
35 | if ! pgrep -qf -U ${USER:-$(id -u)} dbus.\*--session; then
36 | dbus-daemon --session --fork --address=unix:runtime=yes 2>/dev/null
37 | export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
38 | fi
39 | ```
40 |
41 | See [this issue](https://github.com/nullobsi/pass-secrets/issues/11) for more details.
42 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Ideas
2 | - use rofi/dmenu to provide prompts for actions
3 |
4 | # TODO
5 | - track sessions and remove when owner disconnects
6 |
--------------------------------------------------------------------------------
/adaptors/collectionadaptor.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
4 | */
5 |
6 | #ifndef __sdbuscpp__collectionadapter_h__adaptor__H__
7 | #define __sdbuscpp__collectionadapter_h__adaptor__H__
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace org {
14 | namespace freedesktop {
15 | namespace Secret {
16 |
17 | class Collection_adaptor
18 | {
19 | public:
20 | static constexpr const char* INTERFACE_NAME = "org.freedesktop.Secret.Collection";
21 |
22 | protected:
23 | Collection_adaptor(sdbus::IObject& object)
24 | : object_(object)
25 | {
26 | object_.registerMethod("Delete").onInterface(INTERFACE_NAME).withOutputParamNames("prompt").implementedAs([this](){ return this->Delete(); });
27 | object_.registerMethod("SearchItems").onInterface(INTERFACE_NAME).withInputParamNames("attributes").withOutputParamNames("results").implementedAs([this](const std::map& attributes){ return this->SearchItems(attributes); });
28 | object_.registerMethod("CreateItem").onInterface(INTERFACE_NAME).withInputParamNames("properties", "secret", "replace").withOutputParamNames("item", "prompt").implementedAs([this](const std::map& properties, const sdbus::Struct, std::vector, std::string>& secret, const bool& replace){ return this->CreateItem(properties, secret, replace); });
29 | object_.registerSignal("ItemCreated").onInterface(INTERFACE_NAME).withParameters("item");
30 | object_.registerSignal("ItemDeleted").onInterface(INTERFACE_NAME).withParameters("item");
31 | object_.registerSignal("ItemChanged").onInterface(INTERFACE_NAME).withParameters("item");
32 | object_.registerProperty("Items").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Items(); });
33 | object_.registerProperty("Label").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Label(); }).withSetter([this](const std::string& value){ this->Label(value); });
34 | object_.registerProperty("Locked").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Locked(); });
35 | object_.registerProperty("Created").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Created(); });
36 | object_.registerProperty("Modified").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Modified(); });
37 | }
38 |
39 | ~Collection_adaptor() = default;
40 |
41 | public:
42 | void emitItemCreated(const sdbus::ObjectPath& item)
43 | {
44 | object_.emitSignal("ItemCreated").onInterface(INTERFACE_NAME).withArguments(item);
45 | }
46 |
47 | void emitItemDeleted(const sdbus::ObjectPath& item)
48 | {
49 | object_.emitSignal("ItemDeleted").onInterface(INTERFACE_NAME).withArguments(item);
50 | }
51 |
52 | void emitItemChanged(const sdbus::ObjectPath& item)
53 | {
54 | object_.emitSignal("ItemChanged").onInterface(INTERFACE_NAME).withArguments(item);
55 | }
56 |
57 | private:
58 | virtual sdbus::ObjectPath Delete() = 0;
59 | virtual std::vector SearchItems(const std::map& attributes) = 0;
60 | virtual std::tuple CreateItem(const std::map& properties, const sdbus::Struct, std::vector, std::string>& secret, const bool& replace) = 0;
61 |
62 | private:
63 | virtual std::vector Items() = 0;
64 | virtual std::string Label() = 0;
65 | virtual void Label(const std::string& value) = 0;
66 | virtual bool Locked() = 0;
67 | virtual uint64_t Created() = 0;
68 | virtual uint64_t Modified() = 0;
69 |
70 | private:
71 | sdbus::IObject& object_;
72 | };
73 |
74 | }}} // namespaces
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/adaptors/itemadaptor.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
4 | */
5 |
6 | #ifndef __sdbuscpp__itemadapter_h__adaptor__H__
7 | #define __sdbuscpp__itemadapter_h__adaptor__H__
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace org {
14 | namespace freedesktop {
15 | namespace Secret {
16 |
17 | class Item_adaptor
18 | {
19 | public:
20 | static constexpr const char* INTERFACE_NAME = "org.freedesktop.Secret.Item";
21 |
22 | protected:
23 | Item_adaptor(sdbus::IObject& object)
24 | : object_(object)
25 | {
26 | object_.registerMethod("Delete").onInterface(INTERFACE_NAME).withOutputParamNames("Prompt").implementedAs([this](){ return this->Delete(); });
27 | object_.registerMethod("GetSecret").onInterface(INTERFACE_NAME).withInputParamNames("session").withOutputParamNames("secret").implementedAs([this](const sdbus::ObjectPath& session){ return this->GetSecret(session); });
28 | object_.registerMethod("SetSecret").onInterface(INTERFACE_NAME).withInputParamNames("secret").implementedAs([this](const sdbus::Struct, std::vector, std::string>& secret){ return this->SetSecret(secret); });
29 | object_.registerProperty("Locked").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Locked(); });
30 | object_.registerProperty("Attributes").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Attributes(); }).withSetter([this](const std::map& value){ this->Attributes(value); });
31 | object_.registerProperty("Label").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Label(); }).withSetter([this](const std::string& value){ this->Label(value); });
32 | object_.registerProperty("Type").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Type(); }).withSetter([this](const std::string& value){ this->Type(value); });
33 | object_.registerProperty("Created").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Created(); });
34 | object_.registerProperty("Modified").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Modified(); });
35 | }
36 |
37 | ~Item_adaptor() = default;
38 |
39 | private:
40 | virtual sdbus::ObjectPath Delete() = 0;
41 | virtual sdbus::Struct, std::vector, std::string> GetSecret(const sdbus::ObjectPath& session) = 0;
42 | virtual void SetSecret(const sdbus::Struct, std::vector, std::string>& secret) = 0;
43 |
44 | private:
45 | virtual bool Locked() = 0;
46 | virtual std::map Attributes() = 0;
47 | virtual void Attributes(const std::map& value) = 0;
48 | virtual std::string Label() = 0;
49 | virtual void Label(const std::string& value) = 0;
50 | virtual std::string Type() = 0;
51 | virtual void Type(const std::string& value) = 0;
52 | virtual uint64_t Created() = 0;
53 | virtual uint64_t Modified() = 0;
54 |
55 | private:
56 | sdbus::IObject& object_;
57 | };
58 |
59 | }}} // namespaces
60 |
61 | #endif
62 |
--------------------------------------------------------------------------------
/adaptors/promptadaptor.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
4 | */
5 |
6 | #ifndef __sdbuscpp__promptadapter_h__adaptor__H__
7 | #define __sdbuscpp__promptadapter_h__adaptor__H__
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace org {
14 | namespace freedesktop {
15 | namespace Secret {
16 |
17 | class Prompt_adaptor
18 | {
19 | public:
20 | static constexpr const char* INTERFACE_NAME = "org.freedesktop.Secret.Prompt";
21 |
22 | protected:
23 | Prompt_adaptor(sdbus::IObject& object)
24 | : object_(object)
25 | {
26 | object_.registerMethod("Prompt").onInterface(INTERFACE_NAME).withInputParamNames("window-id").implementedAs([this](const std::string& window-id){ return this->Prompt(window-id); });
27 | object_.registerMethod("Dismiss").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Dismiss(); });
28 | object_.registerSignal("Completed").onInterface(INTERFACE_NAME).withParameters("dismissed", "result");
29 | }
30 |
31 | ~Prompt_adaptor() = default;
32 |
33 | public:
34 | void emitCompleted(const bool& dismissed, const sdbus::Variant& result)
35 | {
36 | object_.emitSignal("Completed").onInterface(INTERFACE_NAME).withArguments(dismissed, result);
37 | }
38 |
39 | private:
40 | virtual void Prompt(const std::string& window-id) = 0;
41 | virtual void Dismiss() = 0;
42 |
43 | private:
44 | sdbus::IObject& object_;
45 | };
46 |
47 | }}} // namespaces
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/adaptors/secretsadaptor.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
4 | */
5 |
6 | #ifndef __sdbuscpp__secretsadapter_h__adaptor__H__
7 | #define __sdbuscpp__secretsadapter_h__adaptor__H__
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace org {
14 | namespace freedesktop {
15 | namespace Secret {
16 |
17 | class Service_adaptor
18 | {
19 | public:
20 | static constexpr const char* INTERFACE_NAME = "org.freedesktop.Secret.Service";
21 |
22 | protected:
23 | Service_adaptor(sdbus::IObject& object)
24 | : object_(object)
25 | {
26 | object_.registerMethod("OpenSession").onInterface(INTERFACE_NAME).withInputParamNames("algorithm", "input").withOutputParamNames("output", "result").implementedAs([this](const std::string& algorithm, const sdbus::Variant& input){ return this->OpenSession(algorithm, input); });
27 | object_.registerMethod("CreateCollection").onInterface(INTERFACE_NAME).withInputParamNames("properties", "alias").withOutputParamNames("collection", "prompt").implementedAs([this](const std::map& properties, const std::string& alias){ return this->CreateCollection(properties, alias); });
28 | object_.registerMethod("SearchItems").onInterface(INTERFACE_NAME).withInputParamNames("attributes").withOutputParamNames("unlocked", "locked").implementedAs([this](const std::map& attributes){ return this->SearchItems(attributes); });
29 | object_.registerMethod("Unlock").onInterface(INTERFACE_NAME).withInputParamNames("objects").withOutputParamNames("unlocked", "prompt").implementedAs([this](const std::vector& objects){ return this->Unlock(objects); });
30 | object_.registerMethod("Lock").onInterface(INTERFACE_NAME).withInputParamNames("objects").withOutputParamNames("locked", "Prompt").implementedAs([this](const std::vector& objects){ return this->Lock(objects); });
31 | object_.registerMethod("LockService").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->LockService(); });
32 | object_.registerMethod("ChangeLock").onInterface(INTERFACE_NAME).withInputParamNames("collection").withOutputParamNames("prompt").implementedAs([this](const sdbus::ObjectPath& collection){ return this->ChangeLock(collection); });
33 | object_.registerMethod("GetSecrets").onInterface(INTERFACE_NAME).withInputParamNames("items", "session").withOutputParamNames("secrets").implementedAs([this](const std::vector& items, const sdbus::ObjectPath& session){ return this->GetSecrets(items, session); });
34 | object_.registerMethod("ReadAlias").onInterface(INTERFACE_NAME).withInputParamNames("name").withOutputParamNames("collection").implementedAs([this](const std::string& name){ return this->ReadAlias(name); });
35 | object_.registerMethod("SetAlias").onInterface(INTERFACE_NAME).withInputParamNames("name", "collection").implementedAs([this](const std::string& name, const sdbus::ObjectPath& collection){ return this->SetAlias(name, collection); });
36 | object_.registerSignal("CollectionCreated").onInterface(INTERFACE_NAME).withParameters("collection");
37 | object_.registerSignal("CollectionDeleted").onInterface(INTERFACE_NAME).withParameters("collection");
38 | object_.registerSignal("CollectionChanged").onInterface(INTERFACE_NAME).withParameters("collection");
39 | object_.registerProperty("Collections").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Collections(); });
40 | }
41 |
42 | ~Service_adaptor() = default;
43 |
44 | public:
45 | void emitCollectionCreated(const sdbus::ObjectPath& collection)
46 | {
47 | object_.emitSignal("CollectionCreated").onInterface(INTERFACE_NAME).withArguments(collection);
48 | }
49 |
50 | void emitCollectionDeleted(const sdbus::ObjectPath& collection)
51 | {
52 | object_.emitSignal("CollectionDeleted").onInterface(INTERFACE_NAME).withArguments(collection);
53 | }
54 |
55 | void emitCollectionChanged(const sdbus::ObjectPath& collection)
56 | {
57 | object_.emitSignal("CollectionChanged").onInterface(INTERFACE_NAME).withArguments(collection);
58 | }
59 |
60 | private:
61 | virtual std::tuple OpenSession(const std::string& algorithm, const sdbus::Variant& input) = 0;
62 | virtual std::tuple CreateCollection(const std::map& properties, const std::string& alias) = 0;
63 | virtual std::tuple, std::vector> SearchItems(const std::map& attributes) = 0;
64 | virtual std::tuple, sdbus::ObjectPath> Unlock(const std::vector& objects) = 0;
65 | virtual std::tuple, sdbus::ObjectPath> Lock(const std::vector& objects) = 0;
66 | virtual void LockService() = 0;
67 | virtual sdbus::ObjectPath ChangeLock(const sdbus::ObjectPath& collection) = 0;
68 | virtual std::map, std::vector, std::string>> GetSecrets(const std::vector& items, const sdbus::ObjectPath& session) = 0;
69 | virtual sdbus::ObjectPath ReadAlias(const std::string& name) = 0;
70 | virtual void SetAlias(const std::string& name, const sdbus::ObjectPath& collection) = 0;
71 |
72 | private:
73 | virtual std::vector Collections() = 0;
74 |
75 | private:
76 | sdbus::IObject& object_;
77 | };
78 |
79 | }}} // namespaces
80 |
81 | #endif
82 |
--------------------------------------------------------------------------------
/adaptors/sessionadaptor.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
4 | */
5 |
6 | #ifndef __sdbuscpp__sessionadapter_h__adaptor__H__
7 | #define __sdbuscpp__sessionadapter_h__adaptor__H__
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace org {
14 | namespace freedesktop {
15 | namespace Secret {
16 |
17 | class Session_adaptor
18 | {
19 | public:
20 | static constexpr const char* INTERFACE_NAME = "org.freedesktop.Secret.Session";
21 |
22 | protected:
23 | Session_adaptor(sdbus::IObject& object)
24 | : object_(object)
25 | {
26 |
27 | }
28 |
29 | ~Session_adaptor() = default;
30 |
31 |
32 | private:
33 | sdbus::IObject& object_;
34 | };
35 |
36 | }}} // namespaces
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/impl/Collection.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #include "Collection.h"
6 | #include "SecretService.h"
7 | #include "Item.h"
8 | #include "CollectionProxy.h"
9 | #include
10 | #include
11 |
12 |
13 | Collection::Collection(std::shared_ptr backend_,
14 | sdbus::IConnection &conn,
15 | std::string path,
16 | std::weak_ptr parent_)
17 | : sdbus::AdaptorInterfaces(conn, std::move(path)),
18 | backend(std::move(backend_)), parent(std::move(parent_)) {
19 | registerAdaptor();
20 | }
21 |
22 | Collection::~Collection() {
23 | unregisterAdaptor();
24 | }
25 |
26 | sdbus::ObjectPath
27 | Collection::Delete() {
28 | backend->Delete();
29 | parent.lock()->DiscardCollection(this->backend->getId());
30 | return sdbus::ObjectPath("/");
31 | }
32 |
33 | std::vector
34 | Collection::SearchItems(const std::map &attributes) {
35 | auto it = backend->searchItems(attributes);
36 | std::vector r;
37 | r.reserve(it.size());
38 | for (const auto &id : it) {
39 | r.push_back(items[id]->getPath());
40 | }
41 | return r;
42 | }
43 |
44 | std::tuple
45 | Collection::CreateItem(const std::map &properties,
46 | const sdbus::Struct, std::vector, std::string> &secret,
47 | const bool &replace) {
48 | auto nAttrib = properties.count("org.freedesktop.Secret.Item.Attributes") && properties.at("org.freedesktop.Secret.Item.Attributes").containsValueOfType>() ? properties.at("org.freedesktop.Secret.Item.Attributes").get>() : std::map();
49 | auto nLabel = properties.count("org.freedesktop.Secret.Item.Label") && properties.at("org.freedesktop.Secret.Item.Label").containsValueOfType() ? properties.at("org.freedesktop.Secret.Item.Label").get() : "Secret";
50 | auto nType = properties.count("org.freedesktop.Secret.Item.Type") && properties.at("org.freedesktop.Secret.Item.Type").containsValueOfType() ? properties.at("org.freedesktop.Secret.Item.Type").get() : (nAttrib.count("xdg:schema") ? nAttrib["xdg:schema"] : "org.freedesktop.Secret.Generic");
51 | auto existing = InternalSearchItems(nAttrib);
52 | if (!existing.empty() && !replace) {
53 | // TODO: this error is not part of spec
54 | throw sdbus::Error("org.freedesktop.Secret.Error.ObjectExists", "Such an object already exists in the store");
55 | }
56 | auto data = secret.get<2>();
57 | auto nData = (uint8_t *)malloc(data.size() * sizeof(uint8_t));
58 | memcpy(nData, data.data(), data.size()*sizeof(uint8_t));
59 |
60 | if (replace && !existing.empty()) {
61 | auto item = existing[0]->getBackend();
62 | item->setAttrib(std::move(nAttrib));
63 | item->setLabel(std::move(nLabel));
64 | item->setType(std::move(nType));
65 | item->updateMetadata();
66 | item->setSecret(nData, data.size());
67 | ItemCreated(existing[0]->getPath());
68 | return std::tuple(existing[0]->getPath(), "/");
69 | }
70 | auto item = this->backend->CreateItem(nData, data.size(), move(nAttrib), move(nLabel), move(nType));
71 | auto nItem = std::make_shared- (item, this->getObject().getConnection(), this->getObjectPath() + "/" + item->getId(), weak_from_this());
72 | updateItem(nItem);
73 | items.insert({item->getId(), nItem});
74 | ItemCreated(nItem->getPath());
75 | return std::tuple(nItem->getPath(), "/");
76 | }
77 |
78 | std::vector
79 | Collection::Items() {
80 | std::vector r;
81 | auto it = backend->getItems();
82 | r.reserve(it.size());
83 | for (const auto &item : it) {
84 | r.push_back(items[item->getId()]->getPath());
85 | }
86 | return r;
87 | }
88 |
89 | std::string
90 | Collection::Label() {
91 | return backend->getLabel();
92 | }
93 |
94 | void
95 | Collection::Label(const std::string &value) {
96 | backend->setLabel(value);
97 | backend->updateMetadata();
98 | }
99 |
100 | bool
101 | Collection::Locked() {
102 | return std::any_of(items.cbegin(), items.cend(),
103 | [](const std::pair> &entry) -> bool {
104 | return entry.second->Locked();
105 | });
106 | }
107 |
108 | uint64_t
109 | Collection::Created() {
110 | return backend->getCreated();
111 | }
112 |
113 | uint64_t
114 | Collection::Modified() {
115 | return 0;
116 | }
117 |
118 | std::shared_ptr
119 | Collection::GetBacking() {
120 | return backend;
121 | }
122 |
123 | std::vector>
124 | Collection::InternalSearchItems(const std::map &attributes) {
125 | auto it = backend->searchItems(attributes);
126 | std::vector> r;
127 | r.reserve(it.size());
128 | for (const auto &id : it) {
129 | r.push_back(items[id]);
130 | }
131 | return r;
132 | }
133 |
134 | std::map> &
135 | Collection::getItemMap() {
136 | return items;
137 | }
138 |
139 | void
140 | Collection::DiscardObjects() {
141 | while (!discarded.empty()) {
142 | discarded.pop_back();
143 | }
144 | }
145 |
146 | void
147 | Collection::InitItems() {
148 | for (const auto &item : backend->getItems()) {
149 | items.insert({
150 | item->getId(), std::make_unique
- (item, this->getObject().getConnection(),
151 | this->getObjectPath() + "/" + item->getId(),
152 | weak_from_this())
153 | });
154 | }
155 | updateAlias();
156 | }
157 |
158 |
159 |
160 | void
161 | Collection::DiscardItem(std::string id) {
162 | auto ptr = items.extract(id).mapped();
163 | ItemDeleted(ptr->getPath());
164 | backend->RemoveItem(ptr->getBackend()->getId());
165 | discarded.push_back(move(ptr));
166 | }
167 |
168 | void
169 | Collection::updateAlias() {
170 | std::string path = "";
171 | if (backend->getAlias().empty()) {
172 | if (proxy) {
173 | proxy.reset();
174 | }
175 | } else {
176 | path = "/org/freedesktop/secrets/aliases/" + backend->getAlias();
177 | proxy = std::make_unique(this->getObject().getConnection(), path, weak_from_this());
178 | }
179 | for (const auto &item : items) {
180 | item.second->updateProxy(path);
181 | }
182 | }
183 |
184 | void
185 | Collection::updateItem(std::shared_ptr
- item) {
186 | if (!backend->getAlias().empty()) {
187 | auto path = "/org/freedesktop/secrets/aliases/" + backend->getAlias();
188 | item->updateProxy(path);
189 | } else {
190 | item->updateProxy("");
191 | }
192 | }
193 |
194 | // TODO: do proxies have to use proxied item path?
195 | void
196 | Collection::ItemCreated(const sdbus::ObjectPath &item) {
197 | emitItemCreated(item);
198 | emitPropertiesChangedSignal("org.freedesktop.Secret.Collection", {"Items"});
199 | if (proxy) proxy->emitItemCreated(item);
200 | }
201 |
202 | void
203 | Collection::ItemDeleted(const sdbus::ObjectPath &item) {
204 | emitItemDeleted(item);
205 | emitPropertiesChangedSignal("org.freedesktop.Secret.Collection", {"Items"});
206 | if (proxy) proxy->emitItemDeleted(item);
207 | }
208 |
209 | void
210 | Collection::ItemChanged(const sdbus::ObjectPath &item) {
211 | emitItemChanged(item);
212 | emitPropertiesChangedSignal("org.freedesktop.Secret.Collection", {"Items"});
213 | if (proxy) proxy->emitItemChanged(item);
214 | }
215 |
216 | std::shared_ptr
217 | Collection::GetService() {
218 | return parent.lock();
219 | }
220 |
--------------------------------------------------------------------------------
/impl/Collection.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #ifndef PASS_FDO_SECRETS_COLLECTION_H
6 | #define PASS_FDO_SECRETS_COLLECTION_H
7 |
8 | #include "../interop/PassCollection.h"
9 | #include
10 | #include
11 | #include
12 | #include "../adaptors/collectionadaptor.h"
13 |
14 | class SecretService;
15 | class CollectionProxy;
16 | class Item;
17 |
18 | class Collection
19 | : public sdbus::AdaptorInterfaces,
20 | public std::enable_shared_from_this {
21 | public:
22 | Collection(std::shared_ptr backend_,
23 | sdbus::IConnection &conn,
24 | std::string path,
25 | std::weak_ptr parent_);
26 |
27 | ~Collection();
28 |
29 | void
30 | InitItems();
31 |
32 | void
33 | DiscardItem(std::string id);
34 |
35 | std::shared_ptr
36 | GetBacking();
37 |
38 | void
39 | DiscardObjects();
40 |
41 | std::vector>
42 | InternalSearchItems(const std::map &attributes);
43 |
44 | std::vector
45 | SearchItems(const std::map &attributes) override;
46 |
47 | sdbus::ObjectPath
48 | Delete() override;
49 |
50 | std::tuple
51 | CreateItem(const std::map &properties,
52 | const sdbus::Struct, std::vector, std::string> &secret,
53 | const bool &replace) override;
54 |
55 | std::vector
56 | Items() override;
57 |
58 | std::string
59 | Label() override;
60 |
61 | void
62 | Label(const std::string &value) override;
63 |
64 | bool
65 | Locked() override;
66 |
67 | uint64_t
68 | Created() override;
69 |
70 | uint64_t
71 | Modified() override;
72 |
73 | std::map> &
74 | getItemMap();
75 |
76 | void
77 | updateAlias();
78 |
79 | void
80 | updateItem(std::shared_ptr
- item);
81 |
82 | void
83 | ItemCreated(const sdbus::ObjectPath& item);
84 |
85 | void
86 | ItemDeleted(const sdbus::ObjectPath& item);
87 |
88 | void
89 | ItemChanged(const sdbus::ObjectPath& item);
90 |
91 | std::shared_ptr
92 | GetService();
93 |
94 |
95 | private:
96 | std::shared_ptr backend;
97 | std::weak_ptr parent;
98 | std::map> items;
99 | std::vector> discarded;
100 |
101 | std::unique_ptr proxy;
102 | };
103 |
104 |
105 | #endif //PASS_FDO_SECRETS_COLLECTION_H
106 |
--------------------------------------------------------------------------------
/impl/CollectionProxy.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/23.
3 | //
4 |
5 | #include "CollectionProxy.h"
6 | #include "Collection.h"
7 |
8 | CollectionProxy::CollectionProxy(sdbus::IConnection &conn,
9 | std::string path,
10 | std::weak_ptr parent_) : sdbus::AdaptorInterfaces(conn, std::move(path)), parent(std::move(parent_)) {
11 | registerAdaptor();
12 | }
13 |
14 | CollectionProxy::~CollectionProxy() {
15 | unregisterAdaptor();
16 | }
17 |
18 | sdbus::ObjectPath
19 | CollectionProxy::Delete() {
20 | return parent.lock()->Delete();
21 | }
22 |
23 | std::vector
24 | CollectionProxy::SearchItems(const std::map &attributes) {
25 | return parent.lock()->SearchItems(attributes);
26 | }
27 |
28 | std::tuple
29 | CollectionProxy::CreateItem(const std::map &properties,
30 | const sdbus::Struct, std::vector, std::string> &secret,
31 | const bool &replace) {
32 | return parent.lock()->CreateItem(properties, secret, replace);
33 | }
34 |
35 | std::vector
36 | CollectionProxy::Items() {
37 | return parent.lock()->Items();
38 | }
39 |
40 | std::string
41 | CollectionProxy::Label() {
42 | return parent.lock()->Label();
43 | }
44 |
45 | void
46 | CollectionProxy::Label(const std::string &value) {
47 | parent.lock()->Label(value);
48 | }
49 |
50 | bool
51 | CollectionProxy::Locked() {
52 | return parent.lock()->Locked();
53 | }
54 |
55 | uint64_t
56 | CollectionProxy::Created() {
57 | return parent.lock()->Created();
58 | }
59 |
60 | uint64_t
61 | CollectionProxy::Modified() {
62 | return parent.lock()->Modified();
63 | }
64 |
--------------------------------------------------------------------------------
/impl/CollectionProxy.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/23.
3 | //
4 |
5 | #ifndef PASS_SECRETS_COLLECTIONPROXY_H
6 | #define PASS_SECRETS_COLLECTIONPROXY_H
7 | #include "sdbus-c++/sdbus-c++.h"
8 | #include "../adaptors/collectionadaptor.h"
9 |
10 | class Collection;
11 |
12 | class CollectionProxy : public sdbus::AdaptorInterfaces{
13 | public:
14 | CollectionProxy(sdbus::IConnection &conn,
15 | std::string path, std::weak_ptr parent_);
16 |
17 | ~CollectionProxy();
18 |
19 | sdbus::ObjectPath Delete() override;
20 | std::vector SearchItems(const std::map& attributes) override;
21 | std::tuple CreateItem(const std::map& properties, const sdbus::Struct, std::vector, std::string>& secret, const bool& replace) override;
22 | std::vector Items() override;
23 | std::string Label() override;
24 | void Label(const std::string& value) override;
25 | bool Locked() override;
26 | uint64_t Created() override;
27 | uint64_t Modified() override;
28 |
29 | private:
30 | std::weak_ptr parent;
31 | };
32 |
33 |
34 | #endif //PASS_SECRETS_COLLECTIONPROXY_H
35 |
--------------------------------------------------------------------------------
/impl/Item.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/22.
3 | //
4 |
5 | // TODO: Proxy item
6 | #include "Item.h"
7 |
8 | #include
9 | #include
10 | #include "Collection.h"
11 | #include "ItemProxy.h"
12 | #include "SecretService.h"
13 |
14 | bool
15 | Item::Locked() {
16 | return !backend->isUnlocked();
17 | }
18 |
19 | std::map
20 | Item::Attributes() {
21 | return backend->getAttrib();
22 | }
23 |
24 | void
25 | Item::Attributes(const std::map &value) {
26 | backend->setAttrib(value);
27 | backend->updateMetadata();
28 | emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Attributes", "Modified"});
29 | parent.lock()->ItemChanged(getPath());
30 | }
31 |
32 | std::string
33 | Item::Label() {
34 | return backend->getLabel();
35 | }
36 |
37 | void
38 | Item::Label(const std::string &value) {
39 | backend->setLabel(value);
40 | backend->updateMetadata();
41 | emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Label", "Modified"});
42 | parent.lock()->ItemChanged(getPath());
43 | }
44 |
45 | std::string
46 | Item::Type() {
47 | return backend->getType();
48 | }
49 |
50 | void
51 | Item::Type(const std::string &value) {
52 | backend->setType(value);
53 | backend->updateMetadata();
54 | emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Type", "Modified"});
55 | parent.lock()->ItemChanged(getPath());
56 | }
57 |
58 | uint64_t
59 | Item::Created() {
60 | return backend->getCreated();
61 | }
62 |
63 | uint64_t
64 | Item::Modified() {
65 | return backend->getModified();
66 | }
67 |
68 | sdbus::ObjectPath
69 | Item::Delete() {
70 | backend->Delete();
71 | parent.lock()->DiscardItem(this->backend->getId());
72 | return sdbus::ObjectPath("/");
73 | }
74 |
75 | Item::Item(std::shared_ptr backend_,
76 | sdbus::IConnection &conn,
77 | std::string path,
78 | std::weak_ptr parent_) : backend(std::move(backend_)),
79 | sdbus::AdaptorInterfaces(
80 | conn, std::move(path)), parent(std::move(parent_)) {
81 | registerAdaptor();
82 | }
83 |
84 | Item::~Item() {
85 | unregisterAdaptor();
86 | }
87 |
88 | sdbus::Struct, std::vector, std::string>
89 | Item::GetSecret(const sdbus::ObjectPath &session) {
90 | if (!backend->isUnlocked()) {
91 | throw sdbus::Error("org.freedesktop.Secret.Error.IsLocked",
92 | "The object must be unlocked before this action can be carried out.");
93 | }
94 | auto encrypted = parent.lock()->GetService()
95 | ->EncryptSecret(session, backend->getSecret(), backend->getSecretLength());
96 |
97 |
98 | // TODO: how to check item type?
99 | return std::tuple(session, std::move(encrypted.first), std::move(encrypted.second), "text/plain");
100 | }
101 |
102 | sdbus::ObjectPath
103 | Item::getPath() {
104 | return sdbus::ObjectPath(getObject().getObjectPath());
105 | }
106 |
107 | void
108 | Item::SetSecret(const sdbus::Struct, std::vector, std::string> &secret) {
109 | auto data = secret.get<2>();
110 | auto nData = (uint8_t *)malloc(sizeof(uint8_t) * data.size());
111 | memcpy(nData, data.data(), sizeof(uint8_t) * data.size());
112 | backend->setSecret(nData, data.size());
113 | emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Locked", "Modified"});
114 |
115 | parent.lock()->ItemChanged(getPath());
116 | }
117 |
118 | std::shared_ptr
119 | Item::getBackend() {
120 | return backend;
121 | }
122 |
123 | void
124 | Item::updateProxy(std::string proxiedCollection) {
125 | if (proxiedCollection.empty()) {
126 | if (proxy) {
127 | proxy.reset();
128 | }
129 | } else {
130 | proxy = std::make_unique(this->getObject().getConnection(),
131 | proxiedCollection + "/" + backend->getId(), weak_from_this());
132 | }
133 | }
134 |
135 | std::string
136 | Item::getCollectionId() {
137 | return parent.lock()->GetBacking()->getId();
138 | }
139 |
--------------------------------------------------------------------------------
/impl/Item.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/22.
3 | //
4 |
5 | #ifndef PASS_FDO_SECRETS_ITEM_H
6 | #define PASS_FDO_SECRETS_ITEM_H
7 |
8 | #include "../interop/PassItem.h"
9 | #include "sdbus-c++/sdbus-c++.h"
10 | #include "sdbus-c++/StandardInterfaces.h"
11 | #include "../adaptors/itemadaptor.h"
12 |
13 | class Collection;
14 | class ItemProxy;
15 |
16 | class Item : public sdbus::AdaptorInterfaces , public std::enable_shared_from_this
- {
17 | public:
18 | Item(std::shared_ptr backend_,
19 | sdbus::IConnection &conn,
20 | std::string path,
21 | std::weak_ptr parent_);
22 |
23 | ~Item();
24 |
25 | sdbus::ObjectPath
26 | getPath();
27 |
28 | sdbus::ObjectPath
29 | Delete() override;
30 |
31 | sdbus::Struct, std::vector, std::string>
32 | GetSecret(const sdbus::ObjectPath &session) override;
33 |
34 | void
35 | SetSecret(const sdbus::Struct, std::vector, std::string> &secret) override;
36 |
37 | bool
38 | Locked() override;
39 |
40 | std::map
41 | Attributes() override;
42 |
43 | void
44 | Attributes(const std::map &value) override;
45 |
46 | std::string
47 | Label() override;
48 |
49 | void
50 | Label(const std::string &value) override;
51 |
52 | std::string
53 | Type() override;
54 |
55 | void
56 | Type(const std::string &value) override;
57 |
58 | uint64_t
59 | Created() override;
60 |
61 | uint64_t
62 | Modified() override;
63 |
64 | std::shared_ptr
65 | getBackend();
66 |
67 | void
68 | updateProxy(std::string proxiedCollection);
69 |
70 | std::string
71 | getCollectionId();
72 |
73 |
74 | private:
75 | std::shared_ptr backend;
76 | std::weak_ptr parent;
77 |
78 | std::unique_ptr proxy;
79 | };
80 |
81 |
82 | #endif //PASS_FDO_SECRETS_ITEM_H
83 |
--------------------------------------------------------------------------------
/impl/ItemProxy.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/23.
3 | //
4 |
5 | #include "ItemProxy.h"
6 | #include "Item.h"
7 |
8 | ItemProxy::ItemProxy(sdbus::IConnection &conn,
9 | std::string path,
10 | std::weak_ptr
- parent_): parent(std::move(parent_)), sdbus::AdaptorInterfaces(conn, std::move(path)) {
11 | registerAdaptor();
12 | }
13 |
14 | ItemProxy::~ItemProxy() {
15 | unregisterAdaptor();
16 | }
17 |
18 | sdbus::ObjectPath
19 | ItemProxy::Delete() {
20 | return parent.lock()->Delete();
21 | }
22 |
23 | sdbus::Struct, std::vector, std::string>
24 | ItemProxy::GetSecret(const sdbus::ObjectPath &session) {
25 | return parent.lock()->GetSecret(session);
26 | }
27 |
28 | void
29 | ItemProxy::SetSecret(const sdbus::Struct, std::vector, std::string> &secret) {
30 | return parent.lock()->SetSecret(secret);
31 | }
32 |
33 | bool
34 | ItemProxy::Locked() {
35 | return parent.lock()->Locked();
36 | }
37 |
38 | std::map
39 | ItemProxy::Attributes() {
40 | return parent.lock()->Attributes();
41 | }
42 |
43 | void
44 | ItemProxy::Attributes(const std::map &value) {
45 | return parent.lock()->Attributes(value);
46 | }
47 |
48 | std::string
49 | ItemProxy::Label() {
50 | return parent.lock()->Label();
51 | }
52 |
53 | void
54 | ItemProxy::Label(const std::string &value) {
55 | return parent.lock()->Label(value);
56 | }
57 |
58 | std::string
59 | ItemProxy::Type() {
60 | return parent.lock()->Type();
61 | }
62 |
63 | void
64 | ItemProxy::Type(const std::string &value) {
65 | return parent.lock()->Type(value);
66 | }
67 |
68 | uint64_t
69 | ItemProxy::Created() {
70 | return parent.lock()->Created();
71 | }
72 |
73 | uint64_t
74 | ItemProxy::Modified() {
75 | return parent.lock()->Modified();
76 | }
77 |
--------------------------------------------------------------------------------
/impl/ItemProxy.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/23.
3 | //
4 |
5 | #ifndef PASS_SECRETS_ITEMPROXY_H
6 | #define PASS_SECRETS_ITEMPROXY_H
7 |
8 | #include
9 | #include
10 | #include "../adaptors/itemadaptor.h"
11 |
12 | class Item;
13 |
14 | class ItemProxy : public sdbus::AdaptorInterfaces {
15 | public:
16 | ItemProxy(sdbus::IConnection &conn,
17 | std::string path, std::weak_ptr
- parent_);
18 |
19 | ~ItemProxy();
20 |
21 | sdbus::ObjectPath Delete() override;
22 | sdbus::Struct, std::vector, std::string> GetSecret(const sdbus::ObjectPath& session) override;
23 | void SetSecret(const sdbus::Struct, std::vector, std::string>& secret) override;
24 | bool Locked() override;
25 | std::map Attributes() override;
26 | void Attributes(const std::map& value) override;
27 | std::string Label() override;
28 | void Label(const std::string& value) override;
29 | std::string Type() override;
30 | void Type(const std::string& value) override;
31 | uint64_t Created() override;
32 | uint64_t Modified() override;
33 |
34 | private:
35 | std::weak_ptr
- parent;
36 | };
37 |
38 |
39 | #endif //PASS_SECRETS_ITEMPROXY_H
40 |
--------------------------------------------------------------------------------
/impl/SecretService.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #include "SecretService.h"
6 | #include "Session.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "Item.h"
12 | #include "sessions/sessions.h"
13 |
14 | using namespace std;
15 |
16 | SecretService::SecretService(sdbus::IConnection &conn,
17 | std::string path) : AdaptorInterfaces(conn, std::move(path)) {
18 |
19 | registerAdaptor();
20 | }
21 |
22 | SecretService::~SecretService() {
23 | unregisterAdaptor();
24 | }
25 |
26 | std::tuple
27 | SecretService::OpenSession(const std::string &algorithm,
28 | const sdbus::Variant &input) {
29 | unique_ptr session;
30 | auto ptr = weak_from_this();
31 | auto &conn = this->getObject().getConnection();
32 | auto path = "/org/freedesktop/secrets/session/" + nanoid::generate();
33 | sdbus::Variant rtn;
34 | if (algorithm.empty() || algorithm == "plain") {
35 | session = make_unique(ptr, conn, path);
36 | rtn = session->getOutput();
37 | } else {
38 | throw sdbus::Error("org.freedesktop.DBus.Error.NotSupported", "Only plain is supported");
39 | }
40 |
41 | sessions.insert({path, move(session)});
42 |
43 | return {rtn, path};
44 | }
45 |
46 | std::tuple
47 | SecretService::CreateCollection(const std::map &properties,
48 | const std::string &alias) {
49 | auto nLabel = properties.count("org.freedesktop.Secret.Collection.Label") && properties.at("org.freedesktop.Secret.Collection.Label").containsValueOfType() ? properties.at("org.freedesktop.Secret.Collection.Label").get() : "Collection";
50 | auto nCollection = store.CreateCollection(nLabel, alias);
51 | auto coll = make_shared(nCollection, this->getObject().getConnection(), "/org/freedesktop/secrets/collection/" + nCollection->getId(), weak_from_this());
52 | collections.insert({nCollection->getId(), coll});
53 | return std::tuple(coll->getObjectPath(), "/");
54 | }
55 |
56 | std::tuple, std::vector>
57 | SecretService::SearchItems(const std::map &attributes) {
58 | vector locked;
59 | vector unlocked;
60 | for (const auto &collection : collections) {
61 | vector> items = collection.second->InternalSearchItems(attributes);
62 | for (const auto &item : items) {
63 | if (item->Locked()) {
64 | locked.push_back(item->getPath());
65 | } else {
66 | unlocked.push_back(item->getPath());
67 | }
68 | }
69 | }
70 | return std::tuple(unlocked, locked);
71 | }
72 |
73 |
74 | std::tuple, sdbus::ObjectPath>
75 | SecretService::Unlock(const std::vector &objects) {
76 | // TODO: Prompt?
77 | std::vector unlocked;
78 | for (const auto &item : fromObjectPath((const vector &)objects)) {
79 | if (!item->Locked() || item->getBackend()->unlock()) {
80 | item->emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Locked"});
81 | collections[item->getCollectionId()]->emitPropertiesChangedSignal("org.freedesktop.Secret.Collection", {"Locked"});
82 | unlocked.push_back(item->getPath());
83 | }
84 | }
85 |
86 | return std::tuple(unlocked, "/");
87 | }
88 |
89 | std::tuple, sdbus::ObjectPath>
90 | SecretService::Lock(const std::vector &objects) {
91 | // TODO: Prompt?
92 | std::vector locked;
93 | for (const auto &item : fromObjectPath((const vector &)objects)) {
94 | // TODO: could this cause a segfault?
95 | item->getBackend()->lock();
96 | item->emitPropertiesChangedSignal("org.freedesktop.Secret.Item", {"Locked"});
97 | collections[item->getCollectionId()]->emitPropertiesChangedSignal("org.freedesktop.Secret.Collection", {"Locked"});
98 | locked.push_back(item->getPath());
99 | }
100 | return std::tuple(locked, "/");
101 | }
102 |
103 | void
104 | SecretService::LockService() {
105 | for (const auto &entry : collections) {
106 | for (const auto &item : entry.second->GetBacking()->getItems()) {
107 | item->lock();
108 | }
109 | }
110 | }
111 |
112 | sdbus::ObjectPath
113 | SecretService::ChangeLock(const sdbus::ObjectPath &collection) {
114 | // TODO: Change lock
115 | // this isn't mentioned in the specification (gnome keyring specific?)
116 | return sdbus::ObjectPath("/");
117 | }
118 |
119 | std::map, std::vector, std::string>>
120 | SecretService::GetSecrets(const std::vector &items,
121 | const sdbus::ObjectPath &session) {
122 | auto it = fromObjectPath((const vector &)items);
123 | std::map, std::vector, std::string>> retn;
124 | for (const auto &item : it) {
125 | auto res = item->GetSecret(session);
126 | retn.insert({item->getPath(), res});
127 | }
128 | return retn;
129 | }
130 |
131 | sdbus::ObjectPath
132 | SecretService::ReadAlias(const std::string &name) {
133 | for (auto &entry : collections) {
134 | auto alias = entry.second->GetBacking()->getAlias();
135 | if (alias == name) {
136 | return sdbus::ObjectPath(entry.second->getObjectPath());
137 | }
138 | }
139 | return sdbus::ObjectPath("/");
140 | }
141 |
142 | void
143 | SecretService::SetAlias(const std::string &name,
144 | const sdbus::ObjectPath &collection) {
145 | std::filesystem::path objPath((string)collection);
146 | auto collId = objPath.filename().generic_string();
147 | if (!collections.count(collId)) {
148 | throw sdbus::Error("org.freedesktop.Secret.Error.NoSuchObject", "No such item or collection exists.");
149 | }
150 | collections[collId]->GetBacking()->setAlias(name);
151 | collections[collId]->GetBacking()->updateMetadata();
152 | collections[collId]->updateAlias();
153 | }
154 |
155 | std::vector
156 | SecretService::Collections() {
157 | std::vector cs;
158 | cs.reserve(collections.size());
159 |
160 | for (auto &entry : collections) {
161 | cs.emplace_back(entry.second->getObjectPath());
162 | }
163 |
164 | return cs;
165 | }
166 |
167 | std::vector>
168 | SecretService::fromObjectPath(const std::vector &paths) {
169 | std::vector> items;
170 | for (const auto &objectPath : paths) {
171 | auto oPath = std::filesystem::path((string)objectPath);
172 | if (oPath.has_parent_path()) {
173 | if (oPath.parent_path().filename() == "collection") { // Find all items
174 | auto collId = oPath.filename().generic_string();
175 | if (collections.count(collId)) {
176 | for (const auto &item : collections[collId]->getItemMap()) {
177 | items.push_back(item.second);
178 | }
179 | }
180 | } else { // this should be a normal item
181 | // obtain ids from path
182 | auto itemId = oPath.filename().generic_string();
183 | auto collId = oPath.parent_path().filename().generic_string();
184 | // if exists
185 | if (collections.count(collId) && collections[collId]->getItemMap().count(itemId)) {
186 | auto item = collections[collId]->getItemMap()[itemId];
187 | items.push_back(item);
188 | }
189 | }
190 | }
191 | }
192 | return items;
193 | }
194 |
195 | void
196 | SecretService::DiscardSession(const std::string &path) {
197 | discardedSessions.push_back(move(sessions.extract(path).mapped()));
198 | }
199 |
200 | void
201 | SecretService::DiscardCollection(std::string id) {
202 | discardedCollections.push_back(move(collections.extract(id).mapped()));
203 | }
204 |
205 | void
206 | SecretService::DiscardObjects() {
207 | while (!discardedSessions.empty()) {
208 | discardedSessions.pop_back();
209 | }
210 | while (!discardedCollections.empty()) {
211 | discardedCollections.pop_back();
212 | }
213 | for (const auto &entry : collections) {
214 | entry.second->DiscardObjects();
215 | }
216 | }
217 |
218 | void
219 | SecretService::InitCollections() {
220 | for (auto c : store.GetCollections()) {
221 | auto id = c->getId();
222 | auto collection = make_shared(c, this->getObject().getConnection(),
223 | "/org/freedesktop/secrets/collection/" + id, this->weak_from_this());
224 | collection->InitItems();
225 | collections.insert({id, move(collection)});
226 | }
227 | }
228 |
229 | std::pair, std::vector>
230 | SecretService::EncryptSecret(const string &path, uint8_t *data, size_t len) {
231 | if (!sessions.at(path)) throw std::runtime_error("Error: Session does not exist!");
232 | return std::move(sessions[path]->encryptSecret(data, len));
233 | }
234 |
235 |
236 |
--------------------------------------------------------------------------------
/impl/SecretService.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #ifndef PASS_FDO_SECRETS_SECRETSERVICE_H
6 | #define PASS_FDO_SECRETS_SECRETSERVICE_H
7 |
8 | #include
9 | #include "../adaptors/secretsadaptor.h"
10 | #include "../interop/PassStore.h"
11 | #include "Collection.h"
12 |
13 | class Session;
14 |
15 | class SecretService
16 | : public sdbus::AdaptorInterfaces,
17 | public std::enable_shared_from_this {
18 | public:
19 | SecretService(sdbus::IConnection &conn,
20 | std::string path);
21 |
22 | ~SecretService();
23 |
24 | void
25 | DiscardObjects();
26 |
27 | void
28 | DiscardSession(const std::string &path);
29 |
30 | void
31 | DiscardCollection(std::string id);
32 |
33 | void
34 | InitCollections();
35 |
36 | std::pair, std::vector>
37 | EncryptSecret(const std::string &path, uint8_t *data, size_t len);
38 |
39 | protected:
40 | std::tuple
41 | OpenSession(const std::string &algorithm,
42 | const sdbus::Variant &input) override;
43 |
44 | std::tuple
45 | CreateCollection(const std::map &properties,
46 | const std::string &alias) override;
47 |
48 | std::tuple, std::vector>
49 | SearchItems(const std::map &attributes) override;
50 |
51 | std::tuple, sdbus::ObjectPath>
52 | Unlock(const std::vector &objects) override;
53 |
54 | std::tuple, sdbus::ObjectPath>
55 | Lock(const std::vector &objects) override;
56 |
57 | void
58 | LockService() override;
59 |
60 | sdbus::ObjectPath
61 | ChangeLock(const sdbus::ObjectPath &collection) override;
62 |
63 | std::map, std::vector, std::string>>
64 | GetSecrets(const std::vector &items,
65 | const sdbus::ObjectPath &session) override;
66 |
67 | sdbus::ObjectPath
68 | ReadAlias(const std::string &name) override;
69 |
70 | void
71 | SetAlias(const std::string &name,
72 | const sdbus::ObjectPath &collection) override;
73 |
74 | std::vector
75 | Collections() override;
76 |
77 | private:
78 | std::map> sessions;
79 | std::vector> discardedSessions;
80 |
81 | PassStore store;
82 | std::map> collections;
83 | std::vector> discardedCollections;
84 |
85 | std::vector>
86 | fromObjectPath(const std::vector &paths);
87 | };
88 |
89 | #endif //PASS_FDO_SECRETS_SECRETSERVICE_H
90 |
--------------------------------------------------------------------------------
/impl/Session.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #include "Session.h"
6 | #include "SecretService.h"
7 |
8 | #include
9 |
10 |
11 | Session::Session(std::weak_ptr parent_,
12 | sdbus::IConnection &conn,
13 | std::string path) : AdaptorInterfaces(conn, std::move(path)), parent(std::move(parent_)) {
14 | sdbus::Flags flags;
15 | flags.set(sdbus::Flags::METHOD_NO_REPLY);
16 | this->getObject()
17 | .registerMethod(INTERFACE_NAME, "Close", "", "", [this](sdbus::MethodCall call) -> void { this->Close(call); },
18 | flags);
19 | registerAdaptor();
20 | }
21 |
22 | void
23 | Session::Close(sdbus::MethodCall msg) {
24 | parent.lock()->DiscardSession(this->getObjectPath());
25 | }
26 |
27 | Session::~Session() {
28 | this->unregisterAdaptor();
29 | };
30 |
--------------------------------------------------------------------------------
/impl/Session.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by nullobsi on 2021/03/17.
3 | //
4 |
5 | #ifndef PASS_FDO_SECRETS_SESSION_H
6 | #define PASS_FDO_SECRETS_SESSION_H
7 |
8 | #include "../adaptors/sessionadaptor.h"
9 |
10 | class SecretService;
11 |
12 | class Session : public sdbus::AdaptorInterfaces {
13 | public:
14 |
15 | Session(std::weak_ptr parent,
16 | sdbus::IConnection &conn,
17 | std::string path);
18 |
19 | ~Session();
20 |
21 | virtual std::pair, std::vector> encryptSecret(uint8_t *secret, size_t len) = 0;
22 | virtual sdbus::Variant getOutput() = 0;
23 |
24 | private:
25 | void
26 | Close(sdbus::MethodCall msg);
27 |
28 | std::weak_ptr