diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/CMakeLists.txt trust-store-2.0.0+16.04.20160119/3rd_party/xdg/CMakeLists.txt --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/CMakeLists.txt 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,22 @@ +project(xdg) + +cmake_minimum_required(VERSION 2.8) + +find_package(Boost COMPONENTS filesystem system unit_test_framework) + +include_directories( + . + ${Boost_INCLUDE_DIRS} +) + +add_library(xdg xdg.cpp) +set_property(TARGET xdg PROPERTY CXX_STANDARD 11) +target_link_libraries(xdg ${Boost_LIBRARIES}) + +enable_testing() +add_definitions(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN -DBOOST_TEST_MODULE=xdg) +add_executable(xdg_test xdg_test.cpp) +set_property(TARGET xdg_test PROPERTY CXX_STANDARD 11) +target_link_libraries(xdg_test xdg) + +add_test(xdg_test xdg_test) diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/LICENSE trust-store-2.0.0+16.04.20160119/3rd_party/xdg/LICENSE --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/LICENSE 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/README.md trust-store-2.0.0+16.04.20160119/3rd_party/xdg/README.md --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/README.md 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/README.md 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,87 @@ +# xdg + +A straightforward implementation of the XDG Base Directory Specification in C++11. +I became tired of retyping and retesting the same functionality over and over again, +so I decided to place my own little helper here. + +## Dependencies + + - boost::filesystem: For handling all things filesystem paths. + - boost::system:: Required by boost::filesystem. + - boost::test: For testing purposes obviously. + +Install with +```bash +sudo apt-get install libboost-filesystem-dev libboost-system-dev libboost-test-dev +``` + +## Quick'n'Easy Integration + +xdg provides free functions that are easy to integrate with existing projects. +```cpp +#include + +#include + +int main() +{ + std::cout << xdg::data().home() << std::endl; + std::cout << xdg::config().home() << std::endl; + std::cout << xdg::cache().home() << std::endl; + std::cout << xdg::runtime().dir() << std::endl; + + return 0; +} +``` + +## Complete Integration + +The interface xdg::BaseDirSpecification can be used to integrate xdg base directory +queries into a code base such that interaction with the xdg::BaseDirSpecification is testable. + +```cpp +#include + +class MyClass +{ +public: + MyClass(const std::shared_ptr& bds) : bds{bds} + { + } + + void do_something() + { + // Query the user-specific config directory. + auto path = bds->config().home(); + // Do something with the config files. + } +private: + std::shared_ptr bds; +}; + +// In the testing setup, under the assumption of Google Test and Google Mock. +namespace +{ +struct MockConfig : public xdg::Config +{ + // ... +}; +struct MockBaseDirSpecification : public xdg::BaseDirSpecification +{ + // ... +}; +} + +TEST(MyClass, do_something_queries_config_home_directory) +{ + using namespace ::testing; + auto config = std::make_shared>(); + EXPECT_CALL(*config, home()).Times(1).ReturnRepeatedly("/tmp"); + + auto bds = std::make_shared>(); + ON_CALL(*bds, config()).WillByDefault(ReturnRef(*config)); + + MyClass mc{bds}; + mc.do_something(); +} +``` diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg.cpp trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.cpp --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,203 @@ +// Copyright (C) 2015 Thomas Voß +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . + +#include + +#include + +#include +#include + +namespace fs = boost::filesystem; + +namespace +{ + +fs::path throw_if_not_absolute(const fs::path& p) +{ + if (p.has_root_directory()) + return p; + + throw std::runtime_error{"Directores MUST be absolute."}; +} + +namespace env +{ +std::string get(const std::string& key, const std::string& default_value) +{ + if (auto value = std::getenv(key.c_str())) + return value; + return default_value; +} + +std::string get_or_throw(const std::string& key) +{ + if (auto value = std::getenv(key.c_str())) + { + return value; + } + + throw std::runtime_error{key + " not set in environment"}; +} + +constexpr const char* xdg_data_home{"XDG_DATA_HOME"}; +constexpr const char* xdg_data_dirs{"XDG_DATA_DIRS"}; +constexpr const char* xdg_config_home{"XDG_CONFIG_HOME"}; +constexpr const char* xdg_config_dirs{"XDG_CONFIG_DIRS"}; +constexpr const char* xdg_cache_home{"XDG_CACHE_HOME"}; +constexpr const char* xdg_runtime_dir{"XDG_RUNTIME_DIR"}; +} + +namespace impl +{ +class BaseDirSpecification : public xdg::BaseDirSpecification +{ +public: + static const BaseDirSpecification& instance() + { + static const BaseDirSpecification spec; + return spec; + } + + BaseDirSpecification() + { + } + + const xdg::Data& data() const override + { + return data_; + } + + const xdg::Config& config() const override + { + return config_; + } + + const xdg::Cache& cache() const override + { + return cache_; + } + + const xdg::Runtime& runtime() const override + { + return runtime_; + } + +private: + xdg::Data data_; + xdg::Config config_; + xdg::Cache cache_; + xdg::Runtime runtime_; +}; +} +} + +fs::path xdg::Data::home() const +{ + auto v = env::get(env::xdg_data_home, ""); + if (v.empty()) + return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".local" / "share"); + + return throw_if_not_absolute(fs::path(v)); +} + +std::vector xdg::Data::dirs() const +{ + auto v = env::get(env::xdg_data_dirs, ""); + if (v.empty()) + return {fs::path{"/usr/local/share"}, fs::path{"/usr/share"}}; + + std::vector tokens; + tokens = boost::split(tokens, v, boost::is_any_of(":")); + std::vector result; + for (const auto& token : tokens) + { + result.push_back(throw_if_not_absolute(fs::path(token))); + } + return result; +} + +fs::path xdg::Config::home() const +{ + auto v = env::get(env::xdg_config_home, ""); + if (v.empty()) + return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".config"); + + return throw_if_not_absolute(fs::path(v)); +} + +std::vector xdg::Config::dirs() const +{ + auto v = env::get(env::xdg_config_dirs, ""); + if (v.empty()) + return {fs::path{"/etc/xdg"}}; + + std::vector tokens; + tokens = boost::split(tokens, v, boost::is_any_of(":")); + std::vector result; + for (const auto& token : tokens) + { + fs::path p(token); + result.push_back(throw_if_not_absolute(p)); + } + return result; +} + +fs::path xdg::Cache::home() const +{ + auto v = env::get(env::xdg_cache_home, ""); + if (v.empty()) + return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".cache"); + + return throw_if_not_absolute(fs::path(v)); +} + +fs::path xdg::Runtime::dir() const +{ + auto v = env::get(env::xdg_runtime_dir, ""); + if (v.empty()) + { + // We do not fall back gracefully and instead throw, dispatching to calling + // code for handling the case of a safe user-specfic runtime directory missing. + throw std::runtime_error{"Runtime directory not set"}; + } + + return throw_if_not_absolute(fs::path(v)); +} + +std::shared_ptr xdg::BaseDirSpecification::create() +{ + return std::make_shared(); +} + +const xdg::Data& xdg::data() +{ + return impl::BaseDirSpecification::instance().data(); +} + +const xdg::Config& xdg::config() +{ + return impl::BaseDirSpecification::instance().config(); +} + +const xdg::Cache& xdg::cache() +{ + return impl::BaseDirSpecification::instance().cache(); +} + +const xdg::Runtime& xdg::runtime() +{ + return impl::BaseDirSpecification::instance().runtime(); +} diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg.h trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.h --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.h 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,118 @@ +// Copyright (C) 2015 Thomas Voß +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +#ifndef XDG_H_ +#define XDG_H_ + +#include + +#include +#include + +namespace xdg +{ +// NotCopyable deletes the copy c'tor and the assignment operator. +struct NotCopyable +{ + NotCopyable() = default; + NotCopyable(const NotCopyable&) = delete; + virtual ~NotCopyable() = default; + NotCopyable& operator=(const NotCopyable&) = delete; +}; + +// NotMoveable deletes the move c'tor and the move assignment operator. +struct NotMoveable +{ + NotMoveable() = default; + NotMoveable(NotMoveable&&) = delete; + virtual ~NotMoveable() = default; + NotMoveable& operator=(NotMoveable&&) = delete; +}; + +// Data provides functions to query the XDG_DATA_* entries. +class Data : NotCopyable, NotMoveable +{ +public: + // home returns the base directory relative to which user specific + // data files should be stored. + virtual boost::filesystem::path home() const; + // dirs returns the preference-ordered set of base directories to + // search for data files in addition to the $XDG_DATA_HOME base + // directory. + virtual std::vector dirs() const; +}; + +// Config provides functions to query the XDG_CONFIG_* entries. +class Config : NotCopyable, NotMoveable +{ +public: + // home returns the base directory relative to which user specific + // configuration files should be stored. + virtual boost::filesystem::path home() const; + // dirs returns the preference-ordered set of base directories to + // search for configuration files in addition to the + // $XDG_CONFIG_HOME base directory. + virtual std::vector dirs() const; +}; + +// Cache provides functions to query the XDG_CACHE_HOME entry. +class Cache : NotCopyable, NotMoveable +{ +public: + // home returns the base directory relative to which user specific + // non-essential data files should be stored. + virtual boost::filesystem::path home() const; +}; + +// Runtime provides functions to query the XDG_RUNTIME_DIR entry. +class Runtime : NotCopyable, NotMoveable +{ +public: + // home returns the base directory relative to which user-specific + // non-essential runtime files and other file objects (such as + // sockets, named pipes, ...) should be stored. + virtual boost::filesystem::path dir() const; +}; + +// A BaseDirSpecification implements the XDG base dir specification: +// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +class BaseDirSpecification : NotCopyable, NotMoveable +{ +public: + // create returns an Implementation of BaseDirSpecification. + static std::shared_ptr create(); + + // data returns an immutable Data instance. + virtual const Data& data() const = 0; + // config returns an immutable Config instance. + virtual const Config& config() const = 0; + // cache returns an immutable Cache instance. + virtual const Cache& cache() const = 0; + // runtime returns an immutable Runtime instance. + virtual const Runtime& runtime() const = 0; +protected: + BaseDirSpecification() = default; +}; + +// data returns an immutable reference to a Data instance. +const Data& data(); +// config returns an immutable reference to a Config instance. +const Config& config(); +// cache returns an immutable reference to a Cache instance. +const Cache& cache(); +// runtime returns an immutable reference to a Runtime instance. +const Runtime& runtime(); +} + +#endif // XDG_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg_test.cpp trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg_test.cpp --- trust-store-2.0.0+15.10.20150831.3/3rd_party/xdg/xdg_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg_test.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,130 @@ +// Copyright (C) 2015 Thomas Voß +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . + +#include + +#include + +#include +#include + +BOOST_AUTO_TEST_CASE(XdgDataHomeThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_DATA_HOME", "tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->data().home(), std::runtime_error); + BOOST_CHECK_THROW(xdg::data().home(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgDataHomeReturnsDefaultValueForEmptyEnv) +{ + ::setenv("HOME", "/tmp", 1); + ::setenv("XDG_DATA_HOME", "", 1); + BOOST_CHECK_EQUAL("/tmp/.local/share", xdg::BaseDirSpecification::create()->data().home()); + BOOST_CHECK_EQUAL("/tmp/.local/share", xdg::data().home()); +} + +BOOST_AUTO_TEST_CASE(XdgDataDirsCorrectlyTokenizesEnv) +{ + ::setenv("XDG_DATA_DIRS", "/tmp:/tmp", 1); + BOOST_CHECK(2 == xdg::BaseDirSpecification::create()->data().dirs().size()); + BOOST_CHECK(2 == xdg::data().dirs().size()); +} + +BOOST_AUTO_TEST_CASE(XdgDataDirsThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_DATA_DIRS", "/tmp:tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->data().dirs(), std::runtime_error); + BOOST_CHECK_THROW(xdg::data().dirs(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgDataDirsReturnsDefaultValueForEmptyEnv) +{ + ::setenv("XDG_DATA_DIRS", "", 1); + auto dirs = xdg::data().dirs(); + BOOST_CHECK_EQUAL("/usr/local/share", dirs[0]); + BOOST_CHECK_EQUAL("/usr/share", dirs[1]); + + dirs = xdg::BaseDirSpecification::create()->data().dirs(); + BOOST_CHECK_EQUAL("/usr/local/share", dirs[0]); + BOOST_CHECK_EQUAL("/usr/share", dirs[1]); +} + +BOOST_AUTO_TEST_CASE(XdgConfigHomeThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_CONFIG_HOME", "tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->config().home(), std::runtime_error); + BOOST_CHECK_THROW(xdg::config().home(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgConfigHomeReturnsDefaultValueForEmptyEnv) +{ + ::setenv("HOME", "/tmp", 1); + ::setenv("XDG_CONFIG_HOME", "", 1); + BOOST_CHECK_EQUAL("/tmp/.config", xdg::BaseDirSpecification::create()->config().home()); + BOOST_CHECK_EQUAL("/tmp/.config", xdg::config().home()); +} + +BOOST_AUTO_TEST_CASE(XdgConfigDirsCorrectlyTokenizesEnv) +{ + ::setenv("XDG_CONFIG_DIRS", "/tmp:/tmp", 1); + BOOST_CHECK(2 == xdg::BaseDirSpecification::create()->config().dirs().size()); + BOOST_CHECK(2 == xdg::config().dirs().size()); +} + +BOOST_AUTO_TEST_CASE(XdgConfigDirsThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_CONFIG_DIRS", "/tmp:tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->config().dirs(), std::runtime_error); + BOOST_CHECK_THROW(xdg::config().dirs(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgConfigDirsReturnsDefaultValueForEmptyEnv) +{ + ::setenv("XDG_CONFIG_DIRS", "", 1); + auto dirs = xdg::config().dirs(); + BOOST_CHECK_EQUAL("/etc/xdg", dirs[0]); + dirs = xdg::BaseDirSpecification::create()->config().dirs(); + BOOST_CHECK_EQUAL("/etc/xdg", dirs[0]); +} + +BOOST_AUTO_TEST_CASE(XdgCacheHomeThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_CACHE_HOME", "tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->cache().home(), std::runtime_error); + BOOST_CHECK_THROW(xdg::cache().home(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgCacheHomeReturnsDefaultValueForEmptyEnv) +{ + ::setenv("HOME", "/tmp", 1); + ::setenv("XDG_CACHE_HOME", "", 1); + BOOST_CHECK_EQUAL("/tmp/.cache", xdg::BaseDirSpecification::create()->cache().home()); + BOOST_CHECK_EQUAL("/tmp/.cache", xdg::cache().home()); +} + +BOOST_AUTO_TEST_CASE(XdgRuntimeDirThrowsForRelativeDirectoryFromEnv) +{ + ::setenv("XDG_RUNTIME_DIR", "tmp", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->runtime().dir(), std::runtime_error); + BOOST_CHECK_THROW(xdg::runtime().dir(), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(XdgRuntimeDirThrowsForEmptyEnv) +{ + ::setenv("XDG_RUNTIME_DIR", "", 1); + BOOST_CHECK_THROW(xdg::BaseDirSpecification::create()->runtime().dir(), std::runtime_error); + BOOST_CHECK_THROW(xdg::runtime().dir(), std::runtime_error); +} + diff -Nru trust-store-2.0.0+15.10.20150831.3/CMakeLists.txt trust-store-2.0.0+16.04.20160119/CMakeLists.txt --- trust-store-2.0.0+15.10.20150831.3/CMakeLists.txt 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/CMakeLists.txt 2016-01-19 15:22:45.000000000 +0000 @@ -2,6 +2,37 @@ project(trust-store) +# We haven't received version information via the packaging setup. +# For that, we try to determine sensible values on our own, ensuring +# plain old invocations to cmake still work as expected. +if (NOT DEFINED TRUST_STORE_VERSION_MAJOR) + find_program(LSB_RELEASE lsb_release) + execute_process( + COMMAND ${LSB_RELEASE} -c -s + OUTPUT_VARIABLE DISTRO_CODENAME + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # We explicitly ignore errors and only check if we are building for vivid. + # For all other cases: + # - releases other than vivid + # - other distros + # - errors + # we define the version to be 2.0.0 + if (${DISTRO_CODENAME} STREQUAL "vivid") + set(TRUST_STORE_VERSION_MAJOR 1) + set(TRUST_STORE_VERSION_MINOR 1) + set(TRUST_STORE_VERSION_PATCH 0) + else () + set(TRUST_STORE_VERSION_MAJOR 2) + set(TRUST_STORE_VERSION_MINOR 0) + set(TRUST_STORE_VERSION_PATCH 0) + endif() +endif() + +message(STATUS "${CMAKE_PROJECT_NAME} ${TRUST_STORE_VERSION_MAJOR}.${TRUST_STORE_VERSION_MINOR}.${TRUST_STORE_VERSION_PATCH}") + + + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(cmake/EnableCoverageReport.cmake) @@ -28,7 +59,9 @@ ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE]) find_package(PkgConfig) -find_package(Boost COMPONENTS program_options system REQUIRED) +find_package(Boost COMPONENTS filesystem program_options system REQUIRED) + +add_subdirectory(3rd_party/xdg) option( TRUST_STORE_MIR_AGENT_ENABLED @@ -46,14 +79,11 @@ pkg_check_modules(GLOG libglog REQUIRED) pkg_check_modules(PROCESS_CPP process-cpp REQUIRED) -set(TRUST_STORE_VERSION_MAJOR 2) -set(TRUST_STORE_VERSION_MINOR 0) -set(TRUST_STORE_VERSION_PATCH 0) - include(CTest) include_directories( include/ + 3rd_party/xdg ${GFLAGS_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS} diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/changelog trust-store-2.0.0+16.04.20160119/debian/changelog --- trust-store-2.0.0+15.10.20150831.3/debian/changelog 2015-08-31 15:11:25.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/changelog 2016-01-19 15:22:52.000000000 +0000 @@ -1,3 +1,16 @@ +trust-store (2.0.0+16.04.20160119-0ubuntu1) xenial; urgency=medium + + [ CI Train Bot ] + * Resync trunk. + + [ Thomas Voß ] + * Enable dual landing to vivid+o, and all later releases. + * Merge core::trust::Runtime changes. Add better support for in- + session service scenarios, with services likely being activated on + demand. Add load test cases around in-session service scenario. + + -- Rodney Dawes Tue, 19 Jan 2016 15:22:52 +0000 + trust-store (2.0.0+15.10.20150831.3-0ubuntu1) wily; urgency=medium [ Alfonso Sanchez-Beato (email Canonical) ] @@ -14,6 +27,44 @@ -- Thomas Voß Thu, 23 Jul 2015 09:22:15 +0200 +trust-store (1.1.0+15.04.20160118.4-0ubuntu1) vivid; urgency=medium + + * Enable translations for vivid. (LP: #1532870) + + -- Thomas Voß Mon, 18 Jan 2016 20:35:42 +0000 + +trust-store (1.1.0+15.04.20160112-0ubuntu1) vivid; urgency=medium + + * Update pot file for trust-store. (LP: #1532870) + + -- Thomas Voß Tue, 12 Jan 2016 20:09:20 +0000 + +trust-store (1.1.0+15.04.20151211-0ubuntu1) vivid; urgency=medium + + [ CI Train Bot ] + * Revert bump to major revision 2, vivid (+overlay) still has 1.1.0 + and gcc 4.9. + + [ Thomas Voß ] + * Add a 3rd-party dependency on github.com/vosst/xdg. + * Add interface mir::AppNameResolver. (LP: #1382610, #1504022) + * Introduce a trust::PrivilegeEscalationPreventionAgent, filtering out + invalid requests. Fixes lp:#1518883. (LP: #1518883) + + -- Thomas Voß Fri, 11 Dec 2015 08:58:16 +0000 + +trust-store (1.1.0+15.04.20151126-0ubuntu1) vivid; urgency=medium + + [ Thomas Voß ] + * Revert bump to major revision 2, vivid (+overlay) still has + 1.1.0 and gcc 4.9. + + [ CI Train Bot ] + * New rebuild forced. + * Resync trunk. + + -- Thomas Voß Thu, 26 Nov 2015 07:32:48 +0000 + trust-store (1.1.0+15.04.20150820-0ubuntu1) vivid; urgency=medium [ Ken VanDine ] diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/control trust-store-2.0.0+16.04.20160119/debian/control --- trust-store-2.0.0+15.10.20150831.3/debian/control 2015-08-31 15:11:25.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/control 2016-01-19 15:26:01.000000000 +0000 @@ -1,3 +1,8 @@ +# This file is autogenerated. DO NOT EDIT! +# +# Modifications should be made to control.in instead. +# This file is regenerated automatically in the clean target. +# Source: trust-store Priority: optional Maintainer: Ubuntu Developers @@ -7,17 +12,21 @@ google-mock, graphviz, libapparmor-dev, + libboost-filesystem-dev, libboost-program-options-dev, libboost-system-dev, + libboost-test-dev, libdbus-cpp-dev (>= 4.0.0), libdbus-1-dev, libgflags-dev, + libglib2.0-dev, libgoogle-glog-dev, libgtest-dev, libjson-c-dev, libmirclient-dev [amd64 arm64 i386 armhf], libprocess-cpp-dev, libsqlite3-dev, + lsb-release, pkg-config, qt5-default, qtbase5-dev, diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/control.in trust-store-2.0.0+16.04.20160119/debian/control.in --- trust-store-2.0.0+15.10.20150831.3/debian/control.in 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/control.in 2016-01-19 15:22:39.000000000 +0000 @@ -0,0 +1,97 @@ +Source: trust-store +Priority: optional +Maintainer: Ubuntu Developers +Build-Depends: cmake, + debhelper (>= 9), + doxygen, + google-mock, + graphviz, + libapparmor-dev, + libboost-filesystem-dev, + libboost-program-options-dev, + libboost-system-dev, + libboost-test-dev, + libdbus-cpp-dev (>= 4.0.0), + libdbus-1-dev, + libgflags-dev, + libglib2.0-dev, + libgoogle-glog-dev, + libgtest-dev, + libjson-c-dev, + libmirclient-dev [amd64 arm64 i386 armhf], + libprocess-cpp-dev, + libsqlite3-dev, + lsb-release, + pkg-config, + qt5-default, + qtbase5-dev, + qtdeclarative5-dev, +Standards-Version: 3.9.5 +Section: libs +Homepage: https://launchpad.net/trust-store +# if you don't have have commit access to this branch but would like to upload +# directly to Ubuntu, don't worry: your changes will be merged back into the +# upstream branch +Vcs-Bzr: lp:trust-store + +Package: libtrust-store@TRUST_STORE_SOVERSION@ +Architecture: any +Multi-Arch: same +Pre-Depends: ${misc:Pre-Depends}, +Depends: ${misc:Depends}, + ${shlibs:Depends}, +Description: C++11 library for persisting trust requests - runtime library + Provides a common implementation of a trust store to be used by trusted + helpers. + . + This package includes the trust-store runtime libraries. + +Package: libtrust-store-dev +Section: libdevel +Architecture: any +Multi-Arch: same +Pre-Depends: ${misc:Pre-Depends}, +Recommends: libtrust-store-doc, +Depends: libtrust-store@TRUST_STORE_SOVERSION@ (= ${binary:Version}), + ${misc:Depends}, +Description: C++11 library for persisting trust requests - dev files + Provides a common implementation of a trust store to be used by trusted + helpers. + . + This package includes all the development headers and libraries for + trust-store. + +Package: trust-store-bin +Section: devel +Architecture: any +Depends: libtrust-store@TRUST_STORE_SOVERSION@ (= ${binary:Version}), + ${misc:Depends}, +Description: Daemon binaries to be used by services. + Provides a common implementation of a trust store to be used by trusted + helpers. + . + Daemon binaries to be used by services. + +Package: trust-store-tests +Section: libdevel +Architecture: any +Depends: libtrust-store@TRUST_STORE_SOVERSION@ (= ${binary:Version}), + ${misc:Depends}, +Suggests: libtrust-store-dev, +Description: Test files for libtrust-store1 + Provides a common implementation of a trust store to be used by trusted + helpers. + . + This package includes test executables packaged for post-build execution. + +Package: libtrust-store-doc +Section: doc +Architecture: all +Depends: ${misc:Depends}, +Suggests: libtrust-store-dev, +Description: Documentation files for libtrust-store-dev + Provides a common implementation of a trust store to be used by trusted + helpers. + . + This package includes documentation files for developing with and for + libtrust-store-dev. diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/gen-debian-files.sh trust-store-2.0.0+16.04.20160119/debian/gen-debian-files.sh --- trust-store-2.0.0+15.10.20150831.3/debian/gen-debian-files.sh 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/gen-debian-files.sh 2016-01-19 15:22:39.000000000 +0000 @@ -0,0 +1,97 @@ +#!/bin/sh + +# Copyright (C) 2015 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +# Authored by: Michi Henning +# Thomas Voß + +# +# Script to generate debian files for dual landing in Vivid (gcc 4.9 ABI) +# and Wily and later (gcc 5 ABI). +# +# This script is called from debian/rules and generates: +# +# - control +# - libtrust-store${soversion}.install.${target_arch} +# +# For all but control, this is a straight substition and/or renaming exercise for each file. +# For control, if building on Wily or later, we also fix the "Replaces:" and "Conflicts:" +# entries, so we don't end up with two packages claiming ownership of the same places +# in the file system. +# +# Because the debian files for the different distributions are generated on the fly, +# this allows us to keep a single source tree for both distributions. See ../HACKING +# for more explanations. +# + +set -e # Fail if any command fails. + +progname=$(basename $0) + +[ $# -ne 1 ] && { + echo "usage: $progname path-to-debian-dir" >&2 + exit 1 +} +dir=$1 +version_dir=$(mktemp -d) + +# Dump version numbers into files and initialize vars from those files. + +sh ${dir}/get-versions.sh ${dir} ${version_dir} + +full_version=$(cat "${version_dir}"/libtrust-store.full-version) +major_minor=$(cat "${version_dir}"/libtrust-store.major-minor-version) +soversion=$(cat "${version_dir}"/libtrust-store.soversion) +vivid_soversion=$(cat "${version_dir}"/libtrust-store.vivid-soversion) + +warning=$(mktemp -t gen-debian-files-msg.XXX) + +trap "rm -fr $warning $version_dir" 0 INT TERM QUIT + +warning_msg() +{ + cat >$warning < "$outfile" + +[ "$distro" != "vivid" ] && { + sed -i -e "/Replaces: libtrust-store1,/a\ +\ libtrust-store${vivid_soversion}," \ + "$outfile" +} + +# Generate the install files, naming them according to the soversion. + +# Install file for binary package +infile="${dir}"/libtrust-store.install.in +outfile="${dir}"/libtrust-store${soversion}.install +warning_msg "$infile" +cat $warning "$infile" >"$outfile" + +exit 0 diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/get-versions.sh trust-store-2.0.0+16.04.20160119/debian/get-versions.sh --- trust-store-2.0.0+15.10.20150831.3/debian/get-versions.sh 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/get-versions.sh 2016-01-19 15:22:39.000000000 +0000 @@ -0,0 +1,68 @@ +#!/bin/sh + +# Copyright (C) 2015 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +# Authored by: Michi Henning + +# +# Script to read the version numbers from VERSION and QT-VERSION +# and write the version components and the soversion numbers +# into separate files, so we can pick them up from both +# gen-debian-files.sh and CMakeLists.txt. +# + +set -e # Fail if any command fails. + +progname=$(basename $0) + +[ $# -lt 1 -o $# -gt 2 ] && { + echo "usage: $progname path-to-debian-dir [output-dir]" >&2 + exit 1 +} +dir=$1 +output_dir=`pwd` +[ $# -eq 2 ] && output_dir=$2 + +# Write the various version numbers into a bunch of files. This allows +# us to easily pick them up from both gen-debian-files.sh and CMakeLists.txt. + +distro=$(lsb_release -c -s) + +full_version=$(cat "${dir}"/VERSION) + +major=$(echo $full_version | cut -d'.' -f1) +minor=$(echo $full_version | cut -d'.' -f2) +micro=$(echo $full_version | cut -d'.' -f3) +major_minor="${major}.${minor}" + +vivid_full_version=$(cat "${dir}"/VERSION.vivid) +vivid_major=$(echo $vivid_full_version | cut -d'.' -f1) +vivid_soversion=$vivid_major + +if [ "$distro" = "vivid" ] +then + soversion=${vivid_soversion} +else + soversion="${major}" +fi +[ -n $soversion ] + +echo ${full_version} >${output_dir}/libtrust-store.full-version +echo ${major} >${output_dir}/libtrust-store.major-version +echo ${minor} >${output_dir}/libtrust-store.minor-version +echo ${micro} >${output_dir}/libtrust-store.micro-version +echo ${major_minor} >${output_dir}/libtrust-store.major-minor-version +echo ${soversion} >${output_dir}/libtrust-store.soversion +echo ${vivid_soversion} >${output_dir}/libtrust-store.vivid-soversion diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/libtrust-store2.install trust-store-2.0.0+16.04.20160119/debian/libtrust-store2.install --- trust-store-2.0.0+15.10.20150831.3/debian/libtrust-store2.install 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/libtrust-store2.install 2016-01-19 15:26:01.000000000 +0000 @@ -1,2 +1,7 @@ +# This file is autogenerated. DO NOT EDIT! +# +# Modifications should be made to libtrust-store.install.in instead. +# This file is regenerated automatically in the clean target. +# usr/lib/*/lib*.so.* diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/libtrust-store.install.in trust-store-2.0.0+16.04.20160119/debian/libtrust-store.install.in --- trust-store-2.0.0+15.10.20150831.3/debian/libtrust-store.install.in 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/libtrust-store.install.in 2016-01-19 15:22:34.000000000 +0000 @@ -0,0 +1,2 @@ +usr/lib/*/lib*.so.* + diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/rules trust-store-2.0.0+16.04.20160119/debian/rules --- trust-store-2.0.0+15.10.20150831.3/debian/rules 2015-08-31 15:11:25.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/rules 2016-01-19 15:22:51.000000000 +0000 @@ -5,6 +5,18 @@ include /usr/share/dpkg/default.mk +distro=$(shell lsb_release -c -s) + +ifeq ($(distro),vivid) + full_version=$(shell cat $(CURDIR)/debian/VERSION.vivid) +else + full_version=$(shell cat $(CURDIR)/debian/VERSION) +endif + +major=$(shell echo $(full_version) | cut -d'.' -f1) +minor=$(shell echo $(full_version) | cut -d'.' -f2) +patch=$(shell echo $(full_version) | cut -d'.' -f3) + # Mir is an optional build dependency ifneq (,$(filter $(DEB_HOST_ARCH),amd64 arm64 i386 armhf)) TRUST_STORE_MIR_AGENT_ENABLED = ON @@ -19,4 +31,8 @@ dh $@ --fail-missing override_dh_auto_configure: - dh_auto_configure -- -DTRUST_STORE_MIR_AGENT_ENABLED=$(TRUST_STORE_MIR_AGENT_ENABLED) + dh_auto_configure -- -DTRUST_STORE_MIR_AGENT_ENABLED=$(TRUST_STORE_MIR_AGENT_ENABLED) -DTRUST_STORE_VERSION_MAJOR=$(major) -DTRUST_STORE_VERSION_MINOR=$(minor) -DTRUST_STORE_VERSION_PATCH=$(patch) + +override_dh_auto_clean: + /bin/sh $(CURDIR)/debian/gen-debian-files.sh $(CURDIR)/debian + dh_auto_clean diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/VERSION trust-store-2.0.0+16.04.20160119/debian/VERSION --- trust-store-2.0.0+15.10.20150831.3/debian/VERSION 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/VERSION 2016-01-19 15:22:39.000000000 +0000 @@ -0,0 +1 @@ +2.0.0 \ No newline at end of file diff -Nru trust-store-2.0.0+15.10.20150831.3/debian/VERSION.vivid trust-store-2.0.0+16.04.20160119/debian/VERSION.vivid --- trust-store-2.0.0+15.10.20150831.3/debian/VERSION.vivid 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/debian/VERSION.vivid 2016-01-19 15:22:39.000000000 +0000 @@ -0,0 +1 @@ +1.1.0 \ No newline at end of file diff -Nru trust-store-2.0.0+15.10.20150831.3/include/core/trust/expose.h trust-store-2.0.0+16.04.20160119/include/core/trust/expose.h --- trust-store-2.0.0+15.10.20150831.3/include/core/trust/expose.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/include/core/trust/expose.h 2016-01-19 15:22:50.000000000 +0000 @@ -59,7 +59,7 @@ */ CORE_TRUST_DLL_PUBLIC std::unique_ptr expose_store_to_bus_with_name( const std::shared_ptr& store, - const std::shared_ptr& bus, + const std::shared_ptr& bus, const std::string& name); /** diff -Nru trust-store-2.0.0+15.10.20150831.3/po/ast.po trust-store-2.0.0+16.04.20160119/po/ast.po --- trust-store-2.0.0+15.10.20150831.3/po/ast.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/ast.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-15 19:35+0000\n" -"Last-Translator: ivarela \n" +"PO-Revision-Date: 2015-10-06 11:53+0000\n" +"Last-Translator: Xuacu Saturio \n" "Language-Team: Asturian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-10-07 06:07+0000\n" +"X-Generator: Launchpad (build 17802)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "La aplicación %1% ta intentando l'accesu" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/ca.po trust-store-2.0.0+16.04.20160119/po/ca.po --- trust-store-2.0.0+15.10.20150831.3/po/ca.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/ca.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-10 07:04+0000\n" +"PO-Revision-Date: 2015-09-04 14:27+0000\n" "Last-Translator: David Planella \n" "Language-Team: Catalan \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-05 05:39+0000\n" +"X-Generator: Launchpad (build 17706)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "L'aplicació %1% està intentant accedir" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/de.po trust-store-2.0.0+16.04.20160119/po/de.po --- trust-store-2.0.0+15.10.20150831.3/po/de.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/de.po 2016-01-19 15:22:34.000000000 +0000 @@ -6,20 +6,20 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-10 14:26+0000\n" -"Last-Translator: PS Jenkins bot \n" +"PO-Revision-Date: 2015-11-07 21:39+0000\n" +"Last-Translator: Niklas Wenzel \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-11-08 05:46+0000\n" +"X-Generator: Launchpad (build 17838)\n" "Language: de\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Anwendung »%1%« versucht, zuzugreifen auf" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/el.po trust-store-2.0.0+16.04.20160119/po/el.po --- trust-store-2.0.0+15.10.20150831.3/po/el.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/el.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-11-18 22:47+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2015-09-06 08:21+0000\n" +"Last-Translator: Aggelos Arnaoutis \n" "Language-Team: Greek \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-07 06:00+0000\n" +"X-Generator: Launchpad (build 17706)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Η εφαμογή %1% προσπαθεί να αποκτήσει πρόσβαση" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/en_AU.po trust-store-2.0.0+16.04.20160119/po/en_AU.po --- trust-store-2.0.0+15.10.20150831.3/po/en_AU.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/en_AU.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-12 09:35+0000\n" +"PO-Revision-Date: 2015-09-20 00:58+0000\n" "Last-Translator: Jared Norris \n" "Language-Team: English (Australia) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-21 05:38+0000\n" +"X-Generator: Launchpad (build 17746)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Application %1% is trying to access" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/es.po trust-store-2.0.0+16.04.20160119/po/es.po --- trust-store-2.0.0+15.10.20150831.3/po/es.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/es.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-10 16:24+0000\n" +"PO-Revision-Date: 2015-09-16 09:49+0000\n" "Last-Translator: Víctor R. Ruiz \n" "Language-Team: Spanish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-17 05:48+0000\n" +"X-Generator: Launchpad (build 17737)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "La aplicación %1% está intentando acceder a" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/gd.po trust-store-2.0.0+16.04.20160119/po/gd.po --- trust-store-2.0.0+15.10.20150831.3/po/gd.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/gd.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-10 10:36+0000\n" +"PO-Revision-Date: 2015-09-03 13:16+0000\n" "Last-Translator: GunChleoc \n" "Language-Team: Gaelic; Scottish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-04 05:37+0000\n" +"X-Generator: Launchpad (build 17706)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Tha aplacaid %1% a' feuchainn ri inntrigeadh fhaighinn dha" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/it.po trust-store-2.0.0+16.04.20160119/po/it.po --- trust-store-2.0.0+15.10.20150831.3/po/it.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/it.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-13 09:51+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2015-08-31 06:48+0000\n" +"Last-Translator: Claudio Arseni \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-02 05:52+0000\n" +"X-Generator: Launchpad (build 17706)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "L'applicazione %1% sta tentando di accedere" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/ne.po trust-store-2.0.0+16.04.20160119/po/ne.po --- trust-store-2.0.0+15.10.20150831.3/po/ne.po 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/ne.po 2016-01-19 15:22:34.000000000 +0000 @@ -0,0 +1,31 @@ +# Nepali translation for trust-store +# Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 +# This file is distributed under the same license as the trust-store package. +# FIRST AUTHOR , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: trust-store\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2015-08-20 13:41-0400\n" +"PO-Revision-Date: 2015-11-04 15:47+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Nepali \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2015-11-05 05:46+0000\n" +"X-Generator: Launchpad (build 17838)\n" + +#: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 +#, boost-format +msgid "Application %1% is trying to access" +msgstr "" + +#: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 +msgid "Deny" +msgstr "" + +#: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 +msgid "Allow" +msgstr "" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/pl.po trust-store-2.0.0+16.04.20160119/po/pl.po --- trust-store-2.0.0+15.10.20150831.3/po/pl.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/pl.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-11-01 22:06+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2015-10-22 11:47+0000\n" +"Last-Translator: Krzysztof Tataradziński \n" "Language-Team: Polish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-10-23 05:49+0000\n" +"X-Generator: Launchpad (build 17812)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Aplikacja %1% próbuje uzyskać dostęp" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/ro.po trust-store-2.0.0+16.04.20160119/po/ro.po --- trust-store-2.0.0+15.10.20150831.3/po/ro.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/ro.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-10-10 09:06+0000\n" -"Last-Translator: Marian Vasile \n" +"PO-Revision-Date: 2015-09-04 15:46+0000\n" +"Last-Translator: Meriuță Cornel \n" "Language-Team: Romanian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-09-05 05:39+0000\n" +"X-Generator: Launchpad (build 17706)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Aplicaţia %1% încearcă să acceseze" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/sr.po trust-store-2.0.0+16.04.20160119/po/sr.po --- trust-store-2.0.0+15.10.20150831.3/po/sr.po 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/sr.po 2016-01-19 15:22:34.000000000 +0000 @@ -8,19 +8,19 @@ "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2015-08-20 13:41-0400\n" -"PO-Revision-Date: 2014-11-07 04:09+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2015-10-26 21:49+0000\n" +"Last-Translator: Данило Шеган \n" "Language-Team: Serbian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2015-08-22 05:53+0000\n" -"X-Generator: Launchpad (build 17690)\n" +"X-Launchpad-Export-Date: 2015-10-28 05:56+0000\n" +"X-Generator: Launchpad (build 17833)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" -msgstr "" +msgstr "Програм %1% покушава да приступи" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" diff -Nru trust-store-2.0.0+15.10.20150831.3/po/trust-store.pot trust-store-2.0.0+16.04.20160119/po/trust-store.pot --- trust-store-2.0.0+15.10.20150831.3/po/trust-store.pot 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/po/trust-store.pot 2016-01-19 15:22:45.000000000 +0000 @@ -8,24 +8,23 @@ msgstr "" "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-08-20 13:41-0400\n" +"POT-Creation-Date: 2016-01-12 21:03+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 -#, boost-format -msgid "Application %1% is trying to access" +#: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/daemon.cpp:266 +msgid "is trying to access" msgstr "" -#: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 -msgid "Deny" +#: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/mir/prompt_main.qml:78 +msgid "Allow" msgstr "" -#: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 -msgid "Allow" +#: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/mir/prompt_main.qml:83 +msgid "Don’t Allow" msgstr "" diff -Nru trust-store-2.0.0+15.10.20150831.3/src/CMakeLists.txt trust-store-2.0.0+16.04.20160119/src/CMakeLists.txt --- trust-store-2.0.0+15.10.20150831.3/src/CMakeLists.txt 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/CMakeLists.txt 2016-01-19 15:22:50.000000000 +0000 @@ -20,6 +20,8 @@ pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED) pkg_check_modules(DBUS dbus-1 REQUIRED) +pkg_check_modules(GLIB glib-2.0 REQUIRED) +pkg_check_modules(GOBJECT gobject-2.0 REQUIRED) pkg_check_modules(LIBAPPARMOR libapparmor REQUIRED) pkg_check_modules(SQLITE3 sqlite3 REQUIRED) @@ -28,6 +30,8 @@ include_directories( ${DBUS_CPP_INCLUDE_DIRS} ${DBUS_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${GOBJECT_INCLUDE_DIRS} ${LIBAPPARMOR_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIRS} ) @@ -43,6 +47,9 @@ core/trust/app_id_formatting_trust_agent.h core/trust/app_id_formatting_trust_agent.cpp + # An agent implementation preventing privilege escalation attacks. + core/trust/privilege_escalation_prevention_agent.cpp + # An agent-implementation that allows for selectively whitelisting app ids core/trust/white_listing_agent.cpp # An agent-implementation using a store instance to cache user replies. @@ -70,6 +77,7 @@ # to prompt the user for trusting an application to access a trusted # system service. core/trust/mir/agent.cpp + core/trust/mir/click_desktop_entry_app_info_resolver.cpp ) # Make sure Qt does not inject evil macros like 'signals' and 'slots'. @@ -129,10 +137,15 @@ core/trust/expose.cpp core/trust/request.cpp core/trust/resolve.cpp + core/trust/runtime.h + core/trust/runtime.cpp # All dbus-specific headers go here core/trust/dbus/agent.h + core/trust/dbus/agent.cpp core/trust/dbus/agent_registry.h + core/trust/dbus/bus_factory.h + core/trust/dbus/bus_factory.cpp core/trust/dbus/codec.h core/trust/dbus/interface.h @@ -149,6 +162,9 @@ trust-stored core/trust/daemon.cpp + + core/trust/runtime.h + core/trust/runtime.cpp ) add_executable( @@ -180,11 +196,14 @@ trust-store dbus-cpp + xdg ${Boost_LIBRARIES} ${DBUS_LIBRARIES} ${GFLAGS_LDFLAGS} ${GLOG_LDFLAGS} + ${GLIB_LDFLAGS} + ${GOBJECT_LDFLAGS} ${LIBAPPARMOR_LDFLAGS} ${MIR_CLIENT_LDFLAGS} ${PROCESS_CPP_LDFLAGS} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/daemon.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/daemon.cpp 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -22,11 +22,15 @@ #include #include #include +#include +#include #include #include #include +#include + #include #include #include @@ -49,67 +53,6 @@ namespace { - struct Runtime - { - // Do not execute in parallel, serialize - // accesses. - static constexpr std::size_t concurrency_hint{2}; - - // Our evil singleton pattern. Not bad though, we control the - // entire executable and rely on automatic cleanup of static - // instances. - static Runtime& instance() - { - static Runtime runtime; - return runtime; - } - - ~Runtime() - { - io_service.stop(); - - if (worker1.joinable()) - worker1.join(); - - if (worker2.joinable()) - worker2.join(); - } - - // We trap sig term to ensure a clean shutdown. - std::shared_ptr signal_trap - { - core::posix::trap_signals_for_all_subsequent_threads( - { - core::posix::Signal::sig_term, - core::posix::Signal::sig_int - }) - }; - - // Our io_service instance exposed to remote agents. - boost::asio::io_service io_service - { - concurrency_hint - }; - - // We keep the io_service alive and introduce some artificial - // work. - boost::asio::io_service::work keep_alive - { - io_service - }; - - // We immediate execute the io_service instance - std::thread worker1 - { - std::thread{[this]() { io_service.run(); }} - }; - - std::thread worker2 - { - std::thread{[this]() { io_service.run(); }} - }; - }; - core::trust::Daemon::Dictionary fill_dictionary_from_unrecognized_options(const Options::parsed_options& parsed_options) { auto unrecognized = Options::collect_unrecognized( @@ -151,34 +94,6 @@ core::trust::Request::Answer canned_answer; }; - - core::dbus::Bus::Ptr bus_from_name(const std::string& bus_name) - { - core::dbus::Bus::Ptr bus; - - if (bus_name == "system") - bus = std::make_shared(core::dbus::WellKnownBus::system); - else if (bus_name == "session") - bus = std::make_shared(core::dbus::WellKnownBus::session); - else if (bus_name == "system_with_address_from_env") - bus = std::make_shared(core::posix::this_process::env::get_or_throw("DBUS_SYSTEM_BUS_ADDRESS")); - else if (bus_name == "session_with_address_from_env") - bus = std::make_shared(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS")); - - if (not bus) throw std::runtime_error - { - "Could not create bus for name: " + bus_name - }; - - bus->install_executor(core::dbus::asio::make_executor(bus, Runtime::instance().io_service)); - - return bus; - } - - core::dbus::Bus::Ptr bus_from_dictionary(const core::trust::Daemon::Dictionary& dict) - { - return bus_from_name(dict.at("bus")); - } } const std::map& core::trust::Daemon::Skeleton::known_local_agent_factories() @@ -246,7 +161,7 @@ { { std::string{Daemon::RemoteAgents::UnixDomainSocketRemoteAgent::name}, - [](const std::string& service_name, const std::shared_ptr& agent, const Dictionary& dict) + [](const std::string& service_name, const std::shared_ptr& agent, const core::trust::dbus::BusFactory::Ptr&, const Dictionary& dict) { if (dict.count("endpoint") == 0) throw std::runtime_error { @@ -256,13 +171,13 @@ core::trust::remote::posix::Skeleton::Configuration config { agent, - Runtime::instance().io_service, + core::trust::Runtime::instance().service(), boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::helpers::aa_get_task_con_app_id_resolver(), dict.count("description-pattern") > 0 ? dict.at("description-pattern") : - core::trust::i18n::tr("Application %1% is trying to access") + " " + service_name + ".", + core::trust::i18n::tr("is trying to access") + " " + service_name + ".", dict.count("verify-process-timestamp") > 0 }; @@ -270,15 +185,15 @@ } }, { - std::string{Daemon::RemoteAgents::DBusRemoteAgent::name}, - [](const std::string& service_name, const std::shared_ptr& agent, const Dictionary& dict) + std::string{Daemon::RemoteAgents::SystemServiceDBusRemoteAgent::name}, + [](const std::string& service_name, const std::shared_ptr& agent, const core::trust::dbus::BusFactory::Ptr& bf, const Dictionary& dict) { if (dict.count("bus") == 0) throw std::runtime_error { "Missing bus specifier, please choose from {system, session}." }; - auto bus = bus_from_dictionary(dict); + auto bus = bf->bus_for_type(boost::lexical_cast(dict.at("bus"))); std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name; @@ -289,16 +204,45 @@ core::trust::remote::dbus::default_agent_registry_path }); + core::dbus::DBus daemon{bus}; + core::trust::remote::dbus::Agent::Skeleton::Configuration config { agent, object, + daemon.make_service_watcher(dbus_service_name), service, bus, core::trust::remote::helpers::aa_get_task_con_app_id_resolver() }; - return std::make_shared(config); + return std::make_shared(std::move(config)); + } + }, + { + std::string{Daemon::RemoteAgents::SessionServiceDBusRemoteAgent::name}, + [](const std::string& service_name, const std::shared_ptr& agent, const core::trust::dbus::BusFactory::Ptr& bf, const Dictionary& dict) + { + if (dict.count("bus") == 0) throw std::runtime_error + { + "Missing bus specifier, please choose from {system, session}." + }; + + auto bus = bf->bus_for_type(boost::lexical_cast(dict.at("bus"))); + + auto service = core::dbus::Service::add_service(bus, (core::trust::dbus::Agent::default_service_name_pattern() % service_name).str()); + auto object = service->add_object_for_path(core::trust::dbus::Agent::default_object_path()); + + return std::make_shared( + core::trust::dbus::Agent::Skeleton::Configuration + { + object, + bus, + [agent](const core::trust::Agent::RequestParameters& params) + { + return agent->authenticate_request_with_parameters(params); + } + }); } } }; @@ -315,7 +259,7 @@ options.add_options() (Parameters::ForService::name, Options::value()->required(), Parameters::ForService::description) (Parameters::WithTextDomain::name, Options::value(), Parameters::WithTextDomain::description) - (Parameters::StoreBus::name, Options::value()->default_value("session"), Parameters::StoreBus::description) + (Parameters::StoreBus::name, Options::value()->required(), Parameters::StoreBus::description) (Parameters::LocalAgent::name, Options::value()->required(), Parameters::LocalAgent::description) (Parameters::RemoteAgent::name, Options::value()->required(), Parameters::RemoteAgent::description); @@ -323,10 +267,10 @@ { argc, argv - }; + }; try - { + { auto parsed_options = parser.options(options).allow_unregistered().run(); Options::store(parsed_options, vm); Options::notify(vm); @@ -340,6 +284,8 @@ }; } + auto bf = core::trust::dbus::BusFactory::create_default(); + auto service_name = vm[Parameters::ForService::name].as(); auto service_text_domain = service_name; @@ -375,14 +321,18 @@ }, cached_agent); auto formatting_agent = std::make_shared(whitelisting_agent); + + auto privilege_escalation_prevention_agent = std::make_shared( + core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor(), + formatting_agent); - auto remote_agent = remote_agent_factory(service_name, formatting_agent, dict); + auto remote_agent = remote_agent_factory(service_name, formatting_agent, bf, dict); return core::trust::Daemon::Skeleton::Configuration { service_name, - bus_from_name(vm[Parameters::StoreBus::name].as()), - {local_store, formatting_agent}, + bf->bus_for_type(vm[Parameters::StoreBus::name].as()), + {local_store, privilege_escalation_prevention_agent}, {remote_agent} }; } @@ -390,16 +340,6 @@ // Executes the daemon with the given configuration. core::posix::exit::Status core::trust::Daemon::Skeleton::main(const core::trust::Daemon::Skeleton::Configuration& configuration) { - Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal) - { - Runtime::instance().signal_trap->stop(); - }); - - std::thread worker - { - [configuration]() { configuration.bus->run(); } - }; - // Expose the local store to the bus, keeping it exposed for the // lifetime of the returned token. auto token = core::trust::expose_store_to_bus_with_name( @@ -407,12 +347,7 @@ configuration.bus, configuration.service_name); - Runtime::instance().signal_trap->run(); - - configuration.bus->stop(); - - if (worker.joinable()) - worker.join(); + core::trust::Runtime::instance().run(); return core::posix::exit::Status::success; } @@ -423,7 +358,7 @@ { { std::string{Daemon::RemoteAgents::UnixDomainSocketRemoteAgent::name}, - [](const std::string&, const Dictionary& dict) + [](const std::string&, const core::trust::dbus::BusFactory::Ptr&, const Dictionary& dict) { if (dict.count("endpoint") == 0) throw std::runtime_error { @@ -432,7 +367,7 @@ core::trust::remote::posix::Stub::Configuration config { - Runtime::instance().io_service, + core::trust::Runtime::instance().service(), boost::asio::local::stream_protocol::endpoint{dict.at("endpoint")}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(), @@ -443,10 +378,10 @@ } }, { - std::string{Daemon::RemoteAgents::DBusRemoteAgent::name}, - [](const std::string& service_name, const Dictionary& dict) + std::string{Daemon::RemoteAgents::SystemServiceDBusRemoteAgent::name}, + [](const std::string& service_name, const core::trust::dbus::BusFactory::Ptr& bf, const Dictionary& dict) { - auto bus = bus_from_dictionary(dict); + auto bus = bf->bus_for_type(boost::lexical_cast(dict.at("bus"))); std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name; @@ -502,12 +437,14 @@ }; } + auto bf = core::trust::dbus::BusFactory::create_default(); + auto service_name = vm[Parameters::ForService::name].as(); auto remote_agent_factory = core::trust::Daemon::Stub::known_remote_agent_factories() .at(vm[Parameters::RemoteAgent::name].as()); - auto remote_agent = remote_agent_factory(service_name, dict); + auto remote_agent = remote_agent_factory(service_name, bf, dict); return core::trust::Daemon::Stub::Configuration { @@ -522,13 +459,18 @@ // A user can feed a request to the stub. struct Shell : public std::enable_shared_from_this { - Shell(const std::shared_ptr& agent) + Shell(const std::shared_ptr& agent, boost::asio::io_service& ios) : agent{agent}, - stdin{Runtime::instance().io_service, STDIN_FILENO}, + stdin{ios, STDIN_FILENO}, app_id_resolver{core::trust::remote::helpers::aa_get_task_con_app_id_resolver()} { } + ~Shell() + { + stop(); + } + // Prints out the initial prompt and initiates a read operation on stdin. void start() { @@ -605,20 +547,13 @@ core::posix::exit::Status core::trust::Daemon::Stub::main(const core::trust::Daemon::Stub::Configuration& configuration) { // We setup our minimal shell here. - auto shell = std::make_shared(configuration.remote.agent); - - Runtime::instance().signal_trap->signal_raised().connect([](core::posix::Signal) - { - Runtime::instance().signal_trap->stop(); - }); + auto shell = std::make_shared(configuration.remote.agent, core::trust::Runtime::instance().service()); // We start up our shell shell->start(); // Wait until signal arrives. - Runtime::instance().signal_trap->run(); - - shell->stop(); + core::trust::Runtime::instance().run(); return core::posix::exit::Status::success; } diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/daemon.h trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/daemon.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.h 2016-01-19 15:22:50.000000000 +0000 @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -92,11 +93,20 @@ }; // A remote agent implementation leveraging dbus. - struct DBusRemoteAgent + struct SystemServiceDBusRemoteAgent { static constexpr const char* name { - "DBusRemoteAgent" + "DBusRemoteAgent" // TODO(tvoss): Rename and adjust downstream projects on next abi bump. + }; + }; + + // A remote agent implementation leveraging dbus. + struct SessionServiceDBusRemoteAgent + { + static constexpr const char* name + { + "SessionServiceDBusRemoteAgent" }; }; }; @@ -107,15 +117,16 @@ typedef std::function< std::shared_ptr( const std::string&, // The name of the service. - const Dictionary&) // Dictionary containing Agent-specific configuration options. + const Dictionary&) // Dictionary containing Agent-specific configuration options. > LocalAgentFactory; // Functor for creating trust::remote::Agent instances given a // set of parameters. typedef std::function< - std::shared_ptr( + std::shared_ptr( const std::string&, // The name of the service. const std::shared_ptr&, // The local agent implementation. + const core::trust::dbus::BusFactory::Ptr&, // The bus bus factory. const Dictionary& // Dictionary containing Agent-specific configuration options. ) > RemoteAgentFactory; @@ -187,7 +198,7 @@ // of this daemon instance. struct { - std::shared_ptr agent; + std::shared_ptr agent; } remote; }; @@ -201,6 +212,7 @@ typedef std::function< std::shared_ptr( const std::string&, // The name of the service. + const core::trust::dbus::BusFactory::Ptr&, // The bus bus factory. const Dictionary&) // Dictionary containing Agent-specific configuration options. > RemoteAgentFactory; diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright © 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +boost::format core::trust::dbus::Agent::default_service_name_pattern() +{ + return boost::format("core.trust.dbus.Agent.%1%"); +} + +core::dbus::types::ObjectPath core::trust::dbus::Agent::default_object_path() +{ + return core::dbus::types::ObjectPath{"/core/trust/dbus/Agent"}; +} + +const std::string& core::trust::dbus::Agent::name() +{ + static const std::string s{"core.trust.dbus.Agent"}; + return s; +} + +core::trust::dbus::Agent::Errors::CouldNotDetermineConclusiveAnswer::CouldNotDetermineConclusiveAnswer() + : std::runtime_error("Could not determine conclusive answer to trust request.") +{ +} + +core::trust::dbus::Agent::Stub::Stub(const core::dbus::Object::Ptr& object) + : object{object} +{ +} + +core::trust::Request::Answer core::trust::dbus::Agent::Stub::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) +{ + auto result = object->transact_method + < + Methods::AuthenticateRequestWithParameters, + core::trust::Request::Answer + >(parameters); + + if (result.is_error()) throw std::runtime_error + { + result.error().print() + }; + + return result.value(); +} + +core::trust::dbus::Agent::Skeleton::Skeleton(const Configuration& config) + : configuration(config) +{ + configuration.object->install_method_handler([this](const core::dbus::Message::Ptr& in) + { + core::trust::Agent::RequestParameters params; in->reader() >> params; + + core::dbus::Message::Ptr reply; + try + { + reply = core::dbus::Message::make_method_return(in); + reply->writer() << authenticate_request_with_parameters(params); + } catch(const std::exception& e) + { + // TODO(tvoss): we should report the error locally here. + reply = core::dbus::Message::make_error(in, Errors::CouldNotDetermineConclusiveAnswer::name, ""); + } catch(...) + { + reply = core::dbus::Message::make_error(in, Errors::CouldNotDetermineConclusiveAnswer::name, ""); + } + + configuration.bus->send(reply); + }); +} + +core::trust::Request::Answer core::trust::dbus::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& request) +{ + return configuration.agent(request); +} + + +/** + * @brief create_per_user_agent_for_bus_connection creates a trust::Agent implementation communicating with a remote agent + * implementation living in the same user session. + * @param connection An existing DBus connection. + * @param service The name of the service we are operating for. + * @throws std::runtime_error in case of issues. + */ +std::shared_ptr core::trust::dbus::create_per_user_agent_for_bus_connection( + const std::shared_ptr& connection, + const std::string& service_name) +{ + auto object = + core::dbus::Service::use_service(connection, (core::trust::dbus::Agent::default_service_name_pattern() % service_name).str()) + ->object_for_path(core::trust::dbus::Agent::default_object_path()); + + return std::shared_ptr + { + new core::trust::dbus::Agent::Stub{object} + }; +} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent.h trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.h 2016-01-19 15:22:50.000000000 +0000 @@ -28,6 +28,8 @@ #include #include +#include + namespace core { namespace trust @@ -36,14 +38,10 @@ { struct Agent { - static const std::string& name() - { - static const std::string s - { - "core.trust.dbus.Agent" - }; - return s; - } + CORE_TRUST_DLL_PUBLIC static boost::format default_service_name_pattern(); + CORE_TRUST_DLL_PUBLIC static core::dbus::types::ObjectPath default_object_path(); + + static const std::string& name(); struct Errors { @@ -54,10 +52,7 @@ "core.trust.dbus.Agent.Errors.CouldNotDetermineConclusiveAnswer" }; - CouldNotDetermineConclusiveAnswer() - : std::runtime_error("Could not determine conclusive answer to trust request.") - { - } + CouldNotDetermineConclusiveAnswer(); }; }; @@ -66,39 +61,21 @@ { // And thus not constructible Methods() = delete; - DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(AuthenticateRequestWithParameters, Agent, 120000) }; - class Stub : public core::trust::Agent + class CORE_TRUST_DLL_PUBLIC Stub : public core::trust::Agent { public: - Stub(const core::dbus::Object::Ptr& object) - : object{object} - { - } - - Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override - { - auto result = object->transact_method - < - Methods::AuthenticateRequestWithParameters, - core::trust::Request::Answer - >(parameters); + Stub(const core::dbus::Object::Ptr& object); - if (result.is_error()) throw std::runtime_error - { - result.error().print() - }; - - return result.value(); - } + Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; private: core::dbus::Object::Ptr object; }; - class Skeleton : public core::trust::Agent + class CORE_TRUST_DLL_PUBLIC Skeleton : public core::trust::Agent { public: // All creation time parameters go here. @@ -112,35 +89,9 @@ std::function agent; }; - Skeleton(const Configuration& config) - : configuration(config) - { - configuration.object->install_method_handler([this](const core::dbus::Message::Ptr& in) - { - core::trust::Agent::RequestParameters params; in->reader() >> params; - - core::dbus::Message::Ptr reply; - try - { - reply = core::dbus::Message::make_method_return(in); - reply->writer() << authenticate_request_with_parameters(params); - } catch(const std::exception& e) - { - // TODO(tvoss): we should report the error locally here. - reply = core::dbus::Message::make_error(in, Errors::CouldNotDetermineConclusiveAnswer::name, ""); - } catch(...) - { - reply = core::dbus::Message::make_error(in, Errors::CouldNotDetermineConclusiveAnswer::name, ""); - } - - configuration.bus->send(reply); - }); - } + Skeleton(const Configuration& config); - Request::Answer authenticate_request_with_parameters(const RequestParameters& request) override - { - return configuration.agent(request); - } + Request::Answer authenticate_request_with_parameters(const RequestParameters& request) override; private: // We just store all creation time parameters. @@ -151,25 +102,4 @@ } } -/** - * @brief create_per_user_agent_for_bus_connection creates a trust::Agent implementation communicating with a remote agent - * implementation living in the same user session. - * @param connection An existing DBus connection. - * @param service The name of the service we are operating for. - * @throws std::runtime_error in case of issues. - */ -std::shared_ptr core::trust::dbus::create_per_user_agent_for_bus_connection( - const std::shared_ptr& connection, - const std::string& service_name) -{ - auto object = - core::dbus::Service::use_service(connection,"core.trust.dbus.Agent." + service_name) - ->object_for_path(core::dbus::types::ObjectPath{"/core/trust/dbus/Agent"}); - - return std::shared_ptr - { - new core::trust::dbus::Agent::Stub{object} - }; -} - #endif // CORE_TRUST_DBUS_AGENT_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent_registry.h trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent_registry.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/agent_registry.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent_registry.h 2016-01-19 15:22:50.000000000 +0000 @@ -179,6 +179,44 @@ locking_agent_registry.register_agent_for_user(uid, skeleton); } + // Calls into the remote implementation to register the given agent implementation. + // Throws std::runtime_error and std::logic_error in case of issues. + void register_agent_for_user_async(const core::trust::Uid& uid, const std::shared_ptr& impl, const std::function& then) + { + // We sample a path for the given uid + auto path = configuration.object_path_generator(uid); + // And construct the skeleton instance. + auto skeleton = std::shared_ptr + { + new core::trust::dbus::Agent::Skeleton + { + core::trust::dbus::Agent::Skeleton::Configuration + { + configuration.service->add_object_for_path(path), + configuration.bus, + std::bind(&core::trust::Agent::authenticate_request_with_parameters, impl, std::placeholders::_1) + } + } + }; + + // And announce the agent. + configuration.object->invoke_method_asynchronously_with_callback< + Methods::RegisterAgentForUser, void + >([this, then, uid, skeleton](const core::dbus::Result& result) + { + if (result.is_error()) + { + std::cerr << "Failed to register agent for user: " << result.error().print() << std::endl; + } + else + { + // All good, update our own state prior to invoking the supplied callback. + locking_agent_registry.register_agent_for_user(uid, skeleton); + then(); + } + }, uid, path); + } + // Calls into the remote implementation to unregister any agent registered for the given uid. // Throws std::runtime_error and std::logic_error in case of issues. void unregister_agent_for_user(const core::trust::Uid& uid) override diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/bus_factory.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/bus_factory.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -0,0 +1,104 @@ +/* + * Copyright © 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include +#include + +#include +#include + +#include + +namespace env = core::posix::this_process::env; + +namespace +{ +class DefaultBusFactory : public core::trust::dbus::BusFactory +{ + core::dbus::Bus::Ptr bus_for_type(Type type) override + { + core::dbus::Bus::Ptr bus; + + switch (type) + { + case Type::system: + bus = std::make_shared(core::dbus::WellKnownBus::system); + break; + case Type::session: + bus = std::make_shared(core::dbus::WellKnownBus::session); + break; + case Type::system_with_address_from_env: + bus = std::make_shared(env::get_or_throw("DBUS_SYSTEM_BUS_ADDRESS")); + break; + case Type::session_with_address_from_env: + bus = std::make_shared(env::get_or_throw("DBUS_SESSION_BUS_ADDRESS")); + break; + } + + if (not bus) throw std::runtime_error + { + "Could not create bus for name: " + boost::lexical_cast(type) + }; + + bus->install_executor(core::dbus::asio::make_executor(bus, core::trust::Runtime::instance().service())); + return bus; + } +}; +} + +core::trust::dbus::BusFactory::Ptr core::trust::dbus::BusFactory::create_default() +{ + return std::make_shared(); +} + +std::ostream& core::trust::dbus::operator<<(std::ostream& out, core::trust::dbus::BusFactory::Type type) +{ + switch (type) + { + case core::trust::dbus::BusFactory::Type::system: + out << "system"; + break; + case core::trust::dbus::BusFactory::Type::session: + out << "session"; + break; + case core::trust::dbus::BusFactory::Type::system_with_address_from_env: + out << "system_with_address_from_env"; + break; + case core::trust::dbus::BusFactory::Type::session_with_address_from_env: + out << "session_with_address_from_env"; + break; + } + + return out; +} + +std::istream& core::trust::dbus::operator>>(std::istream& in, core::trust::dbus::BusFactory::Type& type) +{ + std::string s; in >> s; + + if (s == "system") + type = core::trust::dbus::BusFactory::Type::system; + else if (s == "session") + type = core::trust::dbus::BusFactory::Type::session; + else if (s == "system_with_address_from_env") + type = core::trust::dbus::BusFactory::Type::system_with_address_from_env; + else if (s == "session_with_address_from_env") + type = core::trust::dbus::BusFactory::Type::session_with_address_from_env; + + return in; +} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/bus_factory.h trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/dbus/bus_factory.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.h 2016-01-19 15:22:50.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright © 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#ifndef CORE_TRUST_DBUS_BUS_FACTORY_H_ +#define CORE_TRUST_DBUS_BUS_FACTORY_H_ + +#include + +#include + +#include + +namespace core +{ +namespace trust +{ +namespace dbus +{ +// BusFactory abstracts creation of bus instances. +class CORE_TRUST_DLL_PUBLIC BusFactory +{ +public: + typedef std::shared_ptr Ptr; + + // Type enumerates all different types of buses + // that we can create instances for. + enum class Type + { + session, // The default session bus. + system, // The default system bus. + session_with_address_from_env, // Session bus with address as available in the process's env. + system_with_address_from_env // System bus with address as available in the process's env. + }; + + // create_default returns an instance of the default implementation. + static Ptr create_default(); + + // @cond + BusFactory(const BusFactory&) = delete; + BusFactory(BusFactory&&) = delete; + virtual ~BusFactory() = default; + + BusFactory& operator=(const BusFactory&) = delete; + BusFactory& operator=(BusFactory&&) = delete; + // @endcond + + // bus_for_type returns a dbus::Bus instance for type. + virtual core::dbus::Bus::Ptr bus_for_type(Type type) = 0; +protected: + BusFactory() = default; +}; + +// operator<< inserts the given BusFactory::Type instance into the given std::ostream. +CORE_TRUST_DLL_PUBLIC std::ostream& operator<<(std::ostream&, BusFactory::Type); +// operator>> extracts a BusFactory::Type instance from the given std::istream. +CORE_TRUST_DLL_PUBLIC std::istream& operator>>(std::istream&, BusFactory::Type&); +} +} +} + +#endif // CORE_TRUST_DBUS_BUS_FACTORY_H_ + diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/impl/sqlite3/store.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/impl/sqlite3/store.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -17,10 +17,12 @@ */ #include +#include #include #include +#include #include #include @@ -30,39 +32,32 @@ #include #include -namespace core -{ -std::string home() -{ - return core::posix::this_process::env::get_or_throw("HOME"); -} - -std::string runtime_persistent_data_dir() -{ - return core::posix::this_process::env::get( - "XDG_DATA_HOME", - home() + "/.local/share"); -} +namespace fs = boost::filesystem; -struct Directory +namespace core { - Directory(const std::string& name) - { - // Default permissions for directory creation. - mode_t default_mode = 0755; - // This is only a helper and we are consciously ignoring - // errors. We will fail later on when trying to opening the - // database, anyway. - mkdir(name.c_str(), default_mode); - } -}; - namespace trust { namespace impl { namespace sqlite { +// ensure_dirs_or_throw ensures that the directory p exists +// with the correct permissions, i.e., 0700. +fs::path ensure_dir_or_throw(const fs::path& p) +{ + // Ideally, we would use fs::create_directories but + // https://svn.boost.org/trac/boost/ticket/11179 + // Prevents us from doing so. + static const mode_t owner_all = S_IRWXU; + if (mkdir(p.string().c_str(), owner_all) != 0) + { + if (errno != EEXIST) throw std::system_error(errno, std::system_category()); + } + + return p; +} + std::pair is_error(int result) { switch(result) @@ -333,7 +328,7 @@ throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error()); return TaggedPreparedStatement(this, stmt); - } + } std::string error() const { @@ -687,7 +682,7 @@ } d; }; - Store(const std::string &service_name); + Store(const std::string &service_name, xdg::BaseDirSpecification& spec); ~Store(); // Handles upgrades to the underlying database if the schema changes. @@ -704,7 +699,6 @@ std::shared_ptr query(); std::mutex guard; - core::Directory runtime_peristent_data_directory; Database db; TaggedPreparedStatement create_data_table_statement; @@ -719,9 +713,8 @@ namespace trust = core::trust; namespace sqlite = core::trust::impl::sqlite; -sqlite::Store::Store(const std::string& service_name) - : runtime_peristent_data_directory{core::runtime_persistent_data_dir() + "/" + service_name}, - db{core::runtime_persistent_data_dir() + "/" + service_name + "/trust.db"}, +sqlite::Store::Store(const std::string& service_name, xdg::BaseDirSpecification& spec) + : db{(ensure_dir_or_throw(spec.data().home() / service_name) / "trust.db").string()}, create_data_table_statement{db.prepare_tagged_statement()} { upgrade(db.get_version()); @@ -783,10 +776,15 @@ return std::shared_ptr{new sqlite::Store::Query{shared_from_this()}}; } -std::shared_ptr core::trust::create_default_store(const std::string& service_name) +std::shared_ptr core::trust::impl::sqlite::create_for_service(const std::string& name, xdg::BaseDirSpecification& spec) { - if (service_name.empty()) + if (name.empty()) throw core::trust::Errors::ServiceNameMustNotBeEmpty(); - return std::shared_ptr{new sqlite::Store(service_name)}; + return std::make_shared(name, spec); +} + +std::shared_ptr core::trust::create_default_store(const std::string& service_name) +{ + return core::trust::impl::sqlite::create_for_service(service_name, *xdg::BaseDirSpecification::create()); } diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/impl/sqlite3/store.h trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/impl/sqlite3/store.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.h 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ +#ifndef CORE_TRUST_IMPL_SQLITE3_H_ +#define CORE_TRUST_IMPL_SQLITE3_H_ + +#include + +#include +#include + +namespace xdg +{ +class BaseDirSpecification; +} + +namespace core +{ +namespace trust +{ +class Store; +namespace impl +{ +namespace sqlite +{ +// create_for_service creates a Store implementation relying on sqlite3, managing +// trust for the service identified by service_name. Uses spec to determine a user-specific +// directory to place the trust database. +CORE_TRUST_DLL_PUBLIC std::shared_ptr create_for_service(const std::string& service_name, xdg::BaseDirSpecification& spec); +} +} +} +} + +#endif // CORE_TRUST_IMPL_SQLITE3_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/agent.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/agent.cpp 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -33,6 +33,11 @@ namespace mir = core::trust::mir; +bool mir::operator==(const mir::AppInfo& lhs, const mir::AppInfo& rhs) +{ + return lhs.icon == rhs.icon && lhs.id == rhs.id && lhs.name == rhs.name; +} + // Invoked whenever a request for creation of pre-authenticated fds succeeds. void mir::PromptSessionVirtualTable::mir_client_fd_callback(MirPromptSession */*prompt_session*/, size_t count, int const* fds, void* context) { @@ -134,27 +139,15 @@ { static auto child_setup = []() {}; - // We translate to human readable strings here, and do it a non-translateable way first - // We post-process the application id and try to extract the unversioned package name. - // Please see https://wiki.ubuntu.com/AppStore/Interfaces/ApplicationId. - static const std::regex regex_full_app_id{"(.*)_(.*)_(.*)"}; - static const std::regex regex_short_app_id{"(.*)_(.*)"}; - static constexpr std::size_t index_app{2}; - - auto app_name = args.application_id; - - std::smatch match; - if (std::regex_match(app_name, match, regex_full_app_id)) - app_name = std::string{match[index_app]}; - else if (std::regex_match(app_name, match, regex_short_app_id)) - app_name = std::string{match[index_app]}; - - auto description = (boost::format(i18n::tr(args.description, i18n::service_text_domain())) % app_name).str(); + auto app_name = args.app_info.name; + auto description = i18n::tr(args.description, i18n::service_text_domain()); std::vector argv { "--" + std::string{core::trust::mir::cli::option_server_socket}, "fd://" + std::to_string(args.fd), - "--" + std::string{core::trust::mir::cli::option_title}, app_name, + "--" + std::string{core::trust::mir::cli::option_icon}, args.app_info.icon, + "--" + std::string{core::trust::mir::cli::option_name}, args.app_info.name, + "--" + std::string{core::trust::mir::cli::option_id}, args.app_info.id, "--" + std::string{core::trust::mir::cli::option_description}, description }; @@ -219,30 +212,14 @@ }; } -mir::Agent::Agent( - // VTable object providing access to Mir's trusted prompting functionality. - const mir::ConnectionVirtualTable::Ptr& connection_vtable, - // Exec helper for starting up prompt provider child processes with the correct setup - // of command line arguments and environment variables. - const mir::PromptProviderHelper::Ptr& exec_helper, - // A translator function for mapping child process exit states to trust::Request answers. - const std::function& translator) - : connection_vtable(connection_vtable), - exec_helper(exec_helper), - translator(translator) +mir::Agent::Agent(const mir::Agent::Configuration& config) + : config(config) { } // From core::trust::Agent: core::trust::Request::Answer mir::Agent::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) { - // We assume that the agent implementation runs under the same user id as - // the requesting app to prevent from cross-user attacks. - if (core::trust::Uid{::getuid()} != parameters.application.uid) throw std::logic_error - { - "mir::Agent::prompt_user_for_request: current user id does not match requesting app's user id" - }; - // We initialize our callback context with an invalid child-process for setup // purposes. Later on, once we have acquired a pre-authenticated fd for the // prompt provider, we exec the actual provider in a child process and replace the @@ -260,7 +237,7 @@ } scope { // We setup the prompt session and wire up to our own internal callback helper. - connection_vtable->create_prompt_session_sync( + config.connection_vtable->create_prompt_session_sync( parameters.application.pid, Agent::on_trust_session_changed_state, &cb_context) @@ -273,24 +250,25 @@ mir::PromptProviderHelper::InvocationArguments args { fd, - parameters.application.id, + config.app_info_resolver->resolve(parameters.application.id), parameters.description }; // Ask the helper to fire up the prompt provider. - cb_context.prompt_provider_process = exec_helper->exec_prompt_provider_with_arguments(args); + cb_context.prompt_provider_process = config.exec_helper->exec_prompt_provider_with_arguments(args); // And subsequently wait for it to finish. auto result = cb_context.prompt_provider_process.wait_for(core::posix::wait::Flags::untraced); - return translator(result); + return config.translator(result); } bool mir::operator==(const mir::PromptProviderHelper::InvocationArguments& lhs, const mir::PromptProviderHelper::InvocationArguments& rhs) { - return std::tie(lhs.application_id, lhs.description, lhs.fd) == std::tie(rhs.application_id, rhs.description, rhs.fd); + return std::tie(lhs.app_info, lhs.description, lhs.fd) == std::tie(rhs.app_info, rhs.description, rhs.fd); } #include "config.h" +#include "click_desktop_entry_app_info_resolver.h" MirConnection* mir::connect(const std::string& endpoint, const std::string& name) { @@ -318,13 +296,8 @@ } }; - return mir::Agent::Ptr - { - new mir::Agent - { - cvt, - pph, - mir::Agent::translator_only_accepting_exit_status_success() - } - }; + mir::AppInfoResolver::Ptr anr{new mir::ClickDesktopEntryAppInfoResolver{}}; + + mir::Agent::Configuration config{cvt, pph, mir::Agent::translator_only_accepting_exit_status_success(), anr}; + return mir::Agent::Ptr{new mir::Agent{config}}; } diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/agent.h trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/agent.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.h 2016-01-19 15:22:45.000000000 +0000 @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -37,6 +39,17 @@ { namespace mir { +// Info bundles information about an application. +struct AppInfo +{ + std::string icon; // The icon of the application. + std::string name; // The human-readable, localized name of the application. + std::string id; // The unique id of the application. +}; + +// operator== returns true iff lhs is exactly equal to rhs. +bool operator==(const AppInfo& lhs, const AppInfo& rhs); + // We wrap the Mir prompt session API into a struct to // ease with testing and mocking. class CORE_TRUST_DLL_PUBLIC PromptSessionVirtualTable @@ -129,8 +142,8 @@ // The pre-authenticated fd that the helper // should use for connecting to Mir. int fd; - // The application id of the requesting app. - std::string application_id; + // Application-specific information goes here. + AppInfo app_info; // The extended description that should be presented to the user. std::string description; }; @@ -146,6 +159,17 @@ CreationArguments creation_arguments; }; +// An AppNameResolver resolves an application id to a localized application name. +struct AppInfoResolver +{ + // Save us some typing. + typedef std::shared_ptr Ptr; + + virtual ~AppInfoResolver() = default; + // resolve maps app_id to a localized application name. + virtual AppInfo resolve(const std::string& app_id) = 0; +}; + // Implements the trust::Agent interface and dispatches calls to a helper // prompt provider, tying it together with the requesting service and app // by leveraging Mir's trusted session/prompting support. @@ -154,6 +178,20 @@ // Convenience typedef typedef std::shared_ptr Ptr; + // A Configuration bundles creation-time configuration options. + struct Configuration + { + // VTable object providing access to Mir's trusted prompting functionality. + ConnectionVirtualTable::Ptr connection_vtable; + // Exec helper for starting up prompt provider child processes with the correct setup + // of command line arguments and environment variables. + PromptProviderHelper::Ptr exec_helper; + // A translator function for mapping child process exit states to trust::Request answers. + std::function translator; + // AppNameResolver used by the agent to map incoming request app ids to application names. + AppInfoResolver::Ptr app_info_resolver; + }; + // Helper struct for injecting state into on_trust_changed_state_state callbacks. // Used in prompt_user_for_request to wait for the trust session to be stopped. struct OnTrustSessionStateChangedCallbackContext @@ -177,26 +215,16 @@ // Throws std::logic_error if the process did not exit but was signaled. static std::function translator_only_accepting_exit_status_success(); - // Creates a new MirAgent instance with the given MirConnectionVirtualTable instance. - Agent(// VTable object providing access to Mir's trusted prompting functionality. - const ConnectionVirtualTable::Ptr& connection_vtable, - // Exec helper for starting up prompt provider child processes with the correct setup - // of command line arguments and environment variables. - const PromptProviderHelper::Ptr& exec_helper, - // A translator function for mapping child process exit states to trust::Request answers. - const std::function& translator); + // Creates a new MirAgent instance with the given Configuration. + Agent(const Configuration& config); // From core::trust::Agent: // Throws a std::logic_error if anything unforeseen happens during execution, thus // indicating that no conclusive answer could be obtained from the user. core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; - // The connection VTable used for creating trusted prompting sessions. - ConnectionVirtualTable::Ptr connection_vtable; - // Execution helper for firing up prompt provider executables. - PromptProviderHelper::Ptr exec_helper; - // Translator instance. - std::function translator; + // The configured options. + Configuration config; }; CORE_TRUST_DLL_PUBLIC bool operator==(const PromptProviderHelper::InvocationArguments&, const PromptProviderHelper::InvocationArguments&); diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/click_desktop_entry_app_info_resolver.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/click_desktop_entry_app_info_resolver.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace env = core::posix::this_process::env; +namespace fs = boost::filesystem; +namespace mir = core::trust::mir; + +namespace +{ +fs::path resolve_desktop_entry_or_throw(const std::string& app_id) +{ + auto p = xdg::data().home() / "applications" / (app_id + ".desktop"); + if (fs::is_regular_file(p)) + return p; + + fs::path applications{xdg::data().home() / "applications"}; + fs::directory_iterator it(applications), itE; + while (it != itE) + { + if (it->path().filename().string().find(app_id) == 0) + return it->path(); + ++it; + } + + for (auto dir : xdg::data().dirs()) + { + auto p = dir / "applications" / (app_id + ".desktop"); + if (fs::is_regular_file(p)) + return p; + } + + throw std::runtime_error{"Could not resolve desktop entry for " + app_id}; +} + +// Wrap up a GError with an RAII approach, easing +// cleanup if we throw an exception. +struct Error +{ + ~Error() { clear(); } + void clear() { g_clear_error(&error); } + + GError* error = nullptr; +}; + +std::string name_from_desktop_entry_or_throw(const fs::path& fn) +{ + Error g; + std::shared_ptr key_file{g_key_file_new(), [](GKeyFile* file) { if (file) g_key_file_free(file); }}; + + if (not g_key_file_load_from_file(key_file.get(), fn.string().c_str(), G_KEY_FILE_NONE, &g.error)) throw std::runtime_error + { + "Failed to load desktop entry [" + std::string(g.error->message) + "]" + }; + + auto app_name = g_key_file_get_locale_string(key_file.get(), G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, nullptr, &g.error); + + if (g.error) throw std::runtime_error + { + "Failed to query localized name [" + std::string(g.error->message) + "]" + }; + + return app_name; +} + +std::string icon_from_desktop_entry_or_throw(const fs::path& fn) +{ + Error g; + std::shared_ptr key_file{g_key_file_new(), [](GKeyFile* file) { if (file) g_key_file_free(file); }}; + + if (not g_key_file_load_from_file(key_file.get(), fn.string().c_str(), G_KEY_FILE_NONE, &g.error)) throw std::runtime_error + { + "Failed to load desktop entry [" + std::string(g.error->message) + "]" + }; + + auto app_icon = g_key_file_get_locale_string(key_file.get(), G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, nullptr, &g.error); + + if (g.error) throw std::runtime_error + { + "Failed to query icon [" + std::string(g.error->message) + "]" + }; + + // We expect an absolute path to a regular file representing the icon. Ideally, we should + // also run further checks like the file not being part of another app for example. + fs::path p{app_icon}; + if (not p.is_absolute() || not fs::is_regular_file(fs::status(p))) throw std::runtime_error + { + "Icon path is either not absolute or not pointing to a regular file [" + std::string{app_icon} + "]" + }; + + return app_icon; +} +} + +mir::ClickDesktopEntryAppInfoResolver::ClickDesktopEntryAppInfoResolver() +{ +} + +mir::AppInfo mir::ClickDesktopEntryAppInfoResolver::resolve(const std::string& app_id) +{ + auto de = resolve_desktop_entry_or_throw(app_id); + return mir::AppInfo + { + icon_from_desktop_entry_or_throw(de), + name_from_desktop_entry_or_throw(de), + app_id + }; +} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/click_desktop_entry_app_info_resolver.h trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/click_desktop_entry_app_info_resolver.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.h 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#ifndef CORE_TRUST_MIR_CLICK_DESKTOP_ENTRY_APP_NAME_RESOLVER_H_ +#define CORE_TRUST_MIR_CLICK_DESKTOP_ENTRY_APP_NAME_RESOLVER_H_ + +#include + +namespace core +{ +namespace trust +{ +namespace mir +{ +// A ClickDesktopEntryAppNameResolver queries the click database of installed +// packages to resolve an app's installation folder in the local filesystem. +// The directory is searched for a .desktop file, that is then loaded and queried +// for the app's localized name. +class CORE_TRUST_DLL_PUBLIC ClickDesktopEntryAppInfoResolver : public AppInfoResolver +{ +public: + // ClickDesktopEntryAppNameResolver sets up an instance with default dbs. + ClickDesktopEntryAppInfoResolver(); + + // resolve queries the click index and an apps desktop file entry for + // obtaining a localized application name. Throws std::runtime_error in + // case of issues. + AppInfo resolve(const std::string& app_id) override; +}; +} +} +} + +#endif // CORE_TRUST_MIR_CLICK_DESKTOP_ENTRY_APP_NAME_RESOLVER_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.cpp 2015-08-31 15:11:23.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -74,27 +74,33 @@ { // We are throwing exceptions here, which immediately calls abort and still gives a // helpful error message on the terminal. - if (vm.count(cli::option_title) == 0) throw std::logic_error + if (vm.count(cli::option_icon) == 0) throw std::logic_error { - "Missing option title." + "Missing option icon." }; - if (vm.count(cli::option_description) == 0) throw std::logic_error + if (vm.count(cli::option_name) == 0) throw std::logic_error { - "Missing option description" + "Missing option name." }; - if (vm.count(cli::option_server_socket) == 0) throw std::logic_error + if (vm.count(cli::option_id) == 0) throw std::logic_error { - "Missing option mir_server_socket" + "Missing option id." }; - std::string mir_server_socket = vm[cli::option_server_socket].as(); - - if (mir_server_socket.find("fd://") != 0) throw std::logic_error + if (vm.count(cli::option_description) == 0) throw std::logic_error { - "mir_server_socket does not being with fd://" + "Missing option description" }; + + if (vm.count(cli::option_server_socket) > 0) + { + if (vm[cli::option_server_socket].as().find("fd://") != 0) throw std::logic_error + { + "mir_server_socket does not being with fd://" + }; + } } } } @@ -104,8 +110,10 @@ boost::program_options::options_description options; options.add_options() (cli::option_server_socket, boost::program_options::value(), "Mir server socket to connect to.") + (cli::option_icon, boost::program_options::value(), "Icon of the requesting application.") + (cli::option_name, boost::program_options::value(), "Name of the requesting application.") + (cli::option_id, boost::program_options::value(), "Id of the requesting application.") (cli::option_description, boost::program_options::value(), "Extended description of the prompt.") - (cli::option_title, boost::program_options::value(), "Title of the prompt.") (cli::option_testing, "Only checks command-line parameters and does not execute any actions.") (cli::option_testability, "Loads the Qt Testability plugin if provided."); @@ -124,30 +132,29 @@ boost::program_options::store(parsed_options, vm); boost::program_options::notify(vm); + // We immediately bail out if verification of command line arguments fails. + testing::validate_command_line_arguments(vm); + // We just verify command line arguments in testing and immediately return. if (vm.count(cli::option_testing) > 0) - { - testing::validate_command_line_arguments(vm); return 0; - } + return 0; - // Let's validate the arguments. - if (vm.count(cli::option_title) == 0) - abort(); // We have to call abort here to make sure that we get signalled. - - std::string title = vm[cli::option_title].as(); - - std::string description; - if (vm.count(cli::option_description) > 0) - description = vm[cli::option_description].as(); + auto icon = vm[cli::option_icon].as(); + auto name = vm[cli::option_name].as(); + auto id = vm[cli::option_id].as(); + // As per design, we replace "_" in app ids with a "/", thereby + // rendering the app id a little nicer. See: + // + // http://pasteboard.co/2qhB6op7.png + // + // for an example. + std::replace(id.begin(), id.end(), '_', '/'); + auto description = vm[cli::option_description].as(); if (vm.count(cli::option_server_socket) > 0) { - // We make sure that the env variable is not set prior to adusting it. this_env::unset_or_throw(env::option_mir_socket); - - this_env::set_or_throw( - env::option_mir_socket, - vm[cli::option_server_socket].as()); + this_env::set_or_throw(env::option_mir_socket, vm[cli::option_server_socket].as()); } // We install our default gettext domain prior to anything qt. @@ -202,14 +209,10 @@ view->setTitle(QGuiApplication::applicationName()); // Make some properties known to the root context. - // The title of the dialog. - view->rootContext()->setContextProperty( - cli::option_title, - title.c_str()); - // The description of the dialog. - view->rootContext()->setContextProperty( - cli::option_description, - description.c_str()); + view->rootContext()->setContextProperty(cli::option_icon, icon.c_str()); + view->rootContext()->setContextProperty(cli::option_name, name.c_str()); + view->rootContext()->setContextProperty(cli::option_id, id.c_str()); + view->rootContext()->setContextProperty(cli::option_description, description.c_str()); // Point the engine to the right directory. Please note that // the respective value changes with the installation state. diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.h trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.h 2016-01-19 15:22:45.000000000 +0000 @@ -46,10 +46,22 @@ "mir_server_socket" }; -/** @brief Title of the prompt. */ -static constexpr const char* option_title +/** @brief Icon of the requesting app. */ +static constexpr const char* option_icon { - "title" + "icon" +}; + +/** @brief Name of the requesting app. */ +static constexpr const char* option_name +{ + "name" +}; + +/** @brief Id of the requesting app. */ +static constexpr const char* option_id +{ + "id" }; /** @brief Extended description of the prompt. */ diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.qml trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.qml --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/mir/prompt_main.qml 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.qml 2016-01-19 15:22:45.000000000 +0000 @@ -15,40 +15,76 @@ */ import QtQuick 2.0 -import Ubuntu.Components 1.1 -import Ubuntu.Components.Popups 1.0 +import Ubuntu.Components 1.3 +import Ubuntu.Components.Popups 1.3 -Rectangle { - width: units.gu(40) - height: units.gu(71) - color: "transparent" +Item { - property var dialogTitle: title - property var dialogDescription: description + property var appIcon: icon + property var appName: name + property var appId: id + property var serviceDescription: description signal quit(int code) - Component.onCompleted: dialog.show(); - - Dialog { + Component { id: dialog - - title: dialogTitle - text: dialogDescription - fadingAnimation: PropertyAnimation { duration: 0 } - - Button { - objectName: "deny" - text: i18n.tr("Deny") - color: UbuntuColors.red - onClicked: quit(1) - } - - Button { - objectName: "allow" - text: i18n.tr("Allow") - color: UbuntuColors.green - onClicked: quit(0) + Dialog { + id: dialogue + Column { + spacing: units.gu(0.5) + UbuntuShape { + anchors.horizontalCenter: parent.horizontalCenter + id: iconShape + radius: "medium" + aspect: UbuntuShape.DropShadow + anchors.margins: units.gu(1) + sourceFillMode: UbuntuShape.PreserveAspectCrop + source: Image { + id: icon + sourceSize.width: iconShape.width + sourceSize.height: iconShape.height + source: appIcon + } + } + Label { + anchors.horizontalCenter: parent.horizontalCenter + text: appName + horizontalAlignment: Text.AlignHCenter + width: parent.width + elide: Text.ElideRight + wrapMode: Text.Wrap + maximumLineCount: 2 + } + Label { + anchors.horizontalCenter: parent.horizontalCenter + text: appId + color: UbuntuColors.lightGrey + fontSize: "small" + width: parent.width + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideMiddle + maximumLineCount: 1 + } + } + Label { + anchors.horizontalCenter: parent.horizontalCenter + text: serviceDescription + horizontalAlignment: Text.AlignHCenter + width: parent.width + wrapMode: Text.Wrap + } + Button { + text: i18n.tr("Allow") + color: UbuntuColors.green + onClicked: quit(0) + } + Button { + text: i18n.tr("Don’t Allow") + color: UbuntuColors.lightGrey + onClicked: quit(1) + } } } + Component.onCompleted: PopupUtils.open(dialog) } diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/privilege_escalation_prevention_agent.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/privilege_escalation_prevention_agent.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +#include +#include + +core::trust::PrivilegeEscalationPreventionAgent::Error::Error() : std::runtime_error{"Potential privilege escalation attack detected."} +{ +} + +core::trust::PrivilegeEscalationPreventionAgent::UserIdFunctor core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor() +{ + return []() + { + return core::trust::Uid{::getuid()}; + }; +} + +core::trust::PrivilegeEscalationPreventionAgent::PrivilegeEscalationPreventionAgent( + const UserIdFunctor& uid_functor, + const std::shared_ptr& impl) + : uid_functor{uid_functor}, + impl{impl} +{ + if (not impl) throw std::runtime_error + { + "Missing agent implementation." + }; +} + +core::trust::Request::Answer core::trust::PrivilegeEscalationPreventionAgent::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) +{ + if (uid_functor() != parameters.application.uid) throw Error{}; + return impl->authenticate_request_with_parameters(parameters); +} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/privilege_escalation_prevention_agent.h trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/privilege_escalation_prevention_agent.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.h 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#ifndef CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_ +#define CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_ + +#include + +#include + +namespace core +{ +namespace trust +{ +// A PrivilegeEscalationPreventionAgent ensures that requests originating from an application +// running under a different user than the current one are rejected immediately, thereby preventing +// from privilege escalation issues. +class CORE_TRUST_DLL_PUBLIC PrivilegeEscalationPreventionAgent : public core::trust::Agent +{ +public: + // An Error is thrown if a potential privilege escalation attack has been detected. + struct Error : public std::runtime_error + { + // Error creates an instance, providing details about the escalation issue. + Error(); + }; + + // A UserIdFunctor queries the user id under which the current process runs. + typedef std::function UserIdFunctor; + + // default_user_id_functor returns a UserIdFunctor querying the current user id from the system. + static UserIdFunctor default_user_id_functor(); + + // PrivilegeEscalationPreventionAgent creates a new instance that queries the current user, + // forwarding valid requests to impl. + PrivilegeEscalationPreventionAgent(const UserIdFunctor& uid_functor, const std::shared_ptr& impl); + + // From core::trust::Agent + Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; + +private: + UserIdFunctor uid_functor; + std::shared_ptr impl; +}; +} +} + +#endif // CORE_TRUST_PRIVILEGE_ESCALATION_PREVENTION_AGENT_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/remote/dbus.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/remote/dbus.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -19,6 +19,7 @@ #include #include +#include core::trust::remote::dbus::Agent::Stub::Stub(const core::trust::remote::dbus::Agent::Stub::Configuration& configuration) : agent_registry_skeleton @@ -43,20 +44,34 @@ return agent->authenticate_request_with_parameters(parameters); } -core::trust::remote::dbus::Agent::Skeleton::Skeleton(const core::trust::remote::dbus::Agent::Skeleton::Configuration& configuration) +core::trust::remote::dbus::Agent::Skeleton::Skeleton(core::trust::remote::dbus::Agent::Skeleton::Configuration configuration) : core::trust::remote::Agent::Skeleton{configuration.impl}, + config(std::move(configuration)), agent_registry_stub { core::trust::dbus::AgentRegistry::Stub::Configuration { - configuration.agent_registry_object, + config.agent_registry_object, core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(), - configuration.service, - configuration.bus + config.service, + config.bus } } { - agent_registry_stub.register_agent_for_user(core::trust::Uid{::getuid()}, configuration.impl); + agent_registry_stub.register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, []() + { + std::cout << "Error registering agent for user." << std::endl; + }); + + // We don't have to track the lifetime of "this" as config.agent_registry_watcher is owned + // by "this". + config.agent_registry_watcher->service_registered().connect([this]() + { + agent_registry_stub.register_agent_for_user_async(core::trust::Uid{::getuid()}, config.impl, []() + { + std::cout << "Error registering agent for user." << std::endl; + }); + }); } core::trust::Request::Answer core::trust::remote::dbus::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/remote/dbus.h trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/remote/dbus.h 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.h 2016-01-19 15:22:50.000000000 +0000 @@ -25,6 +25,8 @@ #include #include +#include + #include #include @@ -86,6 +88,8 @@ std::shared_ptr impl; // The remote object implementing core.trust.dbus.AgentRegistry. core::dbus::Object::Ptr agent_registry_object; + // The watcher monitoring the remote object implementing core.trust.dbus.AgentRegistry. + std::unique_ptr agent_registry_watcher; // The service that objects implementing core.trust.dbus.Agent should be added to. core::dbus::Service::Ptr service; // The underlying bus instance. @@ -95,11 +99,13 @@ }; // Constructs a new Skeleton instance, installing impl for handling actual requests. - Skeleton(const Configuration& configuration); + Skeleton(Configuration configuration); // From core::trust::Agent, dispatches to the actual implementation. core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters); + // Store all creation-time parameters. + Configuration config; // Stub for accessing the remote agent registry. core::trust::dbus::AgentRegistry::Stub agent_registry_stub; }; diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/runtime.cpp trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.cpp --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/runtime.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * Copyright © 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +#include + +#include +#include + +namespace +{ +void execute_and_never_throw(boost::asio::io_service& ios) noexcept(true) +{ + while (true) + { + try + { + ios.run(); + break; + } + catch (const std::exception& e) + { + std::cerr << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; + } + catch (...) + { + std::cerr << __PRETTY_FUNCTION__ << ": unknown exception" << std::endl; + } + } +} +} + +core::trust::Runtime& core::trust::Runtime::instance() +{ + static Runtime runtime; + return runtime; +} + +core::trust::Runtime::Runtime() + : signal_trap{core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term, core::posix::Signal::sig_int})}, + keep_alive{io_service} +{ + for (std::size_t i = 0; i < Runtime::concurrency_hint; i++) + { + pool.emplace_back(execute_and_never_throw, std::ref(io_service)); + } + + signal_trap->signal_raised().connect([this](const core::posix::Signal&) + { + stop(); + }); +} + +core::trust::Runtime::~Runtime() +{ + io_service.stop(); + + for (auto& worker : pool) + if (worker.joinable()) + worker.join(); +} + +void core::trust::Runtime::run() +{ + signal_trap->run(); +} + +void core::trust::Runtime::stop() +{ + signal_trap->stop(); +} + +boost::asio::io_service& core::trust::Runtime::service() +{ + return io_service; +} + +core::dbus::Executor::Ptr core::trust::Runtime::make_executor_for_bus(const core::dbus::Bus::Ptr& bus) +{ + return core::dbus::asio::make_executor(bus, io_service); +} diff -Nru trust-store-2.0.0+15.10.20150831.3/src/core/trust/runtime.h trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.h --- trust-store-2.0.0+15.10.20150831.3/src/core/trust/runtime.h 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.h 2016-01-19 15:22:50.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * Copyright © 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#ifndef CORE_TRUST_RUNTIME_H_ +#define CORE_TRUST_RUNTIME_H_ + +#include + +#include +#include + +#include + +#include +#include +#include + +namespace core +{ +namespace trust +{ +// A Runtime maintains a pool of workers enabling +// implementations to dispatch invocations and have their +// ready handlers automatically executed. +class Runtime +{ +public: + // Do not execute in parallel, serialize + // accesses. + static constexpr std::size_t concurrency_hint{2}; + + // Our evil singleton pattern. Not bad though, we control the + // entire executable and rely on automatic cleanup of static + // instances. + static Runtime& instance(); + + Runtime(); + + // Gracefully shuts down operations. + ~Runtime() noexcept(true); + + + // run blocks until either stop is called or a + // signal requesting graceful shutdown is received. + void run(); + + // requests the runtime to shut down, does not block. + void stop(); + + // Returns a mutable reference to the underlying boost::asio::io_service + // powering the runtime's reactor. + boost::asio::io_service& service(); + + // Creates an executor for a bus instance hooking into this Runtime instance. + core::dbus::Executor::Ptr make_executor_for_bus(const core::dbus::Bus::Ptr& bus); + +private: + // We trap sig term to ensure a clean shutdown. + std::shared_ptr signal_trap; + + // Our io_service instance exposed to remote agents. + boost::asio::io_service io_service; + + // We keep the io_service alive and introduce some artificial + // work. + boost::asio::io_service::work keep_alive; + + // We execute the io_service on a pool of worker threads. + std::vector pool; +}; +} +} + +#endif // CORE_TRUST_RUNTIME_H_ diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/click_desktop_entry_app_name_resolver_test.cpp trust-store-2.0.0+16.04.20160119/tests/click_desktop_entry_app_name_resolver_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/click_desktop_entry_app_name_resolver_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/click_desktop_entry_app_name_resolver_test.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright © 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include +#include +#include "test_data.h" + +#include + +#include + +namespace env = core::posix::this_process::env; +namespace mir = core::trust::mir; + +namespace +{ +bool ensure_icon_file() +{ + std::ofstream out{"/tmp/test.icon"}; + out << "test.icon"; + return out.good(); +} +} + +TEST(ClickDesktopEntryAppInfoResolver, throws_for_invalid_app_id) +{ + ASSERT_TRUE(ensure_icon_file()); + mir::ClickDesktopEntryAppInfoResolver resolver; + EXPECT_THROW(resolver.resolve("something:not:right"), std::runtime_error); +} + +TEST(ClickDesktopEntryAppInfoResolver, resolves_existing_desktop_entry_from_xdg_data_home) +{ + ASSERT_TRUE(ensure_icon_file()); + env::unset_or_throw("XDG_DATA_HOME"); + env::set_or_throw("XDG_DATA_HOME", core::trust::testing::current_source_dir + std::string("/share")); + mir::ClickDesktopEntryAppInfoResolver resolver; + EXPECT_NO_THROW(resolver.resolve("valid.pkg_app_0.0.0")); +} + +TEST(ClickDesktopEntryAppInfoResolver, robustly_resolves_existing_desktop_entry_from_xdg_data_home) +{ + ASSERT_TRUE(ensure_icon_file()); + env::unset_or_throw("XDG_DATA_HOME"); + env::set_or_throw("XDG_DATA_HOME", core::trust::testing::current_source_dir + std::string("/share")); + + mir::ClickDesktopEntryAppInfoResolver resolver; + EXPECT_NO_THROW(resolver.resolve("valid.pkg_app")); +} + +TEST(ClickDesktopEntryAppInfoResolver, resolves_existing_desktop_entry_from_xdg_data_dirs) +{ + ASSERT_TRUE(ensure_icon_file()); + env::unset_or_throw("XDG_DATA_HOME"); env::unset_or_throw("XDG_DATA_DIRS"); + env::set_or_throw("XDG_DATA_HOME", core::trust::testing::current_source_dir + std::string("/empty")); + env::set_or_throw("XDG_DATA_DIRS", core::trust::testing::current_source_dir + std::string("/share")); + + mir::ClickDesktopEntryAppInfoResolver resolver; + resolver.resolve("valid.pkg_app_0.0.0"); +} diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/CMakeLists.txt trust-store-2.0.0+16.04.20160119/tests/CMakeLists.txt --- trust-store-2.0.0+15.10.20150831.3/tests/CMakeLists.txt 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/CMakeLists.txt 2016-01-19 15:22:50.000000000 +0000 @@ -46,6 +46,9 @@ add_executable( remote_agent_test remote_agent_test.cpp + + ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.h + ${CMAKE_SOURCE_DIR}/src/core/trust/runtime.cpp ) add_executable( @@ -59,6 +62,11 @@ ) add_executable( + privilege_escalation_prevention_agent_test + privilege_escalation_prevention_agent_test.cpp +) + +add_executable( cached_agent_test cached_agent_test.cpp ) @@ -166,6 +174,20 @@ ) target_link_libraries( + privilege_escalation_prevention_agent_test + + trust-store + + gmock + + gtest + gtest_main + + ${PROCESS_CPP_LIBRARIES} +) + + +target_link_libraries( cached_agent_test trust-store @@ -196,6 +218,7 @@ dbus_test trust-store + trust-stored gmock @@ -226,6 +249,7 @@ add_test(app_id_formatting_trust_agent_test ${CMAKE_CURRENT_BINARY_DIR}/app_id_formatting_trust_agent_test) add_test(cached_agent_test ${CMAKE_CURRENT_BINARY_DIR}/cached_agent_test) add_test(white_listing_agent_test ${CMAKE_CURRENT_BINARY_DIR}/white_listing_agent_test) +add_test(privilege_escalation_prevention_agent_test ${CMAKE_CURRENT_BINARY_DIR}/privilege_escalation_prevention_agent_test) # TODO(tvoss) Re-enable daemon tests once CI issues are resolved. # add_test(daemon_test ${CMAKE_CURRENT_BINARY_DIR}/daemon_test) add_test(dbus_test ${CMAKE_CURRENT_BINARY_DIR}/dbus_test) @@ -242,10 +266,16 @@ mir_agent_test.cpp ) + add_executable( + click_desktop_entry_app_name_resolver_test + click_desktop_entry_app_name_resolver_test.cpp + ) + target_link_libraries( mir_agent_test trust-store + xdg gmock @@ -255,7 +285,22 @@ ${PROCESS_CPP_LIBRARIES} ) + target_link_libraries( + click_desktop_entry_app_name_resolver_test + + trust-store + + gmock + + gtest + gtest_main + + ${PROCESS_CPP_LIBRARIES} + ) + + add_test(mir_agent_test ${CMAKE_CURRENT_BINARY_DIR}/mir_agent_test --gtest_filter=*-*requires_mir) + add_test(click_desktop_entry_app_name_resolver_test ${CMAKE_CURRENT_BINARY_DIR}/click_desktop_entry_app_name_resolver_test) install( TARGETS mir_agent_test diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/dbus_test.cpp trust-store-2.0.0+16.04.20160119/tests/dbus_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/dbus_test.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/dbus_test.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -16,10 +16,14 @@ * Authored by: Thomas Voß */ +#include +#include + #include #include #include "mock_agent.h" +#include "process_exited_successfully.h" #include #include @@ -44,6 +48,10 @@ return trap; } +struct BusFactoryType : public testing::TestWithParam> +{ +}; + struct DBusAgent : public core::dbus::testing::Fixture { static constexpr const char* agent_service_name @@ -90,6 +98,76 @@ } +TEST_P(BusFactoryType, stream_insertion_operator_works) +{ + core::trust::dbus::BusFactory::Type t{GetParam().first}; + std::stringstream ss; ss << t; + EXPECT_EQ(GetParam().second, ss.str()); +} + +TEST_P(BusFactoryType, stream_extraction_operator_works) +{ + core::trust::dbus::BusFactory::Type t; + std::stringstream ss{GetParam().second}; ss >> t; + EXPECT_EQ(GetParam().first, t); +} + +INSTANTIATE_TEST_CASE_P(BusFactoryType, BusFactoryType, testing::Values( + std::make_pair(core::trust::dbus::BusFactory::Type::session, "session"), + std::make_pair(core::trust::dbus::BusFactory::Type::system, "system"), + std::make_pair(core::trust::dbus::BusFactory::Type::session_with_address_from_env, "session_with_address_from_env"), + std::make_pair(core::trust::dbus::BusFactory::Type::system_with_address_from_env, "system_with_address_from_env"))); + +TEST_F(DBusAgent, public_api_with_daemon_works) +{ + using namespace ::testing; + + core::testing::CrossProcessSync cps; + + auto daemon = core::posix::fork([this]() + { + const char* argv[] = + { + __PRETTY_FUNCTION__, + "--remote-agent", "SessionServiceDBusRemoteAgent", + "--bus=session_with_address_from_env", + "--local-agent", "TheAlwaysDenyingLocalAgent", + "--for-service", "TestService", + "--store-bus", "session_with_address_from_env" + }; + + auto conf = core::trust::Daemon::Skeleton::Configuration::from_command_line(10, argv); + return core::trust::Daemon::Skeleton::main(conf); + + return core::posix::exit::Status::failure; + }, core::posix::StandardStream::empty); + + std::this_thread::sleep_for(std::chrono::seconds{1}); + + for (std::size_t i = 0; i < 15; i++) + { + auto stub = core::posix::fork([this]() + { + auto bus = session_bus(); + bus->install_executor(core::dbus::asio::make_executor(bus, core::trust::Runtime::instance().service())); + + auto agent = core::trust::dbus::create_per_user_agent_for_bus_connection(bus, "TestService"); + + for (unsigned int i = 0; i < 1000; i++) + EXPECT_EQ(core::trust::Request::Answer::denied, agent->authenticate_request_with_parameters(ref_params)); + + return ::testing::Test::HasFailure() ? + core::posix::exit::Status::failure : + core::posix::exit::Status::success; + }, core::posix::StandardStream::empty); + + EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); + } + + daemon.send_signal_or_throw(core::posix::Signal::sig_term); + EXPECT_TRUE(ProcessExitedSuccessfully(daemon.wait_for(core::posix::wait::Flags::untraced))); +} + TEST_F(DBusAgent, remote_invocation_works_correctly) { using namespace ::testing; diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/mir_agent_test.cpp trust-store-2.0.0+16.04.20160119/tests/mir_agent_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/mir_agent_test.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/mir_agent_test.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -99,6 +99,11 @@ MOCK_METHOD1(translate, core::trust::Request::Answer(const core::posix::wait::Result&)); }; +struct MockAppInfoResolver : public core::trust::mir::AppInfoResolver +{ + MOCK_METHOD1(resolve, core::trust::mir::AppInfo(const std::string&)); +}; + std::shared_ptr a_mocked_connection_vtable() { return std::make_shared>(); @@ -117,6 +122,11 @@ "/bin/false" }); } + +std::shared_ptr a_mocked_app_info_resolver() +{ + return std::make_shared(); +} } TEST(DefaultProcessStateTranslator, throws_for_signalled_process) @@ -172,7 +182,11 @@ core::trust::mir::PromptProviderHelper::InvocationArguments iargs { 42, - "does.not.exist.application", + { + "/tmp", + "Does not exist", + "does.not.exist.application" + }, "Just an extended description for %1%" }; @@ -193,6 +207,8 @@ using namespace ::testing; const core::trust::Pid app_pid {21}; + const std::string app_icon{"/tmp"}; + const std::string app_name {"Does not exist"}; const std::string app_id {"does.not.exist.application"}; const core::trust::Feature feature{42}; const std::string app_description {"This is just an extended description %1%"}; @@ -201,7 +217,11 @@ const core::trust::mir::PromptProviderHelper::InvocationArguments reference_invocation_args { pre_authenticated_fd, - app_id, + { + app_icon, + app_name, + app_id + }, app_description }; @@ -209,6 +229,7 @@ auto prompt_session_vtable = a_mocked_prompt_session_vtable(); auto prompt_provider_exec_helper = a_mocked_prompt_provider_calling_bin_false(); + auto app_info_resolver = a_mocked_app_info_resolver(); ON_CALL(*connection_vtable, create_prompt_session_sync(_, _, _)) .WillByDefault(Return(prompt_session_vtable)); @@ -219,6 +240,9 @@ ON_CALL(*prompt_session_vtable, add_prompt_provider_sync(_)) .WillByDefault(Return(true)); + ON_CALL(*app_info_resolver, resolve(_)) + .WillByDefault(Return(core::trust::mir::AppInfo{app_icon, app_name, app_id})); + EXPECT_CALL(*connection_vtable, create_prompt_session_sync(app_pid, _, _)).Times(1); EXPECT_CALL(*prompt_session_vtable, new_fd_for_prompt_provider()).Times(1); @@ -228,9 +252,13 @@ core::trust::mir::Agent agent { - connection_vtable, - prompt_provider_exec_helper, - core::trust::mir::Agent::translator_only_accepting_exit_status_success() + core::trust::mir::Agent::Configuration + { + connection_vtable, + prompt_provider_exec_helper, + core::trust::mir::Agent::translator_only_accepting_exit_status_success(), + app_info_resolver + } }; EXPECT_EQ(core::trust::Request::Answer::denied, // /bin/false exits with failure. @@ -245,11 +273,82 @@ })); } +TEST(MirAgent, calls_into_app_info_resolver_with_app_id) +{ + using namespace ::testing; + + const core::trust::Pid app_pid {21}; + const std::string app_id {"does.not.exist.application"}; + const std::string app_icon{"/tmp"}; + const std::string app_name{"MeMyselfAndI"}; + const core::trust::Feature feature{42}; + const std::string app_description {"This is just an extended description for %1%"}; + const int pre_authenticated_fd {42}; + + const core::trust::mir::PromptProviderHelper::InvocationArguments reference_invocation_args + { + pre_authenticated_fd, + { + app_icon, + app_name, + app_id + }, + app_description + }; + + auto connection_vtable = a_mocked_connection_vtable(); + auto prompt_session_vtable = a_mocked_prompt_session_vtable(); + + auto prompt_provider_exec_helper = a_mocked_prompt_provider_calling_bin_false(); + auto app_info_resolver = a_mocked_app_info_resolver(); + + ON_CALL(*connection_vtable, create_prompt_session_sync(_, _, _)) + .WillByDefault(Return(prompt_session_vtable)); + + ON_CALL(*prompt_session_vtable, new_fd_for_prompt_provider()) + .WillByDefault(Return(pre_authenticated_fd)); + + ON_CALL(*prompt_session_vtable, add_prompt_provider_sync(_)) + .WillByDefault(Return(true)); + + EXPECT_CALL(*app_info_resolver, resolve(app_id)).Times(1) + .WillRepeatedly( + Return(core::trust::mir::AppInfo{app_icon, app_name, app_id})); + EXPECT_CALL(*prompt_provider_exec_helper, + exec_prompt_provider_with_arguments( + reference_invocation_args)).Times(1); + + core::trust::mir::Agent agent + { + core::trust::mir::Agent::Configuration + { + connection_vtable, + prompt_provider_exec_helper, + core::trust::mir::Agent::translator_only_accepting_exit_status_success(), + app_info_resolver + } + }; + + EXPECT_EQ(core::trust::Request::Answer::denied, // /bin/false exits with failure. + agent.authenticate_request_with_parameters( + core::trust::Agent::RequestParameters + { + core::trust::Uid{::getuid()}, + app_pid, + app_id, + feature, + app_description + })); + +} + TEST(MirAgent, sig_kills_prompt_provider_process_on_status_change) { using namespace ::testing; const core::trust::Pid app_pid {21}; + const std::string app_icon{"/tmp"}; + const std::string app_name{"MeMyselfAndI"}; const std::string app_id {"does.not.exist.application"}; const core::trust::Feature feature{42}; const std::string app_description {"This is just an extended description for %1%"}; @@ -270,6 +369,8 @@ auto prompt_provider_helper = std::make_shared( core::trust::mir::PromptProviderHelper::CreationArguments{"/bin/false"}); + auto app_info_resolver = a_mocked_app_info_resolver(); + void* prompt_session_state_callback_context{nullptr}; ON_CALL(*prompt_provider_helper, exec_prompt_provider_with_arguments(_)) @@ -289,6 +390,9 @@ Return( true)); + ON_CALL(*app_info_resolver, resolve(_)) + .WillByDefault(Return(core::trust::mir::AppInfo{app_icon, app_name, app_id})); + // An invocation results in a session being created. In addition, // we store pointers to callback and context provided by the implementation // for being able to later trigger the callback. @@ -300,9 +404,13 @@ core::trust::mir::Agent agent { - connection_vtable, - prompt_provider_helper, - core::trust::mir::Agent::translator_only_accepting_exit_status_success() + core::trust::mir::Agent::Configuration + { + connection_vtable, + prompt_provider_helper, + core::trust::mir::Agent::translator_only_accepting_exit_status_success(), + app_info_resolver + } }; std::thread asynchronously_stop_the_prompting_session @@ -368,6 +476,8 @@ #include #include +#include + namespace { std::map a_copy_of_the_env() @@ -383,15 +493,25 @@ std::string mir_socket() { // We either take the XDG_RUNTIME_DIR or fall back to /tmp if XDG_RUNTIME_DIR is not set. - std::string dir = core::posix::this_process::env::get("XDG_RUNTIME_DIR", "/tmp"); - return dir + "/mir_socket"; + try + { + return xdg::runtime().dir().string() + "/mir_socket"; + } catch(...) + { + return "/tmp/mir_socket"; + } } std::string trusted_mir_socket() { // We either take the XDG_RUNTIME_DIR or fall back to /tmp if XDG_RUNTIME_DIR is not set. - std::string dir = core::posix::this_process::env::get("XDG_RUNTIME_DIR", "/tmp"); - return dir + "/mir_socket_trusted"; + try + { + return xdg::runtime().dir().string() + "/mir_socket_trusted"; + } catch(...) + { + return "/tmp/mir_socket_trusted"; + } } } @@ -404,7 +524,9 @@ std::vector argv { "--" + std::string{core::trust::mir::cli::option_server_socket} + "=" + mir_socket(), - "--" + std::string{core::trust::mir::cli::option_title} + "=" + pretty_function, + "--" + std::string{core::trust::mir::cli::option_icon}, pretty_function, + "--" + std::string{core::trust::mir::cli::option_name}, pretty_function, + "--" + std::string{core::trust::mir::cli::option_id}, pretty_function, "--" + std::string{core::trust::mir::cli::option_description} + "=" + pretty_function, // We have to circumvent unity8's authentication mechanism and just provide // the desktop_file_hint as part of the command line. diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/privilege_escalation_prevention_agent_test.cpp trust-store-2.0.0+16.04.20160119/tests/privilege_escalation_prevention_agent_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/privilege_escalation_prevention_agent_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/privilege_escalation_prevention_agent_test.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +#include "mock_agent.h" +#include "the.h" + +#include + +namespace +{ +std::shared_ptr> a_mocked_agent() +{ + return std::make_shared>(); +} + +struct MockUserIdFunctor +{ + core::trust::PrivilegeEscalationPreventionAgent::UserIdFunctor to_functional() + { + return [this]() + { + return get_uid(); + }; + } + + MOCK_METHOD0(get_uid, core::trust::Uid()); +}; +} + +TEST(PrivilegeEscalationPreventionAgent, ctor_throws_for_null_agent) +{ + EXPECT_ANY_THROW(core::trust::PrivilegeEscalationPreventionAgent + ( + core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor(), + std::shared_ptr() + )); +} + +TEST(PrivilegeEscalationPreventionAgent, queries_user_id_for_incoming_request_and_dispatches_to_impl_if_no_privilege_escalation_detected) +{ + using namespace ::testing; + + auto mock_agent = a_mocked_agent(); + + auto params = the::default_request_parameters_for_testing(); + params.application.id = params.application.id + std::string{"_app"} + std::string{"_1.2.3"}; + + MockUserIdFunctor uif; + EXPECT_CALL(uif, get_uid()) + .Times(1) + .WillRepeatedly(Return(params.application.uid)); + + EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params)) + .Times(1) + .WillRepeatedly(Return(core::trust::Request::Answer::denied)); + + core::trust::PrivilegeEscalationPreventionAgent agent{uif.to_functional(), mock_agent}; + + EXPECT_EQ(core::trust::Request::Answer::denied, + agent.authenticate_request_with_parameters(params)); +} + +TEST(PrivilegeEscalationPreventionAgent, invokes_user_id_functor_for_incoming_request_and_throws_if_privilege_escalation_detected) +{ + using namespace ::testing; + + auto mock_agent = a_mocked_agent(); + + auto params = the::default_request_parameters_for_testing(); + params.application.id = params.application.id + std::string{"_app"} + std::string{"_1.2.3"}; + + MockUserIdFunctor uif; + EXPECT_CALL(uif, get_uid()) + .Times(1) + .WillRepeatedly(Return(core::trust::Uid{12})); + + EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params)) + .Times(0); + + core::trust::PrivilegeEscalationPreventionAgent agent{uif.to_functional(), mock_agent}; + + EXPECT_THROW(agent.authenticate_request_with_parameters(params), core::trust::PrivilegeEscalationPreventionAgent::Error); +} + +TEST(PrivilegeEscalationPreventionAgentDefaultUserIdFunctor, returns_current_user_id) +{ + auto f = core::trust::PrivilegeEscalationPreventionAgent::default_user_id_functor(); + EXPECT_EQ(core::trust::Uid(::getuid()), f()); +} diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/remote_agent_test.cpp trust-store-2.0.0+16.04.20160119/tests/remote_agent_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/remote_agent_test.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/remote_agent_test.cpp 2016-01-19 15:22:50.000000000 +0000 @@ -381,6 +381,10 @@ cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); + // We have to provide some grace to the service, such that it can spin up threads + // and handle incoming connections. This is specifically required to satisfy slow builders. + std::this_thread::sleep_for(std::chrono::seconds{1}); + EXPECT_CALL(process_start_time_resolver, resolve_process_start_time(_)) .Times(2) .WillRepeatedly(Return(42)); @@ -860,6 +864,8 @@ stub_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); skeleton_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000}); + std::this_thread::sleep_for(std::chrono::seconds{1}); + for (unsigned int i = 0; i < 100; i++) EXPECT_EQ(answer, stub->authenticate_request_with_parameters(ref_params)); @@ -893,6 +899,8 @@ ON_CALL(*mock_agent, authenticate_request_with_parameters(_)) .WillByDefault(Return(answer)); + Mock::AllowLeak(mock_agent.get()); + std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name; stub_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000}); @@ -903,16 +911,19 @@ core::trust::remote::dbus::default_agent_registry_path }); + core::dbus::DBus daemon{bus}; + core::trust::remote::dbus::Agent::Skeleton::Configuration config { mock_agent, object, + daemon.make_service_watcher(dbus_service_name), service, bus, core::trust::remote::helpers::aa_get_task_con_app_id_resolver() }; - auto skeleton = std::make_shared(config); + auto skeleton = std::make_shared(std::move(config)); skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/share/applications/valid.pkg_app_0.0.0.desktop trust-store-2.0.0+16.04.20160119/tests/share/applications/valid.pkg_app_0.0.0.desktop --- trust-store-2.0.0+15.10.20150831.3/tests/share/applications/valid.pkg_app_0.0.0.desktop 1970-01-01 00:00:00.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/share/applications/valid.pkg_app_0.0.0.desktop 2016-01-19 15:22:45.000000000 +0000 @@ -0,0 +1,56 @@ +[Desktop Entry] +Type=Application +Icon=/tmp/test.icon +Name=Camera +Name[am]=ካሜራ +Name[ar]=الكاميرا +Name[ast]=Cámara +Name[az]=Kamera +Name[bg]=Камера +Name[br]=Kamera +Name[bs]=Kamera +Name[ca]=Càmera +Name[ca@valencia]=Càmera +Name[cs]=Fotoaparát +Name[cy]=Camera +Name[da]=Kamera +Name[de]=Kamera +Name[el]=Κάμερα +Name[en_AU]=Camera +Name[en_GB]=Camera +Name[es]=Cámara +Name[eu]=Kamera +Name[fa]=دوربین +Name[fi]=Kamera +Name[fr]=Appareil photo +Name[gd]=Camara +Name[gl]=Cámara +Name[he]=מצלמה +Name[hi]=कैमरा +Name[hr]=Fotoaparat +Name[hu]=Kamera +Name[hy]=Կամերա +Name[is]=Myndavél +Name[it]=Fotocamera +Name[ja]=カメラ +Name[km]=ម៉ាស៊ីនត +Name[ko]=카메라 +Name[lo]=ກ້ອງ +Name[lv]=Fotokamera +Name[ml]=ക്യാമറ +Name[ms]=Kamera +Name[my]=ကငမရာ +Name[nb]=Kamera +Name[nl]=Camera +Name[pa]=ਕੈਮਰਾ +Name[pl]=Aparat +Name[pt]=Câmara +Name[pt_BR]=Câmera +Name[ro]=Aparat foto +Name[ru]=Камера +Name[sl]=Fotoaparat +Name[sr]=Камера +Name[sv]=Kamera +Name[ta]=புகைப்பட கருவி +Name[te]=కెమేరా +Name[tr]=Fotoğraf Makinesi diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/test_data.h.in trust-store-2.0.0+16.04.20160119/tests/test_data.h.in --- trust-store-2.0.0+15.10.20150831.3/tests/test_data.h.in 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/test_data.h.in 2016-01-19 15:22:45.000000000 +0000 @@ -25,6 +25,11 @@ { namespace testing { +static constexpr const char* current_source_dir +{ + "@CMAKE_CURRENT_SOURCE_DIR@" +}; + static constexpr const char* trust_prompt_executable_in_build_dir { "@CMAKE_BINARY_DIR@/src/trust-prompt" diff -Nru trust-store-2.0.0+15.10.20150831.3/tests/trust_store_test.cpp trust-store-2.0.0+16.04.20160119/tests/trust_store_test.cpp --- trust-store-2.0.0+15.10.20150831.3/tests/trust_store_test.cpp 2015-08-31 15:11:19.000000000 +0000 +++ trust-store-2.0.0+16.04.20160119/tests/trust_store_test.cpp 2016-01-19 15:22:45.000000000 +0000 @@ -18,6 +18,9 @@ #include +#include + +#include #include #include @@ -396,3 +399,50 @@ query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } + +#include +namespace +{ +struct MockXdgData: public xdg::Data +{ + MOCK_CONST_METHOD0(home, boost::filesystem::path()); + MOCK_CONST_METHOD0(dirs, std::vector()); +}; + +struct MockXdgBaseDirSpec : public xdg::BaseDirSpecification +{ + const xdg::Data& data() const override + { + return data_; + } + + const xdg::Config& config() const override + { + return config_; + } + + const xdg::Cache& cache() const override + { + return cache_; + } + + const xdg::Runtime& runtime() const override + { + return runtime_; + } + + MockXdgData data_; + xdg::Config config_; + xdg::Cache cache_; + xdg::Runtime runtime_; +}; +} + +TEST(SqliteTrustStore, queries_xdg_data_home) +{ + using namespace ::testing; + + MockXdgBaseDirSpec spec; + EXPECT_CALL(spec.data_, home()).Times(1).WillRepeatedly(Return(boost::filesystem::path{"/tmp"})); + core::trust::impl::sqlite::create_for_service(service_name, spec); +}