trust-store-2.0.0+16.04.20160119/0000755000015600001650000000000012647452606016404 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/doc/0000755000015600001650000000000012647452606017151 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/doc/CMakeLists.txt0000644000015600001650000000246112647452272021713 0ustar pbuserpbgroup00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss option( TRUST_STORE_ENABLE_DOC_GENERATION "Generate package documentation with doxygen" ON ) if (TRUST_STORE_ENABLE_DOC_GENERATION) find_package(Doxygen) if (DOXYGEN_FOUND) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${CMAKE_INSTALL_DOCDIR}) endif (DOXYGEN_FOUND) endif (TRUST_STORE_ENABLE_DOC_GENERATION) trust-store-2.0.0+16.04.20160119/doc/Doxyfile.in0000644000015600001650000023455412647452272021300 0ustar pbuserpbgroup00000000000000# Doxyfile 1.8.3.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = @CMAKE_PROJECT_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @TRUST_STORE_VERSION_MAJOR@.@TRUST_STORE_VERSION_MINOR@.@TRUST_STORE_VERSION_PATCH@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Provides a common implementation of a trust store to be used by trusted helpers." # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented classes, # or namespaces to their corresponding documentation. Such a link can be # prevented in individual cases by by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_CURRENT_SOURCE_DIR@ @CMAKE_CURRENT_SOURCE_DIR@/../include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/../tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page (index.html). # This can be useful if you have a project on for instance GitHub and want reuse # the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/extra.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = YES # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 1 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search engine # library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 1 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = YES # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = YES # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES trust-store-2.0.0+16.04.20160119/cmake/0000755000015600001650000000000012647452606017464 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/cmake/EnableCoverageReport.cmake0000644000015600001650000001537512647452272024536 0ustar pbuserpbgroup00000000000000# - Creates a special coverage build type and target on GCC. # # Defines a function ENABLE_COVERAGE_REPORT which generates the coverage target # for selected targets. Optional arguments to this function are used to filter # unwanted results using globbing expressions. Moreover targets with tests for # the source code can be specified to trigger regenerating the report if the # test has changed # # ENABLE_COVERAGE_REPORT(TARGETS target... [FILTER filter...] [TESTS test targets...]) # # To generate a coverage report first build the project with # CMAKE_BUILD_TYPE=coverage, then call make test and afterwards make coverage. # # The coverage report is based on gcov. Depending on the availability of lcov # a HTML report will be generated and/or an XML report of gcovr is found. # The generated coverage target executes all found solutions. Special targets # exist to create e.g. only the xml report: coverage-xml. # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(ParseArguments) FIND_PACKAGE(Lcov) FIND_PACKAGE(gcovr) FUNCTION(ENABLE_COVERAGE_REPORT) # argument parsing PARSE_ARGUMENTS(ARG "FILTER;TARGETS;TESTS" "" ${ARGN}) SET(COVERAGE_RAW_FILE "${CMAKE_BINARY_DIR}/coverage.raw.info") SET(COVERAGE_FILTERED_FILE "${CMAKE_BINARY_DIR}/coverage.info") SET(COVERAGE_REPORT_DIR "${CMAKE_BINARY_DIR}/coveragereport") SET(COVERAGE_XML_FILE "${CMAKE_BINARY_DIR}/coverage.xml") SET(COVERAGE_XML_COMMAND_FILE "${CMAKE_BINARY_DIR}/coverage-xml.cmake") # decide if there is any tool to create coverage data SET(TOOL_FOUND FALSE) IF(LCOV_FOUND OR GCOVR_FOUND) SET(TOOL_FOUND TRUE) ENDIF() IF(NOT TOOL_FOUND) MESSAGE(STATUS "Cannot enable coverage targets because neither lcov nor gcovr are found.") ENDIF() STRING(TOLOWER "${CMAKE_BUILD_TYPE}" COVERAGE_BUILD_TYPE) IF(CMAKE_COMPILER_IS_GNUCXX AND TOOL_FOUND AND "${COVERAGE_BUILD_TYPE}" MATCHES "coverage") MESSAGE(STATUS "Coverage support enabled for targets: ${ARG_TARGETS}") # create coverage build type SET(CMAKE_CXX_FLAGS_COVERAGE ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_C_FLAGS_COVERAGE ${CMAKE_C_FLAGS_DEBUG} PARENT_SCOPE) SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES} coverage PARENT_SCOPE) # instrument targets SET_TARGET_PROPERTIES(${ARG_TARGETS} PROPERTIES COMPILE_FLAGS --coverage LINK_FLAGS --coverage) # html report IF (LCOV_FOUND) MESSAGE(STATUS "Enabling HTML coverage report") # set up coverage target ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_RAW_FILE} COMMAND ${LCOV_EXECUTABLE} -c -d ${CMAKE_BINARY_DIR} -o ${COVERAGE_RAW_FILE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Collecting coverage data" DEPENDS ${ARG_TARGETS} ${ARG_TESTS} VERBATIM) # filter unwanted stuff LIST(LENGTH ARG_FILTER FILTER_LENGTH) IF(${FILTER_LENGTH} GREATER 0) SET(FILTER COMMAND ${LCOV_EXECUTABLE}) FOREACH(F ${ARG_FILTER}) SET(FILTER ${FILTER} -r ${COVERAGE_FILTERED_FILE} ${F}) ENDFOREACH() SET(FILTER ${FILTER} -o ${COVERAGE_FILTERED_FILE}) ELSE() SET(FILTER "") ENDIF() ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_FILTERED_FILE} COMMAND ${LCOV_EXECUTABLE} -e ${COVERAGE_RAW_FILE} "${CMAKE_SOURCE_DIR}*" -o ${COVERAGE_FILTERED_FILE} ${FILTER} DEPENDS ${COVERAGE_RAW_FILE} COMMENT "Filtering recorded coverage data for project-relevant entries" VERBATIM) ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_REPORT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_REPORT_DIR} COMMAND ${GENHTML_EXECUTABLE} --legend --show-details -t "${PROJECT_NAME} test coverage" -o ${COVERAGE_REPORT_DIR} ${COVERAGE_FILTERED_FILE} DEPENDS ${COVERAGE_FILTERED_FILE} COMMENT "Generating HTML coverage report in ${COVERAGE_REPORT_DIR}" VERBATIM) ADD_CUSTOM_TARGET(coverage-html DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() # xml coverage report IF(GCOVR_FOUND) MESSAGE(STATUS "Enabling XML coverage report") # gcovr cannot write directly to a file so the execution needs to # be wrapped in a cmake file that generates the file output FILE(WRITE ${COVERAGE_XML_COMMAND_FILE} "SET(ENV{LANG} en)\n") FILE(APPEND ${COVERAGE_XML_COMMAND_FILE} "EXECUTE_PROCESS(COMMAND \"${GCOVR_EXECUTABLE}\" --exclude=tests.* --exclude=obj-.* --exclude=cmake.* -x -r \"${CMAKE_SOURCE_DIR}\" OUTPUT_FILE \"${COVERAGE_XML_FILE}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")\n") ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_XML_FILE} COMMAND ${CMAKE_COMMAND} ARGS -P ${COVERAGE_XML_COMMAND_FILE} COMMENT "Generating coverage XML report" VERBATIM) ADD_CUSTOM_TARGET(coverage-xml DEPENDS ${COVERAGE_XML_FILE}) ENDIF() # provide a global coverage target executing both steps if available SET(GLOBAL_DEPENDS "") IF(LCOV_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_REPORT_DIR}) ENDIF() IF(GCOVR_FOUND) LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_XML_FILE}) ENDIF() IF(LCOV_FOUND OR GCOVR_FOUND) ADD_CUSTOM_TARGET(coverage DEPENDS ${GLOBAL_DEPENDS}) ENDIF() ENDIF() ENDFUNCTION() trust-store-2.0.0+16.04.20160119/cmake/Findgcovr.cmake0000644000015600001650000000170212647452272022406 0ustar pbuserpbgroup00000000000000# - Find gcovr scrip # Will define: # # GCOVR_EXECUTABLE - the gcovr script # # Uses: # # GCOVR_ROOT - root to search for the script # # Copyright (C) 2011 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin") FIND_PACKAGE_HANDLE_STANDARD_ARGS(gcovr DEFAULT_MSG GCOVR_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(GCOVR_EXECUTABLE) trust-store-2.0.0+16.04.20160119/cmake/FindGtest.cmake0000644000015600001650000000337212647452272022361 0ustar pbuserpbgroup00000000000000include(ExternalProject) include(FindPackageHandleStandardArgs) #gtest set(GTEST_INSTALL_DIR /usr/src/gmock/gtest/include) find_path(GTEST_INCLUDE_DIR gtest/gtest.h HINTS ${GTEST_INSTALL_DIR}) #gmock find_path(GMOCK_INSTALL_DIR gmock/CMakeLists.txt HINTS /usr/src) if(${GMOCK_INSTALL_DIR} STREQUAL "GMOCK_INSTALL_DIR-NOTFOUND") message(FATAL_ERROR "google-mock package not found") endif() set(GMOCK_INSTALL_DIR ${GMOCK_INSTALL_DIR}/gmock) find_path(GMOCK_INCLUDE_DIR gmock/gmock.h) set(GMOCK_PREFIX gmock) set(GMOCK_BINARY_DIR ${CMAKE_BINARY_DIR}/${GMOCK_PREFIX}/libs) set(GTEST_BINARY_DIR ${GMOCK_BINARY_DIR}/gtest) set(GTEST_CMAKE_ARGS "") if (${MIR_IS_CROSS_COMPILING}) set(GTEST_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_MODULE_PATH}/LinuxCrossCompile.cmake) endif() ExternalProject_Add( GMock #where to build in source tree PREFIX ${GMOCK_PREFIX} #where the source is external to the project SOURCE_DIR ${GMOCK_INSTALL_DIR} #forward the compilers to the subproject so cross-arch builds work CMAKE_ARGS ${GTEST_CMAKE_ARGS} BINARY_DIR ${GMOCK_BINARY_DIR} #we don't need to install, so skip INSTALL_COMMAND "" ) set(GMOCK_LIBRARY ${GMOCK_BINARY_DIR}/libgmock.a) set(GMOCK_MAIN_LIBRARY ${GMOCK_BINARY_DIR}/libgmock_main.a) set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY}) set(GTEST_LIBRARY ${GTEST_BINARY_DIR}/libgtest.a) set(GTEST_MAIN_LIBRARY ${GTEST_BINARY_DIR}/libgtest_main.a) set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) set(GTEST_ALL_LIBRARIES ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES}) find_package_handle_standard_args(GTest DEFAULT_MSG GMOCK_INCLUDE_DIR GTEST_INCLUDE_DIR) trust-store-2.0.0+16.04.20160119/cmake/PrePush.cmake0000644000015600001650000000727612647452272022067 0ustar pbuserpbgroup00000000000000####################################################################### # A convenience target that carries out the following steps: # - Apply astyle to all source files of interest. # - Build & test in a chroot, comparable setup to CI/Autolanding # and ppa builders. Will fail if new files have not been added. # - Build & test for android. # # NOTE: This target is very sensitive to the availability of all # all required dependencies. For that, we prefer to fail the # target if deps are missing to make the problem very visible. # # TODO: # - Wire up the style-check target once we have reached a state # where trunk actually passes the style check. ####################################################################### add_custom_target( pre-push WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) ####################################################################### # Add target for running astyle with the correct options # ####################################################################### find_program(ASTYLE_EXECUTABLE astyle) if (ASTYLE_EXECUTABLE) add_custom_target( astyle ${ASTYLE_EXECUTABLE} --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type --recursive ${CMAKE_SOURCE_DIR}/include/*.h COMMAND ${ASTYLE_EXECUTABLE} --recursive --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type ${CMAKE_SOURCE_DIR}/tests/*.cpp COMMAND ${ASTYLE_EXECUTABLE} --recursive --style=allman -s4 --indent=spaces=4 --pad-header --align-pointer=type ${CMAKE_SOURCE_DIR}/examples/*.h ${CMAKE_CURRENT_SOURCE_DIR}/examples/*.cpp VERBATIM ) endif (ASTYLE_EXECUTABLE) ####################################################################### # Add target for creating a source tarball with bzr export # ####################################################################### add_custom_target( pre-push-source-tarball COMMAND rm -rf pre-push-build-area COMMAND mkdir pre-push-build-area COMMAND bzr export --root pre-push pre-push-build-area/${PROJECT_NAME}_${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.orig.tar.bz2 ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Preparing source tarball for pre-push build & test" ) ####################################################################### # Add target for extracting source tarball for pdebuild # ####################################################################### add_custom_target( extract-pre-push-tarball COMMAND tar -xf {PROJECT_NAME}_${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.${DBUS_CPP_VERSION_MAJOR}.orig.tar.bz2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pre-push-build-area VERBATIM ) ####################################################################### # Builds & tests the last committed revision of the current branch # ####################################################################### find_program(PDEBUILD_EXECUTABLE pdebuild) if(NOT PDEBUILD_EXECUTABLE) message(STATUS "pdebuild NOT found, pre-push is going to FAIL") endif() add_custom_target( pdebuild COMMAND ${PDEBUILD_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pre-push-build-area/pre-push COMMENT "Building & testing in chroot'd environment" VERBATIM ) ####################################################################### # pdebuild: make tarball -> extract to build area -> pdebuild # # android-build: invoke cross-compile script # ####################################################################### add_dependencies(extract-pre-push-tarball pre-push-source-tarball) add_dependencies(pdebuild extract-pre-push-tarball) add_dependencies(pre-push pdebuild android-build) trust-store-2.0.0+16.04.20160119/cmake/ParseArguments.cmake0000644000015600001650000000340612647452272023430 0ustar pbuserpbgroup00000000000000# Parse arguments passed to a function into several lists separated by # upper-case identifiers and options that do not have an associated list e.g.: # # SET(arguments # hello OPTION3 world # LIST3 foo bar # OPTION2 # LIST1 fuz baz # ) # PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) # # results in 7 distinct variables: # * ARG_DEFAULT_ARGS: hello;world # * ARG_LIST1: fuz;baz # * ARG_LIST2: # * ARG_LIST3: foo;bar # * ARG_OPTION1: FALSE # * ARG_OPTION2: TRUE # * ARG_OPTION3: TRUE # # taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments MACRO(PARSE_ARGUMENTS prefix arg_names option_names) SET(DEFAULT_ARGS) FOREACH(arg_name ${arg_names}) SET(${prefix}_${arg_name}) ENDFOREACH(arg_name) FOREACH(option ${option_names}) SET(${prefix}_${option} FALSE) ENDFOREACH(option) SET(current_arg_name DEFAULT_ARGS) SET(current_arg_list) FOREACH(arg ${ARGN}) SET(larg_names ${arg_names}) LIST(FIND larg_names "${arg}" is_arg_name) IF (is_arg_name GREATER -1) SET(${prefix}_${current_arg_name} ${current_arg_list}) SET(current_arg_name ${arg}) SET(current_arg_list) ELSE (is_arg_name GREATER -1) SET(loption_names ${option_names}) LIST(FIND loption_names "${arg}" is_option) IF (is_option GREATER -1) SET(${prefix}_${arg} TRUE) ELSE (is_option GREATER -1) SET(current_arg_list ${current_arg_list} ${arg}) ENDIF (is_option GREATER -1) ENDIF (is_arg_name GREATER -1) ENDFOREACH(arg) SET(${prefix}_${current_arg_name} ${current_arg_list}) ENDMACRO(PARSE_ARGUMENTS) trust-store-2.0.0+16.04.20160119/cmake/FindLcov.cmake0000644000015600001650000000172012647452272022171 0ustar pbuserpbgroup00000000000000# - Find lcov # Will define: # # LCOV_EXECUTABLE - the lcov binary # GENHTML_EXECUTABLE - the genhtml executable # # Copyright (C) 2010 by Johannes Wienke # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General # Public License as published by the Free Software Foundation; # either version 2, 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. # INCLUDE(FindPackageHandleStandardArgs) FIND_PROGRAM(LCOV_EXECUTABLE lcov) FIND_PROGRAM(GENHTML_EXECUTABLE genhtml) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lcov DEFAULT_MSG LCOV_EXECUTABLE GENHTML_EXECUTABLE) # only visible in advanced view MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE) trust-store-2.0.0+16.04.20160119/tests/0000755000015600001650000000000012647452606017546 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/tests/mock_agent.h0000644000015600001650000000235412647452272022031 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef MOCK_AGENT_H_ #define MOCK_AGENT_H_ #include #include struct MockAgent : public core::trust::Agent { /** * @brief Presents the given request to the user, returning the user-provided answer. * @param request The trust request that a user has to answer. * @param description Extended description of the trust request. */ MOCK_METHOD1(authenticate_request_with_parameters, core::trust::Request::Answer(const core::trust::Agent::RequestParameters&)); }; #endif // MOCK_AGENT_H_ trust-store-2.0.0+16.04.20160119/tests/preseed_test.cpp0000644000015600001650000000573112647452272022745 0ustar pbuserpbgroup00000000000000/* * 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 "test_data.h" #include #include #include #include namespace { std::map a_copy_of_the_current_env() { std::map result; core::posix::this_process::env::for_each([&result](const std::string& s, const std::string& t) { result.insert(std::make_pair(s, t)); }); return result; } } TEST(Preseed, correctly_populates_per_service_trust_store) { const std::string service_name{"JustANameForTesting"}; const std::string app_name{"does.not.exist.app"}; const std::vector argv { "--for-service", service_name, "--request", "does.not.exist.app 0 granted", // 1 "--request", "does.not.exist.app 1 denied", // 2 "--request", "does.not.exist.app 2 granted", // 3 "--request", "does.not.exist.app 3 denied", // 4 "--request", "does.not.exist.app 4 granted", // 5 "--request", "does.not.exist.app 5 denied", // 6 "--request", "does.not.exist.app 6 granted", // 7 "--request", "does.not.exist.app 7 denied" // 8 }; auto child = core::posix::exec( core::trust::testing::trust_store_preseed_executable_in_build_dir, argv, a_copy_of_the_current_env(), core::posix::StandardStream::empty); auto result = child.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); auto store = core::trust::create_default_store(service_name); auto query = store->query(); EXPECT_NO_THROW(query->execute()); std::size_t counter{0}; while (query->status() != core::trust::Store::Query::Status::eor) { EXPECT_EQ(counter, query->current().feature.value); if (counter % 2 == 0) EXPECT_EQ(core::trust::Request::Answer::granted, query->current().answer); else EXPECT_EQ(core::trust::Request::Answer::denied, query->current().answer); EXPECT_EQ(app_name, query->current().from); query->next(); counter++; } } trust-store-2.0.0+16.04.20160119/tests/app_id_formatting_trust_agent_test.cpp0000644000015600001650000000507112647452272027420 0ustar pbuserpbgroup00000000000000/* * 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 "mock_agent.h" #include "the.h" #include namespace { std::shared_ptr> a_mocked_agent() { return std::make_shared>(); } } TEST(AppIdFormattingTrustAgent, ctor_throws_for_null_agent) { EXPECT_ANY_THROW(core::trust::AppIdFormattingTrustAgent agent{std::shared_ptr()}); } TEST(AppIdFormattingTrustAgent, removes_version_and_calls_to_implementation) { 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"}; auto params_without_version = the::default_request_parameters_for_testing(); params_without_version.application.id = params_without_version.application.id + std::string{"_app"}; EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params_without_version)) .Times(1) .WillRepeatedly(Return(core::trust::Request::Answer::denied)); core::trust::AppIdFormattingTrustAgent agent{mock_agent}; EXPECT_EQ(core::trust::Request::Answer::denied, agent.authenticate_request_with_parameters(params)); } TEST(AppIdFormattingTrustAgent, leaves_unversioned_app_id_as_is) { using namespace ::testing; auto mock_agent = a_mocked_agent(); auto params = the::default_request_parameters_for_testing(); EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params)) .Times(1) .WillRepeatedly(Return(core::trust::Request::Answer::denied)); core::trust::AppIdFormattingTrustAgent agent{mock_agent}; EXPECT_EQ(core::trust::Request::Answer::denied, agent.authenticate_request_with_parameters(params)); } trust-store-2.0.0+16.04.20160119/tests/remote_trust_store_test.cpp0000644000015600001650000005342112647452272025265 0ustar pbuserpbgroup00000000000000/* * 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 #include #include #include #include #include #include #include #include namespace { static const std::string service_name{"does_not_exist"}; struct RemoteTrustStore : public core::dbus::testing::Fixture { RemoteTrustStore() { // The tests being executed under this fixture are quite intense given their accesses // to the disk. For that, we choose sufficiently high default timeout for the daemons. core::dbus::Fixture::default_daemon_timeout() = core::dbus::Fixture::Seconds{300}; } }; } TEST_F(RemoteTrustStore, a_store_exposed_to_the_session_can_be_reset) { core::testing::CrossProcessSync cps; auto service = [this, &cps]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this, &cps]() { auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); std::cout << "here" << std::endl; EXPECT_NO_THROW(store->reset();); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, a_store_exposed_to_the_session_can_be_added_to) { core::testing::CrossProcessSync cps1, cps2; static const unsigned int request_count = 100; core::trust::Request prototype_request { "com.does.not.exist.app1", core::trust::Feature{0}, std::chrono::system_clock::time_point{std::chrono::seconds(500)}, core::trust::Request::Answer::granted }; auto service = [this, prototype_request, &cps1]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); store->reset(); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps1.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto client = [this, prototype_request, &cps1]() { core::trust::Request r { prototype_request.from, prototype_request.feature, prototype_request.when, prototype_request.answer }; cps1.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); for (unsigned int i = 0; i < request_count; i++) { r.feature.value = i; store->add(r); } // Resetting the feature counter and checking if all requests have been stored. r.feature.value = 0; auto query = store->query(); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); while(query->status() != core::trust::Store::Query::Status::eor) { EXPECT_EQ(r, query->current()); query->next(); r.feature.value++; } return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } // Taken from trust store test namespace { core::testing::CrossProcessSync cps; } TEST_F(RemoteTrustStore, limiting_query_to_app_id_returns_correct_results) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; const std::string app2{"com.does.not.exist.app2"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app2, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); auto query = store->query(); query->for_application_id(app2); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, limiting_query_to_feature_returns_correct_results) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); auto query = store->query(); query->for_feature(r2.feature); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, limiting_query_to_answer_returns_correct_results) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::denied }; store->add(r1); store->add(r2); auto query = store->query(); query->for_answer(r2.answer); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, limiting_query_to_time_interval_returns_correct_result) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::time_point(std::chrono::seconds{500}), core::trust::Request::Answer::granted }; core::trust::Request r3 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); store->add(r3); auto query = store->query(); query->for_interval( std::chrono::system_clock::time_point(std::chrono::seconds{500}), std::chrono::system_clock::now()); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r3, query->current()); query->next(); EXPECT_EQ(r2, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, limiting_query_to_time_interval_and_answer_returns_correct_result) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::time_point(std::chrono::seconds{500}), core::trust::Request::Answer::granted }; core::trust::Request r3 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::denied }; store->add(r1); store->add(r2); store->add(r3); auto query = store->query(); query->for_interval( std::chrono::system_clock::time_point(std::chrono::seconds{500}), std::chrono::system_clock::now()); query->for_answer(core::trust::Request::Answer::denied); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r3, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, added_requests_are_found_by_query_multi_threaded) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); static const std::uint64_t base_feature = 0; auto inserter = [store](int base) { core::trust::Request r { "this.does.not.exist.app", core::trust::Feature{base_feature}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; for (unsigned int i = 0; i < 100; i++) { r.feature.value = base + i; try { store->add(r); } catch(...) { } } }; std::thread t1 {inserter, 0}; std::thread t2 {inserter, 100}; std::thread t3 {inserter, 200}; std::thread t4 {inserter, 300}; std::thread t5 {inserter, 400}; t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); auto query = store->query(); query->all(); query->execute(); unsigned int counter = 0; while(core::trust::Store::Query::Status::eor != query->status()) { query->next(); counter++; } EXPECT_EQ(500u, counter); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } TEST_F(RemoteTrustStore, erasing_requests_empties_store) { auto service = [this]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto store = core::trust::create_default_store(service_name); auto mapping = core::trust::expose_store_to_bus_with_name(store, bus, service_name); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); return core::posix::exit::Status::success; }; auto client = [this]() { auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto store = core::trust::resolve_store_on_bus_with_name(bus, service_name); store->reset(); // Insert a bunch of requests and erase them after that. { core::trust::Request r { "this.does.not.exist.app", core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; for (unsigned int i = 0; i < 100; i++) { r.feature.value = i; store->add(r); } auto query = store->query(); query->execute(); while(core::trust::Store::Query::Status::eor != query->status()) { query->erase(); } } // Now let's see if the records are actually gone. auto query = store->query(); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); return ::testing::Test::HasFatalFailure() || ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client)); } trust-store-2.0.0+16.04.20160119/tests/trust_store_test.cpp0000644000015600001650000002646312647452305023715 0ustar pbuserpbgroup00000000000000/* * 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 #include #include namespace { static const std::string service_name{"52EB2494-76F2-4ABB-A188-20B2D5B3CC94"}; } TEST(TrustStoreRequestAnswer, is_printed_correctly) { { std::stringstream ss; ss << core::trust::Request::Answer::granted; EXPECT_EQ("granted", ss.str()); } { std::stringstream ss; ss << core::trust::Request::Answer::denied; EXPECT_EQ("denied", ss.str()); } } TEST(TrustStoreRequest, is_printed_correctly) { core::trust::Request r { "this.does.not.exist.app", core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; std::stringstream ss; ss << r; EXPECT_EQ("Request(from: this.does.not.exist.app, feature: 0, when: 0, answer: granted)", ss.str()); } TEST(TrustStore, default_implementation_is_available) { auto store = core::trust::create_default_store(service_name); EXPECT_TRUE(store != nullptr); } TEST(TrustStore, resetting_the_store_purges_requests) { auto store = core::trust::create_default_store(service_name); store->reset(); auto query = store->query(); EXPECT_EQ(core::trust::Store::Query::Status::armed, query->status()); query->all(); EXPECT_NO_THROW(query->execute()); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } TEST(TrustStore, added_requests_are_found_by_query) { auto store = core::trust::create_default_store(service_name); store->reset(); static const std::uint64_t base_feature = 0; core::trust::Request r1 { "this.does.not.exist.app", core::trust::Feature{base_feature}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 = r1; r2.feature.value = base_feature + 1; core::trust::Request r3 = r2; r3.feature.value = base_feature + 2; store->add(r1); store->add(r2); store->add(r3); auto query = store->query(); query->all(); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r1, query->current()); query->next(); EXPECT_EQ(r2, query->current()); query->next(); EXPECT_EQ(r3, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } TEST(TrustStore, limiting_query_to_app_id_returns_correct_results) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; const std::string app2{"com.does.not.exist.app2"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app2, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); auto query = store->query(); query->for_application_id(app2); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); } TEST(TrustStore, limiting_query_to_feature_returns_correct_results) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); auto query = store->query(); query->for_feature(r2.feature); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); } TEST(TrustStore, limiting_query_to_answer_returns_correct_results) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::denied }; store->add(r1); store->add(r2); auto query = store->query(); query->for_answer(r2.answer); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r2, query->current()); } TEST(TrustStore, limiting_query_to_time_interval_returns_correct_result) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::time_point(std::chrono::seconds{500}), core::trust::Request::Answer::granted }; core::trust::Request r3 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; store->add(r1); store->add(r2); store->add(r3); auto query = store->query(); query->for_interval( std::chrono::system_clock::time_point(std::chrono::seconds{500}), std::chrono::system_clock::now()); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r3, query->current()); query->next(); EXPECT_EQ(r2, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } TEST(TrustStore, limiting_query_to_time_interval_and_answer_returns_correct_result) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; core::trust::Request r2 { app1, core::trust::Feature{1}, std::chrono::system_clock::time_point(std::chrono::seconds{500}), core::trust::Request::Answer::granted }; core::trust::Request r3 { app1, core::trust::Feature{1}, std::chrono::system_clock::now(), core::trust::Request::Answer::denied }; store->add(r1); store->add(r2); store->add(r3); auto query = store->query(); query->for_interval( std::chrono::system_clock::time_point(std::chrono::seconds{500}), std::chrono::system_clock::now()); query->for_answer(core::trust::Request::Answer::denied); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); EXPECT_EQ(r3, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } TEST(TrustStore, added_requests_are_found_by_query_multi_threaded) { auto store = core::trust::create_default_store(service_name); store->reset(); static const std::uint64_t base_feature = 0; auto inserter = [store](int base) { core::trust::Request r { "this.does.not.exist.app", core::trust::Feature{base_feature}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; for (unsigned int i = 0; i < 100; i++) { r.feature.value = base + i; store->add(r); } }; std::thread t1 {inserter, 0}; std::thread t2 {inserter, 100}; std::thread t3 {inserter, 200}; std::thread t4 {inserter, 300}; std::thread t5 {inserter, 400}; t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); auto query = store->query(); query->all(); query->execute(); unsigned int counter = 0; while(core::trust::Store::Query::Status::eor != query->status()) { query->next(); counter++; } EXPECT_EQ(500u, counter); } TEST(TrustStore, erasing_requests_empties_store) { auto store = core::trust::create_default_store(service_name); store->reset(); // Insert a bunch of requests and erase them after that. { core::trust::Request r { "this.does.not.exist.app", core::trust::Feature{0}, std::chrono::system_clock::now(), core::trust::Request::Answer::granted }; for (unsigned int i = 0; i < 100; i++) { r.feature.value = i; store->add(r); } auto query = store->query(); query->execute(); while(core::trust::Store::Query::Status::eor != query->status()) { query->erase(); } } // Now let's see if the records are actually gone. auto query = store->query(); 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); } trust-store-2.0.0+16.04.20160119/tests/empty/0000755000015600001650000000000012647452606020704 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/tests/empty/applications/0000755000015600001650000000000012647452606023372 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/tests/mir_agent_test.cpp0000644000015600001650000005017512647452305023262 0ustar pbuserpbgroup00000000000000/* * 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ß */ // Implementation-specific header #include #include #include #include #include #include "test_data.h" #include #include #include #include #include namespace { struct MockPromptSessionVirtualTable : public core::trust::mir::PromptSessionVirtualTable { MockPromptSessionVirtualTable() : core::trust::mir::PromptSessionVirtualTable{} { } // Requests a new, pre-authenticated fd for associating prompt providers. // Returns the fd or throws std::runtime_error. MOCK_METHOD0(new_fd_for_prompt_provider, int()); // Adds a prompt provider process to the prompting session, identified by its PID. // Returns true if addition of the prompt provider succeeded. MOCK_METHOD1(add_prompt_provider_sync, bool(pid_t)); // Finalizes and releases the given prompt session instance. MOCK_METHOD0(release_sync, void()); }; struct MockConnectionVirtualTable : public core::trust::mir::ConnectionVirtualTable { MockConnectionVirtualTable() : core::trust::mir::ConnectionVirtualTable{} { } // Creates a new trusted prompt session instance synchronously. MOCK_METHOD3(create_prompt_session_sync, core::trust::mir::PromptSessionVirtualTable::Ptr( // The process id of the requesting app/service core::trust::Pid app_pid, // Callback handling prompt session state changes. mir_prompt_session_state_change_callback, // Callback context void*)); }; struct MockPromptProviderHelper : public core::trust::mir::PromptProviderHelper { MockPromptProviderHelper(const core::trust::mir::PromptProviderHelper::CreationArguments& args) : core::trust::mir::PromptProviderHelper{args} { using namespace ::testing; ON_CALL(*this, exec_prompt_provider_with_arguments(_)) .WillByDefault( Invoke(this, &MockPromptProviderHelper::super_exec_prompt_provider_with_arguments)); } // Execs the executable provided at construction time for the arguments and // returns the corresponding child process. MOCK_METHOD1(exec_prompt_provider_with_arguments, core::posix::ChildProcess( const core::trust::mir::PromptProviderHelper::InvocationArguments&)); core::posix::ChildProcess super_exec_prompt_provider_with_arguments(const core::trust::mir::PromptProviderHelper::InvocationArguments& args) { return core::trust::mir::PromptProviderHelper::exec_prompt_provider_with_arguments(args); } }; struct MockTranslator { 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>(); } std::shared_ptr a_mocked_prompt_session_vtable() { return std::make_shared>(); } std::shared_ptr a_mocked_prompt_provider_calling_bin_false() { return std::make_shared( core::trust::mir::PromptProviderHelper::CreationArguments { "/bin/false" }); } std::shared_ptr a_mocked_app_info_resolver() { return std::make_shared(); } } TEST(DefaultProcessStateTranslator, throws_for_signalled_process) { core::posix::wait::Result result; result.status = core::posix::wait::Result::Status::signaled; result.detail.if_signaled.signal = core::posix::Signal::sig_kill; result.detail.if_signaled.core_dumped = true; auto translator = core::trust::mir::Agent::translator_only_accepting_exit_status_success(); EXPECT_THROW(translator(result), std::logic_error); } TEST(DefaultProcessStateTranslator, throws_for_stopped_process) { core::posix::wait::Result result; result.status = core::posix::wait::Result::Status::stopped; result.detail.if_stopped.signal = core::posix::Signal::sig_stop; auto translator = core::trust::mir::Agent::translator_only_accepting_exit_status_success(); EXPECT_THROW(translator(result), std::logic_error); } TEST(DefaultProcessStateTranslator, returns_denied_for_process_exiting_with_failure) { core::posix::wait::Result result; result.status = core::posix::wait::Result::Status::exited; result.detail.if_exited.status = core::posix::exit::Status::failure; auto translator = core::trust::mir::Agent::translator_only_accepting_exit_status_success(); EXPECT_EQ(core::trust::Request::Answer::denied, translator(result)); } TEST(DefaultProcessStateTranslator, returns_granted_for_process_exiting_successfully) { core::posix::wait::Result result; result.status = core::posix::wait::Result::Status::exited; result.detail.if_exited.status = core::posix::exit::Status::success; auto translator = core::trust::mir::Agent::translator_only_accepting_exit_status_success(); EXPECT_EQ(core::trust::Request::Answer::granted, translator(result)); } TEST(DefaultPromptProviderHelper, correctly_passes_arguments_to_prompt_executable) { core::posix::this_process::env::set_or_throw("CORE_TRUST_MIR_PROMPT_TESTING", "1"); core::trust::mir::PromptProviderHelper::CreationArguments cargs { core::trust::mir::trust_prompt_executable_in_build_dir }; core::trust::mir::PromptProviderHelper::InvocationArguments iargs { 42, { "/tmp", "Does not exist", "does.not.exist.application" }, "Just an extended description for %1%" }; core::trust::mir::PromptProviderHelper helper{cargs}; auto child = helper.exec_prompt_provider_with_arguments(iargs); auto result = child.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); // And clean up. core::posix::this_process::env::unset_or_throw("CORE_TRUST_MIR_PROMPT_TESTING"); } TEST(MirAgent, creates_prompt_session_and_execs_helper_with_preauthenticated_fd) { 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%"}; 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)); 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); 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, 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%"}; const int pre_authenticated_fd {42}; auto a_spinning_process = []() { while (true) { std::this_thread::sleep_for(std::chrono::milliseconds{20}); } return core::posix::exit::Status::success; }; auto connection_vtable = std::make_shared(); auto prompt_session_vtable = a_mocked_prompt_session_vtable(); 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(_)) .WillByDefault( Return( core::posix::fork( a_spinning_process, core::posix::StandardStream::empty))); 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)); 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. ON_CALL(*connection_vtable, create_prompt_session_sync(app_pid, _, _)) .WillByDefault( DoAll( SaveArg<2>(&prompt_session_state_callback_context), Return(prompt_session_vtable))); core::trust::mir::Agent agent { 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 { [&prompt_session_state_callback_context]() { std::this_thread::sleep_for(std::chrono::seconds{1}); core::trust::mir::Agent::on_trust_session_changed_state( nullptr, mir_prompt_session_state_stopped, prompt_session_state_callback_context); } }; // The spinning prompt provider should get signalled if the prompting session is stopped. // If that does not happen, the prompt provider returns success and we would have a result // granted. EXPECT_THROW(agent.authenticate_request_with_parameters( core::trust::Agent::RequestParameters { core::trust::Uid{::getuid()}, core::trust::Pid{app_pid}, app_id, feature, app_description }), std::logic_error); // And some clean up. if (asynchronously_stop_the_prompting_session.joinable()) asynchronously_stop_the_prompting_session.join(); } TEST(TrustPrompt, aborts_for_missing_title) { // And we pass in an empty argument vector std::vector argv; // We pass in the empty env std::map env; auto child = core::posix::exec( core::trust::testing::trust_prompt_executable_in_build_dir, argv, env, core::posix::StandardStream::empty); auto result = child.wait_for(core::posix::wait::Flags::untraced); EXPECT_EQ(core::posix::wait::Result::Status::signaled, result.status); EXPECT_EQ(core::posix::Signal::sig_abrt, result.detail.if_signaled.signal); } /*********************************************************************** * All tests requiring a running Mir instance go here. * * They are tagged with _requires_mir and taken out of the * * automatic build and test cycle. * ***********************************************************************/ #include #include #include #include namespace { std::map a_copy_of_the_env() { std::map result; core::posix::this_process::env::for_each([&result](const std::string& key, const std::string& value) { result.insert(std::make_pair(key, value)) ; }); return result; } std::string mir_socket() { // We either take the XDG_RUNTIME_DIR or fall back to /tmp if XDG_RUNTIME_DIR is not set. 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. try { return xdg::runtime().dir().string() + "/mir_socket_trusted"; } catch(...) { return "/tmp/mir_socket_trusted"; } } } TEST(MirAgent, default_agent_works_correctly_against_running_mir_instance_requires_mir) { std::string pretty_function{__PRETTY_FUNCTION__}; // We start up an application in a child process and simulate that it is requesting access // to a trusted system service/resource. std::vector argv { "--" + std::string{core::trust::mir::cli::option_server_socket} + "=" + mir_socket(), "--" + 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. "--desktop_file_hint=/usr/share/applications/webbrowser-app.desktop" }; core::posix::ChildProcess app = core::posix::exec( core::trust::mir::trust_prompt_executable_in_lib_dir, argv, a_copy_of_the_env(), core::posix::StandardStream::empty); // We give the app some time to come up. std::this_thread::sleep_for(std::chrono::seconds{5}); // We pretend to be a trusted helper and connect to mir via its trusted socket. auto mir_connection = mir_connect_sync(trusted_mir_socket().c_str(), pretty_function.c_str()); // Based on the mir connection, we create a prompting agent. auto mir_agent = core::trust::mir::create_agent_for_mir_connection(mir_connection); // And issue a prompt request. As a result, the user is presented with a prompting dialog. auto answer = mir_agent->authenticate_request_with_parameters( core::trust::Agent::RequestParameters { core::trust::Uid{::getuid()}, core::trust::Pid{app.pid()}, "embedded prompt", core::trust::Feature{}, "embedded prompt" }); // And we cross-check with the user: std::cout << "You answered the trust prompt with: " << answer << "." << "Is that correct? [y/n]:"; char y_or_n{'n'}; std::cin >> y_or_n; EXPECT_EQ('y', y_or_n); // We are bit rude here, but we have no more use for the app. app.send_signal_or_throw(core::posix::Signal::sig_kill); // And wait for the app to complete to avoid zombies. app.wait_for(core::posix::wait::Flags::untraced); } trust-store-2.0.0+16.04.20160119/tests/request_processor_test.cpp0000644000015600001650000001541212647452272025102 0ustar pbuserpbgroup00000000000000/* * 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 #include "mock_agent.h" #include "mock_store.h" #include #include #include namespace { core::trust::Pid the_default_pid_for_testing() { return core::trust::Pid{42}; } core::trust::Uid the_default_uid_for_testing() { return core::trust::Uid{42}; } core::trust::Feature the_default_feature_for_testing() { return core::trust::Feature{0}; } std::shared_ptr a_null_agent() { return std::shared_ptr{}; } std::shared_ptr> a_mocked_agent() { return std::make_shared>(); } std::shared_ptr a_null_store() { return std::shared_ptr{}; } std::shared_ptr> a_mocked_store() { return std::make_shared>(); } std::shared_ptr> a_mocked_query() { return std::make_shared>(); } core::trust::RequestParameters default_request_parameters_for_testing() { return core::trust::RequestParameters { a_null_agent(), a_null_store(), the_default_uid_for_testing(), the_default_pid_for_testing(), "this.is.just.for.testing.purposes", the_default_feature_for_testing(), "Someone wants to access all your credentials and steal your identity." }; } core::trust::Request::Answer throw_a_dice() { // We seed the rng with the current time to ensure randomness across test runs. static std::default_random_engine generator { static_cast(std::chrono::system_clock::now().time_since_epoch().count()) }; // Our dice :) static std::uniform_int_distribution distribution { 1, 6 }; return distribution(generator) <= 3 ? core::trust::Request::Answer::denied : core::trust::Request::Answer::granted; } } TEST(RequestProcessing, throws_for_missing_agent_implementation) { auto params = default_request_parameters_for_testing(); params.store = a_mocked_store(); EXPECT_THROW(core::trust::process_trust_request(params), std::logic_error); } TEST(RequestProcessing, throws_for_missing_store_implementation) { auto params = default_request_parameters_for_testing(); params.agent = a_mocked_agent(); EXPECT_THROW(core::trust::process_trust_request(params), std::logic_error); } TEST(RequestProcessing, queries_store_for_cached_results_and_returns_cached_value) { using namespace ::testing; auto answer = throw_a_dice(); auto params = default_request_parameters_for_testing(); core::trust::Request request { params.application_id, params.feature, std::chrono::system_clock::now(), answer }; auto mocked_agent = a_mocked_agent(); auto mocked_query = a_mocked_query(); auto mocked_store = a_mocked_store(); ON_CALL(*mocked_query, status()) .WillByDefault( Return( core::trust::Store::Query::Status::has_more_results)); ON_CALL(*mocked_query, current()) .WillByDefault( Return( request)); ON_CALL(*mocked_store, query()) .WillByDefault( Return( mocked_query)); EXPECT_CALL(*mocked_store, query()).Times(1); // We expect the processor to limit the query to the respective application id // and to the respective feature. EXPECT_CALL(*mocked_query, for_application_id(params.application_id)).Times(1); EXPECT_CALL(*mocked_query, for_feature(params.feature)).Times(1); // The setup ensures that a previously stored answer is available in the store. // For that, the agent should not be queried. EXPECT_CALL(*mocked_agent, authenticate_request_with_parameters(_)).Times(0); params.agent = mocked_agent; params.store = mocked_store; EXPECT_EQ(answer, core::trust::process_trust_request(params)); } TEST(RequestProcessing, queries_agent_if_no_cached_results_and_returns_users_answer) { using namespace ::testing; auto answer = throw_a_dice(); auto params = default_request_parameters_for_testing(); core::trust::Agent::RequestParameters agent_params { params.application_uid, params.application_pid, params.application_id, params.feature, params.description }; core::trust::Request request { params.application_id, params.feature, std::chrono::system_clock::now(), answer }; auto mocked_agent = a_mocked_agent(); auto mocked_query = a_mocked_query(); auto mocked_store = a_mocked_store(); ON_CALL(*mocked_agent, authenticate_request_with_parameters(agent_params)) .WillByDefault( Return( answer)); // We return EndOfRecord for queries, and expect the request processor // to subsequently ask the user for his answer. ON_CALL(*mocked_query, status()) .WillByDefault( Return( core::trust::Store::Query::Status::eor)); ON_CALL(*mocked_store, query()) .WillByDefault( Return( mocked_query)); EXPECT_CALL(*mocked_query, current()).Times(0); EXPECT_CALL(*mocked_store, query()).Times(1); // We expect the processor to limit the query to the respective application id // and to the respective feature. EXPECT_CALL(*mocked_query, for_application_id(params.application_id)).Times(1); EXPECT_CALL(*mocked_query, for_feature(params.feature)).Times(1); // The setup ensures that a previously stored answer is available in the store. // For that, the agent should not be queried. EXPECT_CALL(*mocked_agent, authenticate_request_with_parameters(agent_params)).Times(1); params.agent = mocked_agent; params.store = mocked_store; EXPECT_EQ(answer, core::trust::process_trust_request(params)); } trust-store-2.0.0+16.04.20160119/tests/click_desktop_entry_app_name_resolver_test.cpp0000644000015600001650000000513312647452305031127 0ustar pbuserpbgroup00000000000000/* * 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"); } trust-store-2.0.0+16.04.20160119/tests/daemon_test.cpp0000644000015600001650000001535512647452272022564 0ustar pbuserpbgroup00000000000000/* * 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 "process_exited_successfully.h" #include #include #include #include #include namespace { static constexpr const char* service_name { "UnlikelyToEverExistOutsideOfTesting" }; static constexpr const char* endpoint { "/tmp/unlikely.to.ever.exist.outside.of.testing" }; } TEST(Daemon, unix_domain_agents_for_stub_and_skeleton_work_as_expected) { // We fire up private bus instances to ensure tests working // during package builds. core::dbus::Fixture private_buses { core::dbus::Fixture::default_session_bus_config_file(), core::dbus::Fixture::default_system_bus_config_file() }; std::remove(endpoint); // The stub accepting trust requests, relaying them via // the configured remote agent. core::posix::ChildProcess stub = core::posix::fork([]() { const char* argv[] = { __PRETTY_FUNCTION__, "--for-service", service_name, "--remote-agent", "UnixDomainSocketRemoteAgent", "--endpoint=/tmp/unlikely.to.ever.exist.outside.of.testing" }; auto configuration = core::trust::Daemon::Stub::Configuration::from_command_line(6, argv); return core::trust::Daemon::Stub::main(configuration); }, core::posix::StandardStream::stdin | core::posix::StandardStream::stdout); // We really want to write EXPECT_TRUE(WaitForEndPointToBecomeAvailableFor(endpoint, 500ms)); std::this_thread::sleep_for(std::chrono::milliseconds{500}); // The skeleton announcing itself to the stub instance started before via // the endpoint specified for the remote agent. In addition, it features a local // agent instance that always replies: denied. auto skeleton = core::posix::fork([]() { const char* argv[] { __PRETTY_FUNCTION__, "--remote-agent", "UnixDomainSocketRemoteAgent", "--endpoint=/tmp/unlikely.to.ever.exist.outside.of.testing", "--local-agent", "TheAlwaysDenyingLocalAgent", "--for-service", service_name, "--store-bus", "session_with_address_from_env" }; auto configuration = core::trust::Daemon::Skeleton::Configuration::from_command_line(10, argv); return core::trust::Daemon::Skeleton::main(configuration); }, core::posix::StandardStream::empty); // Wait for everything to be setup std::this_thread::sleep_for(std::chrono::milliseconds{500}); // And inject a request into the stub std::string answer; for (int feature = 0; feature < 50; feature++) { stub.cin() << core::posix::this_process::instance().pid() << " " << ::getuid() << " " << feature << std::endl; stub.cout() >> answer; } // Wait for all requests to be answered std::this_thread::sleep_for(std::chrono::milliseconds{500}); // Sigterm both stub and skeleton. skeleton.send_signal_or_throw(core::posix::Signal::sig_term); stub.send_signal_or_throw(core::posix::Signal::sig_term); // Expect both of them to exit with success. EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); } TEST(Daemon, dbus_agents_for_stub_and_skeleton_work_as_expected) { // We fire up private bus instances to ensure tests working // during package builds. core::dbus::Fixture private_buses { core::dbus::Fixture::default_session_bus_config_file(), core::dbus::Fixture::default_system_bus_config_file() }; static std::string bus_arg{"--bus=session_with_address_from_env"}; // The stub accepting trust requests, relaying them via // the configured remote agent. core::posix::ChildProcess stub = core::posix::fork([]() { const char* argv[] = { __PRETTY_FUNCTION__, "--for-service", service_name, "--remote-agent", "DBusRemoteAgent", bus_arg.c_str() }; auto configuration = core::trust::Daemon::Stub::Configuration::from_command_line(6, argv); return core::trust::Daemon::Stub::main(configuration); }, core::posix::StandardStream::stdin | core::posix::StandardStream::stdout); std::this_thread::sleep_for(std::chrono::milliseconds{500}); // The skeleton announcing itself to the stub instance started before via // the endpoint specified for the remote agent. In addition, it features a local // agent instance that always replies: denied. auto skeleton = core::posix::fork([]() { const char* argv[] { __PRETTY_FUNCTION__, "--remote-agent", "DBusRemoteAgent", bus_arg.c_str(), "--local-agent", "TheAlwaysDenyingLocalAgent", "--for-service", service_name, "--store-bus", "session_with_address_from_env" }; auto configuration = core::trust::Daemon::Skeleton::Configuration::from_command_line(10, argv); return core::trust::Daemon::Skeleton::main(configuration); }, core::posix::StandardStream::empty); // Wait for everything to be setup std::this_thread::sleep_for(std::chrono::milliseconds{500}); // And inject a request into the stub std::string answer; for (int feature = 0; feature < 50; feature++) { stub.cin() << core::posix::this_process::instance().pid() << " " << ::getuid() << " " << feature << std::endl; stub.cout() >> answer; } // Wait for all requests to be answered std::this_thread::sleep_for(std::chrono::milliseconds{500}); // Sigterm both stub and skeleton. skeleton.send_signal_or_throw(core::posix::Signal::sig_term); stub.send_signal_or_throw(core::posix::Signal::sig_term); // Expect both of them to exit with success. EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); } trust-store-2.0.0+16.04.20160119/tests/cached_agent_test.cpp0000644000015600001650000001752112647452272023703 0ustar pbuserpbgroup00000000000000/* * 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 "mock_agent.h" #include "mock_store.h" #include "the.h" namespace { struct MockReporter : public core::trust::CachedAgent::Reporter { /** @brief Invoked whenever the implementation was able to resolve a cached request. */ MOCK_METHOD2(report_cached_answer_found, void(const core::trust::Agent::RequestParameters&, const core::trust::Request&)); /** @brief Invoked whenever the implementation called out to an agent to prompt the user for trust. */ MOCK_METHOD2(report_user_prompted_for_trust, void(const core::trust::Agent::RequestParameters&, const core::trust::Request::Answer&)); }; std::shared_ptr a_null_agent() { return std::shared_ptr{}; } std::shared_ptr> a_mocked_agent() { return std::make_shared>(); } std::shared_ptr a_null_store() { return std::shared_ptr{}; } std::shared_ptr> a_mocked_store() { return std::make_shared>(); } std::shared_ptr> a_mocked_query() { return std::make_shared>(); } std::shared_ptr> a_mocked_reporter() { return std::make_shared>(); } core::trust::Request::Answer throw_a_dice() { // We seed the rng with the current time to ensure randomness across test runs. static std::default_random_engine generator { static_cast(std::chrono::system_clock::now().time_since_epoch().count()) }; // Our dice :) static std::uniform_int_distribution distribution { 1, 6 }; return distribution(generator) <= 3 ? core::trust::Request::Answer::denied : core::trust::Request::Answer::granted; } } TEST(CachedAgent, ctor_throws_for_missing_agent_implementation) { core::trust::CachedAgent::Configuration configuration { a_null_agent(), a_mocked_store(), a_mocked_reporter() }; EXPECT_THROW(core::trust::CachedAgent agent{configuration}, std::logic_error); } TEST(RequestProcessing, ctor_throws_for_missing_store_implementation) { core::trust::CachedAgent::Configuration configuration { a_mocked_agent(), a_null_store(), a_mocked_reporter() }; EXPECT_THROW(core::trust::CachedAgent agent{configuration}, std::logic_error); } TEST(CachedAgent, queries_store_for_cached_results_and_returns_cached_value) { using namespace ::testing; auto answer = throw_a_dice(); auto params = the::default_request_parameters_for_testing(); core::trust::Request request { params.application.id, params.feature, std::chrono::system_clock::now(), answer }; auto mocked_agent = a_mocked_agent(); auto mocked_query = a_mocked_query(); auto mocked_store = a_mocked_store(); auto mocked_reporter = a_mocked_reporter(); ON_CALL(*mocked_query, status()) .WillByDefault( Return( core::trust::Store::Query::Status::has_more_results)); ON_CALL(*mocked_query, current()) .WillByDefault( Return( request)); ON_CALL(*mocked_store, query()) .WillByDefault( Return( mocked_query)); EXPECT_CALL(*mocked_store, query()).Times(1); // We expect the processor to limit the query to the respective application id // and to the respective feature. EXPECT_CALL(*mocked_query, for_application_id(params.application.id)).Times(1); EXPECT_CALL(*mocked_query, for_feature(params.feature)).Times(1); // The setup ensures that a previously stored answer is available in the store. // For that, the agent should not be queried. EXPECT_CALL(*mocked_agent, authenticate_request_with_parameters(_)).Times(0); // We expect the implementation to call into the reporter with the request // resolved from the cache, and returning early, thus not reporting any user prompting. EXPECT_CALL(*mocked_reporter, report_cached_answer_found(params, _)).Times(1); EXPECT_CALL(*mocked_reporter, report_user_prompted_for_trust(params, _)).Times(0); core::trust::CachedAgent::Configuration configuration { mocked_agent, mocked_store, mocked_reporter }; core::trust::CachedAgent agent { configuration }; EXPECT_EQ(answer, agent.authenticate_request_with_parameters(params)); } TEST(CachedAgent, queries_agent_if_no_cached_results_and_returns_users_answer) { using namespace ::testing; auto answer = throw_a_dice(); auto params = the::default_request_parameters_for_testing(); core::trust::Agent::RequestParameters agent_params { params.application.uid, params.application.pid, params.application.id, params.feature, params.description }; core::trust::Request request { params.application.id, params.feature, std::chrono::system_clock::now(), answer }; auto mocked_agent = a_mocked_agent(); auto mocked_query = a_mocked_query(); auto mocked_store = a_mocked_store(); auto mocked_reporter = a_mocked_reporter(); ON_CALL(*mocked_agent, authenticate_request_with_parameters(agent_params)) .WillByDefault( Return( answer)); // We return EndOfRecord for queries, and expect the request processor // to subsequently ask the user for his answer. ON_CALL(*mocked_query, status()) .WillByDefault( Return( core::trust::Store::Query::Status::eor)); ON_CALL(*mocked_store, query()) .WillByDefault( Return( mocked_query)); EXPECT_CALL(*mocked_query, current()).Times(0); EXPECT_CALL(*mocked_store, query()).Times(1); // We expect the processor to limit the query to the respective application id // and to the respective feature. EXPECT_CALL(*mocked_query, for_application_id(params.application.id)).Times(1); EXPECT_CALL(*mocked_query, for_feature(params.feature)).Times(1); // The setup ensures that a previously stored answer is available in the store. // For that, the agent should not be queried. EXPECT_CALL(*mocked_agent, authenticate_request_with_parameters(agent_params)).Times(1); // We expect the implementation to *not* call into the reporter as there is no request // available from the cache. Instead the user should have been prompted. EXPECT_CALL(*mocked_reporter, report_cached_answer_found(params, _)).Times(0); EXPECT_CALL(*mocked_reporter, report_user_prompted_for_trust(params, _)).Times(1); core::trust::CachedAgent::Configuration configuration { mocked_agent, mocked_store, mocked_reporter }; core::trust::CachedAgent agent { configuration }; EXPECT_EQ(answer, agent.authenticate_request_with_parameters(params)); } trust-store-2.0.0+16.04.20160119/tests/mock_store.h0000644000015600001650000000536112647452272022070 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef MOCK_STORE_H_ #define MOCK_STORE_H_ #include #include #include struct MockStore : public core::trust::Store { struct MockQuery : public core::trust::Store::Query { /** @brief Access the status of the query. */ MOCK_CONST_METHOD0(status, core::trust::Store::Query::Status()); /** @brief Limit the query to a specific application Id. */ MOCK_METHOD1(for_application_id, void(const std::string&)); /** @brief Limit the query to a service-specific feature. */ MOCK_METHOD1(for_feature, void(core::trust::Feature)); /** @brief Limit the query to the specified time interval. */ MOCK_METHOD2(for_interval, void(const core::trust::Request::Timestamp&, const core::trust::Request::Timestamp&)); /** @brief Limit the query for a specific answer. */ MOCK_METHOD1(for_answer, void(core::trust::Request::Answer)); /** @brief Query all stored requests. */ MOCK_METHOD0(all, void()); /** @brief Execute the query against the store. */ MOCK_METHOD0(execute, void()); /** @brief After successful execution, advance to the next request. */ MOCK_METHOD0(next, void()); /** @brief After successful execution, erase the current element and advance to the next request. */ MOCK_METHOD0(erase, void()); /** @brief Access the request the query currently points to. */ MOCK_METHOD0(current, core::trust::Request()); }; /** @brief Resets the state of the store, implementations should discard * all persistent and non-persistent state. */ MOCK_METHOD0(reset, void()); /** @brief Add the provided request to the store. When this function returns true, * the request has been persisted by the implementation. */ MOCK_METHOD1(add, void(const core::trust::Request&)); /** * @brief Create a query for this store. */ MOCK_METHOD0(query, std::shared_ptr()); }; #endif // MOCK_STORE_H_ trust-store-2.0.0+16.04.20160119/tests/white_listing_agent_test.cpp0000644000015600001650000000714712647452272025350 0ustar pbuserpbgroup00000000000000/* * 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 "mock_agent.h" #include "the.h" #include namespace { std::shared_ptr> a_mocked_agent() { return std::make_shared>(); } struct MockWhiteListingPredicate { core::trust::WhiteListingAgent::WhiteListingPredicate to_functional() { return [this](const core::trust::Agent::RequestParameters& params) { return is_whitelisted(params); }; } MOCK_METHOD1(is_whitelisted, bool(const core::trust::Agent::RequestParameters&)); }; } TEST(WhiteListingAgent, ctor_throws_for_null_agent) { EXPECT_ANY_THROW(core::trust::WhiteListingAgent ( core::trust::WhiteListingAgent::always_grant_for_unconfined(), std::shared_ptr() )); } TEST(WhiteListingAgent, invokes_predicate_for_incoming_request_and_dispatches_to_impl_for_non_whitelisted) { 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"}; MockWhiteListingPredicate wlp; EXPECT_CALL(wlp, is_whitelisted(params)) .Times(1) .WillRepeatedly(Return(false)); EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params)) .Times(1) .WillRepeatedly(Return(core::trust::Request::Answer::denied)); core::trust::WhiteListingAgent agent{wlp.to_functional(), mock_agent}; EXPECT_EQ(core::trust::Request::Answer::denied, agent.authenticate_request_with_parameters(params)); } TEST(WhiteListingAgent, invokes_predicate_for_incoming_request_and_returns_immediately_for_non_whitelisted) { 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"}; MockWhiteListingPredicate wlp; EXPECT_CALL(wlp, is_whitelisted(params)) .Times(1) .WillRepeatedly(Return(true)); EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(params)) .Times(0); core::trust::WhiteListingAgent agent{wlp.to_functional(), mock_agent}; EXPECT_EQ(core::trust::Request::Answer::granted, agent.authenticate_request_with_parameters(params)); } TEST(WhiteListingAgent, unconfined_predicate_only_returns_true_for_unconfined) { using namespace ::testing; auto predicate = core::trust::WhiteListingAgent::always_grant_for_unconfined(); auto params = the::default_request_parameters_for_testing(); params.application.id = params.application.id + std::string{"_app"} + std::string{"_1.2.3"}; EXPECT_FALSE(predicate(params)); params.application.id = "unconfined"; EXPECT_TRUE(predicate(params)); } trust-store-2.0.0+16.04.20160119/tests/remote_agent_test.cpp0000644000015600001650000007554712647452312023776 0ustar pbuserpbgroup00000000000000/* * 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ß */ // Implementation-specific header #include #include #include #include "mock_agent.h" #include "process_exited_successfully.h" #include #include #include #include #include #include #include namespace { struct MockRemoteAgentStub : public core::trust::remote::Agent::Stub { // Sends out the request to the receiving end, either returning an answer // or throwing an exception if no conclusive answer could be obtained from // the user. MOCK_METHOD1(send, core::trust::Request::Answer(const core::trust::Agent::RequestParameters&)); }; } TEST(RemoteAgentStub, calls_send_for_handling_requests_and_returns_answer) { using namespace ::testing; core::trust::Agent::RequestParameters parameters { core::trust::Uid{21}, core::trust::Pid{42}, std::string{"does.not.exist"}, core::trust::Feature{}, std::string{"some meaningless description"} }; MockRemoteAgentStub stub; EXPECT_CALL(stub, send(parameters)) .Times(1) .WillOnce(Return(core::trust::Request::Answer::granted)); EXPECT_EQ(core::trust::Request::Answer::granted, stub.authenticate_request_with_parameters(parameters)); } TEST(RemoteAgentSkeleton, calls_out_to_implementation) { using namespace ::testing; core::trust::Agent::RequestParameters parameters { core::trust::Uid{21}, core::trust::Pid{42}, std::string{"does.not.exist"}, core::trust::Feature{}, std::string{"some meaningless description"} }; std::shared_ptr mock_agent { new MockAgent{} }; core::trust::remote::Agent::Skeleton skeleton { mock_agent }; EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(parameters)) .Times(1) .WillOnce(Return(core::trust::Request::Answer::granted)); EXPECT_EQ(core::trust::Request::Answer::granted, skeleton.authenticate_request_with_parameters(parameters)); } TEST(RemoteAgentStubSessionRegistry, adding_and_removing_of_a_valid_session_works) { using Session = core::trust::remote::posix::Stub::Session; boost::asio::io_service io_service; Session::Ptr session { new Session { io_service } }; Session::Registry::Ptr registry { new Session::Registry{} }; core::trust::Uid uid{::getuid()}; EXPECT_NO_THROW(registry->add_session_for_uid(uid, session);); EXPECT_TRUE(registry->has_session_for_uid(uid)); EXPECT_NE(nullptr, registry->resolve_session_for_uid(uid)); EXPECT_NO_THROW(registry->remove_session_for_uid(uid);); EXPECT_FALSE(registry->has_session_for_uid(uid)); EXPECT_THROW(registry->resolve_session_for_uid(uid), std::out_of_range); } TEST(RemoteAgentStubSessionRegistry, adding_a_null_session_throws) { using Session = core::trust::remote::posix::Stub::Session; Session::Ptr session; Session::Registry::Ptr registry { new Session::Registry{} }; core::trust::Uid uid{::getuid()}; EXPECT_THROW(registry->add_session_for_uid(uid, session), std::logic_error); EXPECT_FALSE(registry->has_session_for_uid(uid)); EXPECT_THROW(registry->resolve_session_for_uid(uid), std::out_of_range); } TEST(RemoteAgentStubSessionRegistry, resolving_a_non_existing_session_throws) { using Session = core::trust::remote::posix::Stub::Session; Session::Registry::Ptr registry { new Session::Registry{} }; core::trust::Uid uid{::getuid()}; EXPECT_THROW(registry->resolve_session_for_uid(uid), std::out_of_range); } TEST(RemoteAgentStubSessionRegistry, removing_a_non_existing_session_does_not_throw) { using Session = core::trust::remote::posix::Stub::Session; Session::Registry::Ptr registry { new Session::Registry{} }; core::trust::Uid uid{::getuid()}; EXPECT_FALSE(registry->has_session_for_uid(uid)); EXPECT_NO_THROW(registry->remove_session_for_uid(uid)); } namespace { struct UnixDomainSocketRemoteAgent : public ::testing::Test { static constexpr const char* endpoint_for_testing { "/tmp/unlikely.to.ever.be.used.by.someone.else" }; UnixDomainSocketRemoteAgent() : keep_alive{io_service}, worker{[this]() { io_service.run(); }} { std::remove(endpoint_for_testing); } ~UnixDomainSocketRemoteAgent() { io_service.stop(); if (worker.joinable()) worker.join(); } // Returns the default stub setup for testing core::trust::remote::posix::Stub::Configuration the_default_stub_configuration() { return core::trust::remote::posix::Stub::Configuration { io_service, boost::asio::local::stream_protocol::endpoint{UnixDomainSocketRemoteAgent::endpoint_for_testing}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(), std::make_shared() }; } // Returns a peer ready to be forked that connects to the endpoint_for_testing // and immediately exits, checking for any sort of testing failures that might have // occured in between. static std::function a_raw_peer_immediately_exiting() { return []() { boost::asio::io_service io_service; boost::asio::io_service::work keep_alive{io_service}; std::thread worker{[&io_service]() { io_service.run(); }}; boost::asio::local::stream_protocol::socket socket{io_service}; EXPECT_NO_THROW(socket.connect(boost::asio::local::stream_protocol::endpoint{UnixDomainSocketRemoteAgent::endpoint_for_testing})); io_service.stop(); if(worker.joinable()) worker.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; } boost::asio::io_service io_service; boost::asio::io_service::work keep_alive; std::thread worker; }; struct MockProcessStartTimeResolver { virtual ~MockProcessStartTimeResolver() = default; core::trust::remote::helpers::ProcessStartTimeResolver to_functional() { return [this](core::trust::Pid pid) { return resolve_process_start_time(pid); }; } MOCK_METHOD1(resolve_process_start_time, std::int64_t(core::trust::Pid)); }; } TEST_F(UnixDomainSocketRemoteAgent, accepts_connections_on_endpoint) { auto stub = core::trust::remote::posix::Stub::create_stub_for_configuration( the_default_stub_configuration()); // Make sure that the stub and all its threads are spun up. std::this_thread::sleep_for(std::chrono::milliseconds{500}); core::posix::ChildProcess child = core::posix::fork( UnixDomainSocketRemoteAgent::a_raw_peer_immediately_exiting(), core::posix::StandardStream::empty); EXPECT_TRUE(ProcessExitedSuccessfully(child.wait_for(core::posix::wait::Flags::untraced))); EXPECT_TRUE(stub->has_session_for_uid(core::trust::Uid{::getuid()})); } TEST_F(UnixDomainSocketRemoteAgent, queries_peer_credentials_for_incoming_connection) { static const core::trust::Uid uid{42}; bool peer_credentials_queried{false}; auto config = the_default_stub_configuration(); config.peer_credentials_resolver = [&peer_credentials_queried](int) { peer_credentials_queried = true; return std::make_tuple(uid, core::trust::Pid{42}, core::trust::Gid{42}); }; auto stub = core::trust::remote::posix::Stub::create_stub_for_configuration(config); core::posix::ChildProcess child = core::posix::fork( UnixDomainSocketRemoteAgent::a_raw_peer_immediately_exiting(), core::posix::StandardStream::empty); EXPECT_TRUE(ProcessExitedSuccessfully(child.wait_for(core::posix::wait::Flags::untraced))); EXPECT_TRUE(peer_credentials_queried); EXPECT_TRUE(stub->has_session_for_uid(uid)); } TEST_F(UnixDomainSocketRemoteAgent, stub_and_skeleton_query_process_start_time_for_request) { using namespace ::testing; // We need to make sure that we have a valid pid. auto app = core::posix::fork([]() { while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500}); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); // skeleton --| good to go |--> stub core::testing::CrossProcessSync cps; NiceMock process_start_time_resolver; auto config = the_default_stub_configuration(); config.start_time_resolver = process_start_time_resolver.to_functional(); auto stub = core::trust::remote::posix::Stub::create_stub_for_configuration(config); core::posix::ChildProcess child = core::posix::fork([&cps]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); boost::asio::io_service io_service; boost::asio::io_service::work work{io_service}; std::thread worker{[&io_service] { io_service.run(); }}; NiceMock process_start_time_resolver; EXPECT_CALL(process_start_time_resolver, resolve_process_start_time(_)) .Times(1) .WillRepeatedly(Return(42)); auto mock_agent = std::make_shared<::testing::NiceMock>(); EXPECT_CALL(*mock_agent, authenticate_request_with_parameters(_)) .Times(1) .WillRepeatedly(Return(core::trust::Request::Answer::denied)); core::trust::remote::posix::Skeleton::Configuration config { mock_agent, io_service, boost::asio::local::stream_protocol::endpoint{UnixDomainSocketRemoteAgent::endpoint_for_testing}, process_start_time_resolver.to_functional(), core::trust::remote::helpers::aa_get_task_con_app_id_resolver(), "Just a test for %1%.", true }; auto skeleton = core::trust::remote::posix::Skeleton::create_skeleton_for_configuration(config); cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); io_service.stop(); if (worker.joinable()) worker.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); 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)); EXPECT_EQ(core::trust::Request::Answer::denied, stub->authenticate_request_with_parameters( core::trust::Agent::RequestParameters { core::trust::Uid{::getuid()}, core::trust::Pid{app.pid()}, "", core::trust::Feature{}, "" })); child.send_signal_or_throw(core::posix::Signal::sig_term); EXPECT_TRUE(ProcessExitedSuccessfully(child.wait_for(core::posix::wait::Flags::untraced))); } /************************************** Full blown acceptance tests go here. **************************************/ #include namespace { static constexpr const char* endpoint_for_acceptance_testing { "/tmp/endpoint.for.acceptance.testing" }; // Our rng used in acceptance testing, seeded with the current time since // the epoch in seconds. static std::default_random_engine rng { static_cast(std::time(nullptr)) }; // Our dice static std::uniform_int_distribution dice(1,6); } TEST(UnixDomainSocket, a_service_can_query_a_remote_agent) { using namespace ::testing; std::remove(endpoint_for_acceptance_testing); core::testing::CrossProcessSync stub_ready, // signals stub --| I'm ready |--> skeleton skeleton_ready; // signals skeleton --| I'm ready |--> stub auto app = core::posix::fork([]() { while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500}); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); // We sample an answer by throwing a dice. const core::trust::Request::Answer answer { dice(rng) <= 3 ? core::trust::Request::Answer::denied : core::trust::Request::Answer::granted }; const core::trust::Uid app_uid{::getuid()}; const core::trust::Pid app_pid{app.pid()}; auto stub = core::posix::fork([app_uid, app_pid, answer, &stub_ready, &skeleton_ready]() { boost::asio::io_service io_service; boost::asio::io_service::work keep_alive{io_service}; std::thread worker{[&io_service]() { io_service.run(); }}; core::trust::remote::posix::Stub::Configuration config { io_service, boost::asio::local::stream_protocol::endpoint{endpoint_for_acceptance_testing}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::posix::Stub::get_sock_opt_credentials_resolver(), std::make_shared() }; auto stub = core::trust::remote::posix::Stub::create_stub_for_configuration(config); std::this_thread::sleep_for(std::chrono::milliseconds{500}); stub_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); skeleton_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000}); for (unsigned int i = 0; i < 100; i++) { EXPECT_EQ(answer, stub->authenticate_request_with_parameters( core::trust::Agent::RequestParameters { app_uid, app_pid, "", core::trust::Feature{}, "" })); } io_service.stop(); if (worker.joinable()) worker.join(); return Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); auto skeleton = core::posix::fork([answer, &stub_ready, &skeleton_ready]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); boost::asio::io_service io_service; boost::asio::io_service::work keep_alive{io_service}; std::thread worker{[&io_service]() { io_service.run(); }}; // We have to rely on a MockAgent to break the dependency on a running Mir instance. auto mock_agent = std::make_shared<::testing::NiceMock>(); ON_CALL(*mock_agent, authenticate_request_with_parameters(_)) .WillByDefault(Return(answer)); core::trust::remote::posix::Skeleton::Configuration config { mock_agent, io_service, boost::asio::local::stream_protocol::endpoint{endpoint_for_acceptance_testing}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::helpers::aa_get_task_con_app_id_resolver(), "Just a test for %1%.", true }; stub_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000}); auto skeleton = core::trust::remote::posix::Skeleton::create_skeleton_for_configuration(config); std::this_thread::sleep_for(std::chrono::milliseconds{500}); skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); trap->run(); io_service.stop(); if (worker.joinable()) worker.join(); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); skeleton.send_signal_or_throw(core::posix::Signal::sig_term); EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); app.send_signal_or_throw(core::posix::Signal::sig_kill); } // A test case using a standalone service that is not using our header files. // The test-case here is equivalent to the code that we are wiring up in the // Android camera service. #include #include namespace { // We declare another struct for testing purposes. struct Request { uid_t uid; pid_t pid; ::uint64_t feature; ::int64_t start_time; }; } TEST(UnixDomainSocket, a_standalone_service_can_query_a_remote_agent) { using namespace ::testing; std::remove(endpoint_for_acceptance_testing); core::testing::CrossProcessSync stub_ready, // signals stub --| I'm ready |--> skeleton skeleton_ready; // signals skeleton --| I'm ready |--> stub auto app = core::posix::fork([]() { while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500}); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); // We sample an answer by throwing a dice. const core::trust::Request::Answer answer { dice(rng) <= 3 ? core::trust::Request::Answer::denied : core::trust::Request::Answer::granted }; const core::trust::Uid app_uid{::getuid()}; const core::trust::Pid app_pid{app.pid()}; auto start_time_helper = core::trust::remote::helpers::proc_stat_start_time_resolver(); auto app_start_time = start_time_helper(core::trust::Pid{app.pid()}); auto stub = core::posix::fork([app_uid, app_pid, app_start_time, answer, &stub_ready, &skeleton_ready]() { // Stores all known connections indexed by user id std::map known_connections_by_user_id; static const int socket_error_code{-1}; // We create a unix domain socket int socket_fd = ::socket(PF_UNIX, SOCK_STREAM, 0); if (socket_fd == socket_error_code) { ::perror("Could not create unix stream socket"); return core::posix::exit::Status::failure; } // Prepare for binding to endpoint in file system. // Consciously ignoring errors here. ::unlink(endpoint_for_acceptance_testing); // Setup address sockaddr_un address; ::memset(&address, 0, sizeof(sockaddr_un)); address.sun_family = AF_UNIX; ::snprintf(address.sun_path, 108, endpoint_for_acceptance_testing); // And bind to the endpoint in the filesystem. static const int bind_error_code{-1}; int rc = ::bind(socket_fd, reinterpret_cast(&address), sizeof(sockaddr_un)); if (rc == bind_error_code) { ::perror("Could not bind to endpoint"); return core::posix::exit::Status::failure; } // Start listening for incoming connections. static const int listen_error_code{-1}; static const int back_log_size{5}; rc = ::listen(socket_fd, back_log_size); if (rc == listen_error_code) { ::perror("Could not start listening for incoming connections"); return core::posix::exit::Status::failure; } // Spawn a thread for accepting connections. std::thread acceptor([socket_fd, &known_connections_by_user_id]() { bool keep_on_running{true}; // Error code when accepting connections. static const int accept_error_code{-1}; // Error code when querying socket options. static const int get_sock_opt_error = -1; // Some state we preserve across loop iterations. sockaddr_un address; socklen_t address_length = sizeof(sockaddr_un); ucred peer_credentials { 0, 0, 0 }; socklen_t len = sizeof(peer_credentials); while(keep_on_running) { address_length = sizeof(sockaddr_un); int connection_fd = ::accept(socket_fd, reinterpret_cast(&address), &address_length); if (connection_fd == accept_error_code) { switch (errno) { case EINTR: case EAGAIN: keep_on_running = true; break; default: keep_on_running = false; break; } } else { // We query the peer credentials len = sizeof(ucred); auto rc = ::getsockopt(connection_fd, SOL_SOCKET, SO_PEERCRED, &peer_credentials, &len); if (rc == get_sock_opt_error) { ::perror("Could not query peer credentials"); } else { known_connections_by_user_id.insert( std::make_pair( peer_credentials.uid, connection_fd)); } } } }); // This is obviously super ugly, but we would like to avoid implementing // a full blown reactor pattern. acceptor.detach(); 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::milliseconds{500}); Request request { app_uid.value, app_pid.value, 0, app_start_time }; for (unsigned int i = 0; i < 100; i++) { std::int32_t answer_from_socket; int socket = known_connections_by_user_id.at(::getuid()); EXPECT_NE(-1, ::write(socket, &request, sizeof(Request))); EXPECT_NE(-1, ::read(socket, &answer_from_socket, sizeof(std::int32_t))); EXPECT_EQ(static_cast(answer), answer_from_socket); } ::close(socket_fd); return Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); auto skeleton = core::posix::fork([answer, &stub_ready, &skeleton_ready]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); boost::asio::io_service io_service; boost::asio::io_service::work keep_alive{io_service}; std::thread worker{[&io_service]() { io_service.run(); }}; // We have to rely on a MockAgent to break the dependency on a running Mir instance. auto mock_agent = std::make_shared<::testing::NiceMock>(); ON_CALL(*mock_agent, authenticate_request_with_parameters(_)) .WillByDefault(Return(answer)); core::trust::remote::posix::Skeleton::Configuration config { mock_agent, io_service, boost::asio::local::stream_protocol::endpoint{endpoint_for_acceptance_testing}, core::trust::remote::helpers::proc_stat_start_time_resolver(), core::trust::remote::helpers::aa_get_task_con_app_id_resolver(), "Just a test for %1%.", true }; stub_ready.wait_for_signal_ready_for(std::chrono::milliseconds{1000}); auto skeleton = core::trust::remote::posix::Skeleton::create_skeleton_for_configuration(config); skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); trap->run(); io_service.stop(); if (worker.joinable()) worker.join(); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); skeleton.send_signal_or_throw(core::posix::Signal::sig_term); EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); app.send_signal_or_throw(core::posix::Signal::sig_kill); } namespace { struct DBus : public core::dbus::testing::Fixture { }; std::string service_name { "JustForTestingPurposes" }; } // A test-case using the remote dbus agent implementation. TEST_F(DBus, a_service_can_query_a_remote_agent) { using namespace ::testing; core::testing::CrossProcessSync stub_ready, // signals stub --| I'm ready |--> skeleton skeleton_ready; // signals skeleton --| I'm ready |--> stub auto app = core::posix::fork([]() { while(true) std::this_thread::sleep_for(std::chrono::milliseconds{500}); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); // We sample an answer by throwing a dice. const core::trust::Request::Answer answer { dice(rng) <= 3 ? core::trust::Request::Answer::denied : core::trust::Request::Answer::granted }; const core::trust::Uid app_uid{::getuid()}; const core::trust::Pid app_pid{app.pid()}; auto stub = core::posix::fork([this, app_uid, app_pid, answer, &stub_ready, &skeleton_ready]() { core::trust::Agent::RequestParameters ref_params { app_uid, app_pid, "just.a.testing.id", core::trust::Feature{40}, "just an example description" }; auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread worker{[bus]() { bus->run(); }}; std::string dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name; auto service = core::dbus::Service::add_service(bus, dbus_service_name); auto object = service->add_object_for_path(core::dbus::types::ObjectPath { core::trust::remote::dbus::default_agent_registry_path }); core::trust::remote::dbus::Agent::Stub::Configuration config { object, bus }; auto stub = std::make_shared(config); 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)); bus->stop(); if (worker.joinable()) worker.join(); return Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }, core::posix::StandardStream::empty); auto skeleton = core::posix::fork([this, answer, &stub_ready, &skeleton_ready]() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread worker{[bus]() { bus->run(); }}; // We have to rely on a MockAgent to break the dependency on a running Mir instance. auto mock_agent = std::make_shared<::testing::NiceMock>(); 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}); auto service = core::dbus::Service::use_service(bus, dbus_service_name); auto object = service->object_for_path(core::dbus::types::ObjectPath { 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(std::move(config)); skeleton_ready.try_signal_ready_for(std::chrono::milliseconds{1000}); trap->run(); bus->stop(); if (worker.joinable()) worker.join(); return core::posix::exit::Status::success; }, core::posix::StandardStream::empty); EXPECT_TRUE(ProcessExitedSuccessfully(stub.wait_for(core::posix::wait::Flags::untraced))); skeleton.send_signal_or_throw(core::posix::Signal::sig_term); EXPECT_TRUE(ProcessExitedSuccessfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); app.send_signal_or_throw(core::posix::Signal::sig_kill); } trust-store-2.0.0+16.04.20160119/tests/share/0000755000015600001650000000000012647452606020650 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/tests/share/applications/0000755000015600001650000000000012647452606023336 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/tests/share/applications/valid.pkg_app_0.0.0.desktop0000644000015600001650000000221712647452305030161 0ustar pbuserpbgroup00000000000000[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 trust-store-2.0.0+16.04.20160119/tests/privilege_escalation_prevention_agent_test.cpp0000644000015600001650000000663612647452305031137 0ustar pbuserpbgroup00000000000000/* * 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()); } trust-store-2.0.0+16.04.20160119/tests/process_exited_successfully.h0000644000015600001650000000217112647452272025543 0ustar pbuserpbgroup00000000000000/* * 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 ::testing::AssertionResult ProcessExitedSuccessfully(const core::posix::wait::Result& result) { if (core::posix::wait::Result::Status::exited != result.status) return ::testing::AssertionFailure(); if (core::posix::exit::Status::success != result.detail.if_exited.status) return ::testing::AssertionFailure(); return ::testing::AssertionSuccess(); } trust-store-2.0.0+16.04.20160119/tests/the.h0000644000015600001650000000262712647452272020505 0ustar pbuserpbgroup00000000000000/* * 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 // Concrete values for reuse in testing namespace the { core::trust::Pid default_pid_for_testing() { return core::trust::Pid{42}; } core::trust::Uid default_uid_for_testing() { return core::trust::Uid{42}; } core::trust::Feature default_feature_for_testing() { return core::trust::Feature{0}; } core::trust::Agent::RequestParameters default_request_parameters_for_testing() { return core::trust::Agent::RequestParameters { default_uid_for_testing(), default_pid_for_testing(), "this.is.just.for.testing.purposes", default_feature_for_testing(), "Someone wants to access all your credentials and steal your identity." }; } } trust-store-2.0.0+16.04.20160119/tests/test_data.h.in0000644000015600001650000000221412647452305022267 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef TEST_DATA_H_ #define TEST_DATA_H_ namespace core { namespace trust { 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" }; static constexpr const char* trust_store_preseed_executable_in_build_dir { "@CMAKE_BINARY_DIR@/src/trust-store-preseed" }; } } } #endif // TEST_DATA_H_ trust-store-2.0.0+16.04.20160119/tests/CMakeLists.txt0000644000015600001650000001217712647452312022310 0ustar pbuserpbgroup00000000000000include_directories(${CMAKE_BINARY_DIR}/src) # Build with system gmock and embedded gtest set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory") set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") set (GTEST_INCLUDE_DIR "${GMOCK_SOURCE_DIR}/gtest/include" CACHE PATH "gtest source include directory") add_subdirectory(${GMOCK_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock") pkg_check_modules(DBUS dbus-1) add_definitions(-DCORE_DBUS_ENABLE_GOOGLE_TEST_FIXTURE) configure_file(test_data.h.in test_data.h @ONLY) include_directories( ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ${GMOCK_INCLUDE_DIR} ${GTEST_INCLUDE_DIR} ${PROCESS_CPP_INCLUDE_DIRS} ${DBUS_INCLUDE_DIRS} ) add_executable( bug_1387734 bug_1387734.cpp ) add_executable( trust_store_test trust_store_test.cpp ) add_executable( remote_trust_store_test remote_trust_store_test.cpp ) add_executable( request_processor_test request_processor_test.cpp ) 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( app_id_formatting_trust_agent_test app_id_formatting_trust_agent_test.cpp ) add_executable( white_listing_agent_test white_listing_agent_test.cpp ) add_executable( privilege_escalation_prevention_agent_test privilege_escalation_prevention_agent_test.cpp ) add_executable( cached_agent_test cached_agent_test.cpp ) add_executable( daemon_test daemon_test.cpp ) add_executable( dbus_test dbus_test.cpp ) add_executable( preseed_test preseed_test.cpp ) target_link_libraries( bug_1387734 trust-store gmock gtest gtest_main ) target_link_libraries( trust_store_test trust-store gmock gtest gtest_main ) target_link_libraries( remote_trust_store_test trust-store gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( request_processor_test trust-store gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( remote_agent_test trust-store gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( app_id_formatting_trust_agent_test trust-store gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( white_listing_agent_test trust-store gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) 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 gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( daemon_test trust-store trust-stored gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( dbus_test trust-store trust-stored gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) target_link_libraries( preseed_test trust-store-preseed-helper gmock gtest gtest_main ${PROCESS_CPP_LIBRARIES} ) add_test(bug_1387734 ${CMAKE_CURRENT_BINARY_DIR}/bug_1387734) add_test(trust_store_test ${CMAKE_CURRENT_BINARY_DIR}/trust_store_test) add_test(remote_trust_store_test ${CMAKE_CURRENT_BINARY_DIR}/remote_trust_store_test) add_test(request_processor_test ${CMAKE_CURRENT_BINARY_DIR}/request_processor_test) add_test(remote_agent_test ${CMAKE_CURRENT_BINARY_DIR}/remote_agent_test) 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) install( TARGETS trust_store_test remote_trust_store_test request_processor_test remote_agent_test cached_agent_test daemon_test dbus_test RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/trust-store-tests ) # Test setups relying on optional build dependencies go here if (TRUST_STORE_MIR_AGENT_ENABLED) add_executable( mir_agent_test 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 gtest gtest_main ${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 RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/trust-store-tests ) endif () trust-store-2.0.0+16.04.20160119/tests/dbus_test.cpp0000644000015600001650000003633112647452312022246 0ustar pbuserpbgroup00000000000000/* * 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 #include #include "mock_agent.h" #include "process_exited_successfully.h" #include #include #include #include #include #include namespace { std::shared_ptr a_trap_for_sig_term() { auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); trap->signal_raised().connect([trap](core::posix::Signal) { trap->stop(); }); return trap; } struct BusFactoryType : public testing::TestWithParam> { }; struct DBusAgent : public core::dbus::testing::Fixture { static constexpr const char* agent_service_name { "core.trust.dbus.Agent" }; static constexpr const char* agent_path { "/core/trust/dbus/Agent" }; }; struct DBusAgentRegistry : public core::dbus::testing::Fixture { static constexpr const char* agent_registry_service_name { "core.trust.dbus.AgentRegistry" }; static constexpr const char* agent_registry_path { "/core/trust/dbus/AgentRegistry" }; }; struct MockAgentRegistry : public core::trust::Agent::Registry { // Registers an agent for the given uid. MOCK_METHOD2(register_agent_for_user, void(const core::trust::Uid&, const std::shared_ptr&)); // Removes the agent for the given uid from the registry MOCK_METHOD1(unregister_agent_for_user, void(const core::trust::Uid&)); }; core::trust::Agent::RequestParameters ref_params { core::trust::Uid{42}, core::trust::Pid{41}, "just.a.testing.id", core::trust::Feature{40}, "just an example description" }; } 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; core::testing::CrossProcessSync cps; auto skeleton = [this, &cps]() { auto trap = a_trap_for_sig_term(); auto agent = std::make_shared(); EXPECT_CALL(*agent, authenticate_request_with_parameters(_)) .Times(1) .WillRepeatedly(Return(core::trust::Request::Answer::denied)); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t{[bus]() { bus->run(); }}; auto service = core::dbus::Service::add_service(bus, agent_service_name); auto object = service->add_object_for_path(core::dbus::types::ObjectPath{agent_path}); core::trust::dbus::Agent::Skeleton skeleton { core::trust::dbus::Agent::Skeleton::Configuration { object, bus, [agent](const core::trust::Agent::RequestParameters& params) { return agent->authenticate_request_with_parameters(params); } } }; cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto stub = [this, &cps]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = core::dbus::Service::use_service(bus, agent_service_name); auto object = service->object_for_path(core::dbus::types::ObjectPath{agent_path}); core::trust::dbus::Agent::Stub stub { object }; std::thread t{[bus]() { bus->run(); }}; EXPECT_EQ(core::trust::Request::Answer::denied, stub.authenticate_request_with_parameters(ref_params)); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(skeleton, stub)); } TEST_F(DBusAgent, remote_invocation_throws_if_answer_non_conclusive) { using namespace ::testing; core::testing::CrossProcessSync cps; auto skeleton = [this, &cps]() { auto trap = a_trap_for_sig_term(); auto agent = std::make_shared(); EXPECT_CALL(*agent, authenticate_request_with_parameters(_)) .Times(1) .WillRepeatedly(Throw(std::logic_error{""})); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t{[bus]() { bus->run(); }}; auto service = core::dbus::Service::add_service(bus, agent_service_name); auto object = service->add_object_for_path(core::dbus::types::ObjectPath{agent_path}); core::trust::dbus::Agent::Skeleton skeleton { core::trust::dbus::Agent::Skeleton::Configuration { object, bus, [agent](const core::trust::Agent::RequestParameters& params) { return agent->authenticate_request_with_parameters(params); } } }; cps.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto stub = [this, &cps]() { cps.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = core::dbus::Service::use_service(bus, agent_service_name); auto object = service->object_for_path(core::dbus::types::ObjectPath{agent_path}); core::trust::dbus::Agent::Stub stub { object }; std::thread t{[bus]() { bus->run(); }}; EXPECT_ANY_THROW(stub.authenticate_request_with_parameters(ref_params)); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(skeleton, stub)); } TEST_F(DBusAgentRegistry, remote_invocation_works_correctly) { using namespace ::testing; static const int expected_invocation_count{10}; core::testing::CrossProcessSync service_ready, agent_registered; auto skeleton = [this, &service_ready, &agent_registered]() { auto trap = a_trap_for_sig_term(); core::trust::LockingAgentRegistry locking_agent_registry; MockAgentRegistry agent_registry; EXPECT_CALL(agent_registry, register_agent_for_user(_, _)) .Times(1) .WillRepeatedly(Invoke(&locking_agent_registry, &core::trust::LockingAgentRegistry::register_agent_for_user)); EXPECT_CALL(agent_registry, unregister_agent_for_user(_)) .Times(1); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); std::thread t{[bus]() { bus->run(); }}; std::thread u{[&locking_agent_registry, &agent_registered]() { agent_registered.wait_for_signal_ready_for(std::chrono::seconds{5}); auto agent = locking_agent_registry.agent_for_user(core::trust::Uid{::getuid()}); for (unsigned int i = 0; i < expected_invocation_count; i++) EXPECT_EQ(core::trust::Request::Answer::denied, agent->authenticate_request_with_parameters(ref_params)); }}; auto service = core::dbus::Service::add_service(bus, agent_registry_service_name); auto object = service->add_object_for_path(core::dbus::types::ObjectPath{agent_registry_path}); core::trust::dbus::AgentRegistry::Skeleton skeleton { core::trust::dbus::AgentRegistry::Skeleton::Configuration { object, bus, agent_registry } }; service_ready.try_signal_ready_for(std::chrono::milliseconds{500}); trap->run(); bus->stop(); if (t.joinable()) t.join(); if (u.joinable()) u.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; auto stub = [this, &service_ready, &agent_registered]() { service_ready.wait_for_signal_ready_for(std::chrono::milliseconds{500}); auto bus = session_bus(); bus->install_executor(core::dbus::asio::make_executor(bus)); auto service = core::dbus::Service::use_service(bus, agent_registry_service_name); auto agent_object = service->add_object_for_path(core::dbus::types::ObjectPath{DBusAgent::agent_path}); auto agent_registry_object = service->object_for_path(core::dbus::types::ObjectPath{DBusAgentRegistry::agent_registry_path}); struct State { void wait() { std::unique_lock ul(guard); wait_condition.wait_for( ul, std::chrono::milliseconds{1000}, [this]() { return invocation_count == expected_invocation_count; }); } void notify() { std::lock_guard lg(guard); invocation_count++; wait_condition.notify_all(); } std::uint32_t invocation_count{0}; std::mutex guard; std::condition_variable wait_condition; } state; auto agent = std::make_shared(); EXPECT_CALL(*agent, authenticate_request_with_parameters(ref_params)) .Times(expected_invocation_count) .WillRepeatedly( DoAll( InvokeWithoutArgs(&state, &State::notify), Return(core::trust::Request::Answer::denied))); core::trust::dbus::AgentRegistry::Stub stub { core::trust::dbus::AgentRegistry::Stub::Configuration { agent_registry_object, core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(), service, bus } }; std::thread t{[bus]() { bus->run(); }}; // We register for the current user id. stub.register_agent_for_user(core::trust::Uid{::getuid()}, agent); // Tell the other side that we are good to go. agent_registered.try_signal_ready_for(std::chrono::milliseconds{500}); // We wait until we have seen 5 invocations state.wait(); // And unregister again. stub.unregister_agent_for_user(core::trust::Uid{::getuid()}); bus->stop(); if (t.joinable()) t.join(); return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; }; EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(skeleton, stub)); } trust-store-2.0.0+16.04.20160119/tests/bug_1387734.cpp0000644000015600001650000000417612647452272021756 0ustar pbuserpbgroup00000000000000/* * 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 namespace { static const std::string service_name{"52EB2494-76F2-4ABB-A188-20B2D5B3CC94"}; } // See https://bugs.launchpad.net/ubuntu-rtm/+source/trust-store/+bug/1387734 TEST(TrustStore, cached_user_replies_are_sorted_by_age_in_descending_order) { auto store = core::trust::create_default_store(service_name); store->reset(); const std::string app1{"com.does.not.exist.app1"}; // This is the older reply, the user answered granted. core::trust::Request r1 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{0}), core::trust::Request::Answer::granted }; // This is the newer reply, the user revoked the trust. core::trust::Request r2 { app1, core::trust::Feature{0}, std::chrono::system_clock::time_point(std::chrono::seconds{500}), core::trust::Request::Answer::denied }; store->add(r1); store->add(r2); auto query = store->query(); query->execute(); EXPECT_EQ(core::trust::Store::Query::Status::has_more_results, query->status()); // We expect the more recent query to be enumerated first. EXPECT_EQ(r2, query->current()); query->next(); // We expect the older query to be enumerated second. EXPECT_EQ(r1, query->current()); query->next(); EXPECT_EQ(core::trust::Store::Query::Status::eor, query->status()); } trust-store-2.0.0+16.04.20160119/include/0000755000015600001650000000000012647452606020027 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/include/core/0000755000015600001650000000000012647452606020757 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/include/core/trust/0000755000015600001650000000000012647452606022140 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/include/core/trust/visibility.h0000644000015600001650000000202312647452272024474 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_VISIBILITY_H_ #define CORE_TRUST_VISIBILITY_H_ #if __GNUC__ >= 4 #define CORE_TRUST_DLL_PUBLIC __attribute__ ((visibility ("default"))) #define CORE_TRUST_DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define CORE_TRUST_DLL_PUBLIC #define CORE_TRUST_DLL_LOCAL #endif #endif // CORE_TRUST_VISIBILITY_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/mir_agent.h0000644000015600001650000000364312647452272024263 0ustar pbuserpbgroup00000000000000/* * 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_MIR_AGENT_H_ #define CORE_TRUST_MIR_AGENT_H_ #include #include #include // Forward declare the MirConnection type. struct MirConnection; namespace core { namespace trust { // Forward declare the Agent interface. class Agent; namespace mir { class InvalidMirConnection : public std::runtime_error { public: explicit InvalidMirConnection(const char* what_arg) : std::runtime_error(what_arg) {} }; /** * @brief Helper function building up a connection to Mir. * @param endpoint The name of the endpoint exposed by the Mir instance. * @param name The name assigned to this connection. * @throws std::runtime_error in case of issues. */ CORE_TRUST_DLL_PUBLIC MirConnection* connect(const std::string& endpoint, const std::string& name); /** * @brief create_agent_for_mir_connection creates a trust::Agent implementation leveraging Mir's trusted prompting API. * @param connection An existing connection to a Mir instance. * @throws InvalidMirConnection if the connection object is invalid. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr create_agent_for_mir_connection(MirConnection* connection); } } } #endif // CORE_TRUST_MIR_AGENT_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/tagged_integer.h0000644000015600001650000000631312647452272025263 0ustar pbuserpbgroup00000000000000/* * 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_TAGGED_INTEGER_H_ #define CORE_TRUST_TAGGED_INTEGER_H_ #include #include #include #include namespace core { namespace trust { /** @brief Helper structure for tagging integer types with certain semantics. */ template struct TaggedInteger { /** @brief We bail out if the Integral type is not an integral one. */ static_assert(std::is_integral::value, "Integer has to be an integral type"); /** @brief Stores the Tag type. */ typedef Tag TagType; /** @brief Stores the Integer type. */ typedef Integer IntegerType; /** @brief Construct an instance with a default value. */ TaggedInteger() : value{} { } /** @brief Construct an instance from an existing integer type. */ explicit TaggedInteger(Integer value) : value{value} { } /** @brief The contained integer value. */ Integer value; }; /** @brief Returns true iff both tagged integer instances are equal. */ template inline bool operator==(const TaggedInteger& lhs, const TaggedInteger& rhs) { return lhs.value == rhs.value; } /** @brief Returns true iff both tagged integer instances are not equal. */ template inline bool operator!=(const TaggedInteger& lhs, const TaggedInteger& rhs) { return lhs.value != rhs.value; } /** @brief Returns true iff the left-hand-side integer instance is smaller than the right-hand-side. */ template inline bool operator<(const TaggedInteger& lhs, const TaggedInteger& rhs) { return lhs.value < rhs.value; } /** @brief Pretty prints a tagged integer. */ template inline std::ostream& operator<<(std::ostream& out, const TaggedInteger& ti) { return out << ti.value; } namespace tag { // Tags a group id struct Gid {}; // Tags a process id struct Pid {}; // Tags a user id struct Uid {}; // Tags a service-specific feature struct Feature {}; } /** @brief Our internal group id type. */ typedef TaggedInteger Gid; /** @brief Our internal process id type. */ typedef TaggedInteger Pid; /** @brief Our internal user id type. */ typedef TaggedInteger Uid; /** @brief Our internal service-feature type. */ typedef TaggedInteger Feature; } } #endif // CORE_TRUST_TAGGED_INTEGER_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/resolve.h0000644000015600001650000000346312647452272023775 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_RESOLVE_H_ #define CORE_TRUST_RESOLVE_H_ #include #include #include namespace core { namespace dbus { class Bus; } namespace trust { // Forward declarations class Store; /** * @brief Resolves an existing store instance within the current user session. * @throw Error::ServiceNameMustNotBeEmpty. * @param bus The bus connection. * @param name The name under which the service can be found within the session. * @return A token that limits the lifetime of the exposure. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr resolve_store_on_bus_with_name( const std::shared_ptr& bus, const std::string& name); /** * @brief Resolves an existing store instance within the current user session. * @throw Error::ServiceNameMustNotBeEmpty. * @param name The name under which the service can be found within the session. * @return A token that limits the lifetime of the exposure. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr resolve_store_in_session_with_name( const std::string& name); } } #endif // CORE_TRUST_RESOLVE_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/store.h0000644000015600001650000001551412647452272023452 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_STORE_H_ #define CORE_TRUST_STORE_H_ #include #include #include #include #include #include namespace core { /** * @brief Contains functionality for implementing Ubuntu's trust model. * * Ubuntu's trust model extends upon a strict confinement approach implemented * on top of AppArmor. In this approach, applications are not trusted by default, and * we assume a very negative view of the app world. That is, we assume that all apps * are created with malicious intentions in mind, invading a user's privacy and wasting * resources. For that, we severely limit an application's access to the system and * provide trusted gates out of the confinement. These trusted gates, also called trusted helpers, * ensure that the user is prompted for granting or denying trust to a specific application. * */ namespace trust { /** * @brief Models read/write/query access to persisted trust requests. */ class CORE_TRUST_DLL_PUBLIC Store { public: /** @brief All Store-specific error/exception types go here. */ struct Errors { /** @cond */ Errors() = delete; /** @endcond */ /** * @brief Thrown if a store implementation could not access the persistence backend. */ struct ErrorOpeningStore : public std::runtime_error { ErrorOpeningStore(const char* implementation_specific) : std::runtime_error(implementation_specific) { } }; /** * @brief Thrown if a store implementation could not reset state and drop all previously stored requests. */ struct ErrorResettingStore : public std::runtime_error { ErrorResettingStore(const char* implementation_specific) : std::runtime_error(implementation_specific) { } }; }; /** * @brief The Query class encapsulates queries against a trust store instance. */ class Query { public: /** @brief All Query-specific error/exception types go here. */ struct Errors { /** @cond */ Errors() = delete; /** @endcond */ /** * @brief Thrown if functionality of a query is accessed although the query is in error state. */ struct QueryIsInErrorState : public std::runtime_error { QueryIsInErrorState() : std::runtime_error("Query is in error state, cannot extract result.") { } }; /** * @brief Thrown when trying to access the current result although the query status is not has_more_results. */ struct NoCurrentResult : public std::runtime_error { NoCurrentResult() : std::runtime_error("Query does not have a current result.") { } }; }; /** @brief The state of the query. */ enum class Status { armed, ///< The query is armed but hasn't been run. has_more_results, ///< The query has been executed and has more results. eor, ///< All results have been visited. error ///< An error occured. }; Query(const Query&) = delete; virtual ~Query() = default; /** @brief Access the status of the query. */ virtual Status status() const = 0; /** @brief Limit the query to a specific application Id. */ virtual void for_application_id(const std::string& id) = 0; /** @brief Limit the query to a service-specific feature. */ virtual void for_feature(Feature feature) = 0; /** @brief Limit the query to the specified time interval. */ virtual void for_interval(const Request::Timestamp& begin, const Request::Timestamp& end) = 0; /** @brief Limit the query for a specific answer. */ virtual void for_answer(Request::Answer answer) = 0; /** @brief Query all stored requests. */ virtual void all() = 0; /** @brief Execute the query against the store. */ virtual void execute() = 0; /** @brief After successful execution, advance to the next request. */ virtual void next() = 0; /** @brief After successful execution, erase the current element and advance to the next request. */ virtual void erase() = 0; /** @brief Access the request the query currently points to. */ virtual Request current() = 0; protected: Query() = default; }; Store(const Store&) = delete; virtual ~Store() = default; Store& operator=(const Store&) = delete; bool operator==(const Store&) const = delete; /** @brief Resets the state of the store, implementations should discard * all persistent and non-persistent state. */ virtual void reset() = 0; /** @brief Add the provided request to the store. When this function returns true, * the request has been persisted by the implementation. */ virtual void add(const Request& request) = 0; /** * @brief Create a query for this store. */ virtual std::shared_ptr query() = 0; protected: Store() = default; }; /** @brief All core::trust-specific error/exception types go here. */ struct Errors { /** @cond */ Errors() = delete; /** @endcond */ /** * @brief The ServiceNameMustNotBeEmpty is thrown if an empty service name * is provided when creating a store. */ struct ServiceNameMustNotBeEmpty : public std::runtime_error { ServiceNameMustNotBeEmpty() : std::runtime_error("Service name must not be empty") { } }; }; /** * @brief Creates an instance for the default store implementation. * @throw Error::ServiceNameMustNotBeEmpty. * @param service_name [in] The service name, must not be empty. * @return An instance of trust::Store. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr create_default_store(const std::string& service_name); } } #endif // CORE_TRUST_STORE_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/agent.h0000644000015600001650000000620412647452272023410 0ustar pbuserpbgroup00000000000000/* * 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_AGENT_H_ #define CORE_TRUST_AGENT_H_ #include #include #include #include namespace core { namespace trust { /** @brief Abstracts user-prompting functionality. */ class CORE_TRUST_DLL_PUBLIC Agent { public: /** @cond */ Agent() = default; virtual ~Agent() = default; Agent(const Agent&) = delete; Agent(Agent&&) = delete; Agent& operator=(const Agent&) = delete; Agent& operator=(Agent&&) = delete; /** @endcond */ /** @brief Abstracts functionality for storing agent instances and associating them with a user id. */ struct Registry { /** @brief Convenience typedef for a shared ptr. */ typedef std::shared_ptr Ptr; /** @cond */ Registry() = default; virtual ~Registry() = default; /** @endcond */ /** @brief Registers an agent for the given uid. */ virtual void register_agent_for_user(const core::trust::Uid& uid, const std::shared_ptr& agent) = 0; /** @brief Removes the agent for the given uid from the registry */ virtual void unregister_agent_for_user(const core::trust::Uid& uid) = 0; }; /** @brief Summarizes all parameters for processing a trust request. */ struct RequestParameters { /** @brief All application-specific parameters go here. */ struct { /** @brief The user id under which the requesting application runs. */ core::trust::Uid uid; /** @brief The process id of the requesting application. */ core::trust::Pid pid; /** @brief The id of the requesting application. */ std::string id; } application; /** @brief The service-specific feature identifier. */ Feature feature; /** @brief An extended description that should be presented to the user on prompting. */ std::string description; }; /** * @brief Authenticates the given request and returns the user's answer. * @param parameters [in] Describe the request. */ virtual Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) = 0; }; /** @brief Returns true iff lhs and rhs are equal. */ CORE_TRUST_DLL_PUBLIC bool operator==(const Agent::RequestParameters& lhs, const Agent::RequestParameters& rhs); } } #endif // CORE_TRUST_AGENT_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/expose.h0000644000015600001650000000441012647452312023605 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_EXPOSE_H_ #define CORE_TRUST_EXPOSE_H_ #include #include #include namespace core { namespace dbus { class Bus; } namespace trust { // Forward declarations class Store; /** @brief Opaque type describing the exposure of a store instance.*/ class CORE_TRUST_DLL_PUBLIC Token { public: Token(const Token&) = delete; virtual ~Token() = default; Token& operator=(const Token&) = delete; bool operator==(const Token&) const = delete; protected: Token() = default; }; /** * @brief Exposes an existing store instance on the given bus. * @throw Error::ServiceNameMustNotBeEmpty. * @param store The instance to be exposed. * @param bus The bus connection. * @param name The name under which the service can be found within the session. * @return A token that limits the lifetime of the exposure. */ 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::string& name); /** * @brief Exposes an existing store instance with the current user session. * @throw Error::ServiceNameMustNotBeEmpty. * @param store The instance to be exposed. * @param name The name under which the service can be found within the session. * @return A token that limits the lifetime of the exposure. */ CORE_TRUST_DLL_PUBLIC std::unique_ptr expose_store_to_session_with_name( const std::shared_ptr& store, const std::string& name); } } #endif // CORE_TRUST_EXPOSE_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/request.h0000644000015600001650000001455512647452272024012 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_REQUEST_H_ #define CORE_TRUST_REQUEST_H_ #include #include #include #include #include #include #include namespace core { namespace trust { // Forward declarations class Agent; class Store; /** * @brief The Request struct encapsulates information about a trust request answered by the user. * * A Request is the main entity managed by the trust-store API. Whenever an * application tries to access the functionality offered by a trusted helper, * the trusted helper checks whether the application has issued a request * before. If a query against the trust store returns yes and the user * previously granted trust to the application, the application's request to * the trusted helpers functionality is granted. If the user previously * rejected the request, the app's request is denied. If no previous request * can be found, the trusted helper issues a question to the user, collects the * answer and transacts the complete request to the store. * */ struct CORE_TRUST_DLL_PUBLIC Request { /** @brief Duration in wallclock time. */ typedef std::chrono::system_clock::duration Duration; /** @brief Requests are timestamped with wallclock time. */ typedef std::chrono::system_clock::time_point Timestamp; /** @brief Default feature identifier. */ static constexpr const unsigned int default_feature = 0; /** @brief Enumerates the possible answers given by a user. */ enum class Answer : std::int32_t { denied, ///< Nope, I do not trust this application. granted, ///< Yup, I do trust this application. }; /** The application id of the application that resulted in the request. */ std::string from; /** An application-specific feature identifier. */ Feature feature; /** When the request happened in wallclock time. */ Timestamp when; /** The user's answer. */ Answer answer; }; /** * @brief operator == compares two Requests for equality. * @param lhs [in] The left-hand-side of the comparison. * @param rhs [in] The right-hand-side of the comparison. * @return true iff both requests are equal. */ CORE_TRUST_DLL_PUBLIC bool operator==(const Request& lhs, const Request& rhs); /** * @brief operator << pretty prints answers to the provided output stream. * @param out [in, out] The stream to print to. * @param a The answer to be printed. * @return The output stream. */ CORE_TRUST_DLL_PUBLIC std::ostream& operator<<(std::ostream& out, const Request::Answer& a); /** * @brief operator << pretty prints a request to the provided output stream. * @param out [in, out] The stream to print to. * @param r The request to be printed. * @return The output stream. */ CORE_TRUST_DLL_PUBLIC std::ostream& operator<<(std::ostream& out, const Request& r); /** @brief Summarizes all parameters for processing a trust request. */ struct CORE_TRUST_DLL_PUBLIC RequestParameters { /** @brief The Agent implementation to dispatch a request to the user. */ std::shared_ptr agent; /** @brief The trust store to be used for caching purposes. */ std::shared_ptr store; /** @brief The user id under which the requesting application runs. */ core::trust::Uid application_uid; /** @brief The process id of the requesting application. */ core::trust::Pid application_pid; /** @brief The id of the requesting application. */ std::string application_id; /** @brief The service-specific feature identifier. */ Feature feature; /** @brief An extended description that should be presented to the user on prompting. */ std::string description; }; /** * @brief Processes an incoming trust-request by an application, tries to lookup a previous reply before * issuing a prompt request via the given agent to the user. On return, the given trust-store is up-to-date. * * @throws std::exception To indicate that no conclusive answer could be resolved from either the store or * the user. In that case, the state of the store instance passed in to the function is not altered. * * The following code snippet illustrates how to use the function: * * @code * struct Service * { * static constexpr std::uint64_t default_feature = 0; * * void on_session_requested(core::trust::Uid app_uid, core::trust::Pid app_pid, std::string const& app_id) * { * core::trust::RequestParameters params * { * trust.agent, * trust.store, * app_uid, * app_pid, * app_id, * core::trust::Feature{default_feature}, * "Application " + app_id + " wants to access the example service." * }; * * switch(process_trust_request(params)) * { * case core::trust::Request::Answer::granted: * // Create session and get back to application with session credentials. * break; * case core::trust::Request::Answer::denied: * // Deny session creation and inform application. * break; * } * } * * struct * { * // We use Mir's trust session support to request the prompting UI. * std::shared_ptr agent * { * core::trust::mir::make_agent_for_existing_connection(mir_connection) * }; * * std::shared_ptr store * { * core::trust::create_default_store("my.example.service"); * }; * } trust; * }; * @endcode */ CORE_TRUST_DLL_PUBLIC Request::Answer process_trust_request(const RequestParameters& params); } } #endif // CORE_TRUST_REQUEST_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/cached_agent.h0000644000015600001650000000551312647452272024701 0ustar pbuserpbgroup00000000000000/* * 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_CACHED_AGENT_H_ #define CORE_TRUST_CACHED_AGENT_H_ #include namespace core { namespace trust { /** @brief An agent implementation that uses a trust store instance to cache results. */ class CORE_TRUST_DLL_PUBLIC CachedAgent : public core::trust::Agent { public: /** @brief To save some typing. */ typedef std::shared_ptr Ptr; /** @brief Abstract capturer of internal events for post-mortem debugging/analysis purposes. */ struct Reporter { /** @cond */ Reporter() = default; virtual ~Reporter() = default; /** @endcond */ /** @brief Invoked whenever the implementation was able to resolve a cached request. */ virtual void report_cached_answer_found(const core::trust::Agent::RequestParameters&, const core::trust::Request&); /** @brief Invoked whenever the implementation called out to an agent to prompt the user for trust. */ virtual void report_user_prompted_for_trust(const core::trust::Agent::RequestParameters&, const core::trust::Request::Answer&); }; /** @brief Creation time parameters. */ struct Configuration { /** @brief The actual agent implementation for prompting the user. */ std::shared_ptr agent; /** @brief The store caching user answers to trust prompts. */ std::shared_ptr store; /** @brief The reporter implementation. */ std::shared_ptr reporter; }; /** * @brief CachedAgent creates a new agent instance. * @param configuration Specifies the actual agent and the store. * @throws std::logic_error if either the agent or the store are null. */ CachedAgent(const Configuration& configuration); /** @cond */ virtual ~CachedAgent() = default; /** @endcond */ /** @brief From core::trust::Agent. */ Request::Answer authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) override; private: /** @brief We just store a copy of the configuration parameters */ Configuration configuration; }; } } #endif // CORE_TRUST_CACHED_AGENT_H_ trust-store-2.0.0+16.04.20160119/include/core/trust/dbus_agent.h0000644000015600001650000000406612647452272024431 0ustar pbuserpbgroup00000000000000/* * 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_DBUSAGENT_H_ #define CORE_TRUST_DBUSAGENT_H_ #include namespace core { namespace dbus { class Bus; } namespace trust { // Forward declare the Agent interface. class Agent; namespace dbus { /** * @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_name The name of the service we are operating for. * @throws std::runtime_error in case of issues. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr create_per_user_agent_for_bus_connection( const std::shared_ptr& connection, const std::string& service_name); /** * @brief create_multi_user_agent_for_bus_connection creates a trust::Agent implementation communicating with user-specific * remote agent implementations, living in user sessions. * @param connection An existing DBus connection. * @param service_name The name of the service we are operating for. * @throws std::runtime_error in case of issues. */ CORE_TRUST_DLL_PUBLIC std::shared_ptr create_multi_user_agent_for_bus_connection( const std::shared_ptr& connection, const std::string& service_name); } } } #endif // CORE_TRUST_DBUSAGENT_H_ trust-store-2.0.0+16.04.20160119/include/CMakeLists.txt0000644000015600001650000000010712647452272022564 0ustar pbuserpbgroup00000000000000install( DIRECTORY core DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ ) trust-store-2.0.0+16.04.20160119/src/0000755000015600001650000000000012647452606017173 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/0000755000015600001650000000000012647452606020123 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/0000755000015600001650000000000012647452606021304 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/app_id_formatting_trust_agent.h0000644000015600001650000000266412647452272027571 0ustar pbuserpbgroup00000000000000/* * 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_APP_ID_FORMATTING_TRUST_AGENT_H_ #define CORE_TRUST_APP_ID_FORMATTING_TRUST_AGENT_H_ #include namespace core { namespace trust { // An agent implementation pre-processing application ids, ensuring // legible application ids, independent of application versions. Forwards // to an actual agent implementation. class CORE_TRUST_DLL_PUBLIC AppIdFormattingTrustAgent : public core::trust::Agent { public: AppIdFormattingTrustAgent(const std::shared_ptr& impl); // From core::trust::Agent Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; private: std::shared_ptr impl; }; } } #endif // CORE_TRUST_APP_ID_FORMATTING_TRUST_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.cpp0000644000015600001650000005147212647452312023256 0ustar pbuserpbgroup00000000000000/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Options = boost::program_options; namespace { core::trust::Daemon::Dictionary fill_dictionary_from_unrecognized_options(const Options::parsed_options& parsed_options) { auto unrecognized = Options::collect_unrecognized( parsed_options.options, Options::exclude_positional); core::trust::Daemon::Dictionary dict; for (std::string& element : unrecognized) { if (element.find("--") != 0) continue; auto idx = element.find("="); if (idx == std::string::npos) continue; auto key = element.substr(0, idx).substr(2, std::string::npos); auto value = element.substr(idx+1, std::string::npos); dict[key] = value; } return dict; } struct DummyAgent : public core::trust::Agent { DummyAgent(core::trust::Request::Answer canned_answer) : canned_answer{canned_answer} { } core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters&) override { return canned_answer; } core::trust::Request::Answer canned_answer; }; } const std::map& core::trust::Daemon::Skeleton::known_local_agent_factories() { static std::map lut { { std::string{Daemon::LocalAgents::MirAgent::name}, [](const std::string& service_name, const Dictionary& dict) { if (dict.count("trusted-mir-socket") == 0) throw std::runtime_error { "Missing endpoint specification for accessing Mir's trusted socket." }; auto trusted_mir_socket = dict.at("trusted-mir-socket"); // TODO: log reconnection attempts int connection_attempts = 5; while (true) { try { return core::trust::mir::create_agent_for_mir_connection( core::trust::mir::connect( trusted_mir_socket, service_name)); } catch (core::trust::mir::InvalidMirConnection const&) { if (--connection_attempts == 0) throw; } std::this_thread::sleep_for(std::chrono::seconds(1)); std::cerr << "reattempt connection to mir..."<< std::endl; } } }, { std::string{Daemon::LocalAgents::TerminalAgent::name}, [](const std::string& service_name, const Dictionary&) { return std::make_shared(service_name); } }, { "TheAlwaysDenyingLocalAgent", [](const std::string&, const Dictionary&) { auto agent = std::shared_ptr { new DummyAgent{core::trust::Request::Answer::denied} }; return agent; } } }; return lut; } const std::map& core::trust::Daemon::Skeleton::known_remote_agent_factories() { static std::map lut { { std::string{Daemon::RemoteAgents::UnixDomainSocketRemoteAgent::name}, [](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 { "Missing endpoint specification for UnixDomainSocketRemoteAgent." }; core::trust::remote::posix::Skeleton::Configuration config { agent, 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("is trying to access") + " " + service_name + ".", dict.count("verify-process-timestamp") > 0 }; return core::trust::remote::posix::Skeleton::create_skeleton_for_configuration(config); } }, { 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 = 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; auto service = core::dbus::Service::use_service(bus, dbus_service_name); auto object = service->object_for_path( core::dbus::types::ObjectPath { 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(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); } }); } } }; return lut; } // Parses the configuration from the given command line. core::trust::Daemon::Skeleton::Configuration core::trust::Daemon::Skeleton::Configuration::from_command_line(int argc, const char** argv) { Options::variables_map vm; Dictionary dict; Options::options_description options{"Known options"}; 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()->required(), Parameters::StoreBus::description) (Parameters::LocalAgent::name, Options::value()->required(), Parameters::LocalAgent::description) (Parameters::RemoteAgent::name, Options::value()->required(), Parameters::RemoteAgent::description); Options::command_line_parser parser { argc, argv }; try { auto parsed_options = parser.options(options).allow_unregistered().run(); Options::store(parsed_options, vm); Options::notify(vm); dict = fill_dictionary_from_unrecognized_options(parsed_options); } catch(const boost::exception& e) { throw std::runtime_error { "Error parsing command line: " + boost::diagnostic_information(e) }; } auto bf = core::trust::dbus::BusFactory::create_default(); auto service_name = vm[Parameters::ForService::name].as(); auto service_text_domain = service_name; if (vm.count(Parameters::WithTextDomain::name) > 0) service_text_domain = vm[Parameters::WithTextDomain::name].as(); core::trust::i18n::set_service_text_domain(service_text_domain); auto local_agent_factory = core::trust::Daemon::Skeleton::known_local_agent_factories() .at(vm[Parameters::LocalAgent::name].as()); auto remote_agent_factory = core::trust::Daemon::Skeleton::known_remote_agent_factories() .at(vm[Parameters::RemoteAgent::name].as()); auto local_store = core::trust::create_default_store(service_name); auto local_agent = local_agent_factory(service_name, dict); auto cached_agent = std::make_shared( core::trust::CachedAgent::Configuration { local_agent, local_store, std::make_shared( core::trust::CachedAgentGlogReporter::Configuration{}) }); auto whitelisting_agent = std::make_shared([dict](const core::trust::Agent::RequestParameters& params) -> bool { static auto unconfined_predicate = core::trust::WhiteListingAgent::always_grant_for_unconfined(); const bool is_unconfined = unconfined_predicate(params); return is_unconfined || ((not (dict.count("disable-whitelisting") > 0)) && params.application.id == "com.ubuntu.camera_camera"); }, 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, bf, dict); return core::trust::Daemon::Skeleton::Configuration { service_name, bf->bus_for_type(vm[Parameters::StoreBus::name].as()), {local_store, privilege_escalation_prevention_agent}, {remote_agent} }; } // Executes the daemon with the given configuration. core::posix::exit::Status core::trust::Daemon::Skeleton::main(const core::trust::Daemon::Skeleton::Configuration& configuration) { // 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( configuration.local.store, configuration.bus, configuration.service_name); core::trust::Runtime::instance().run(); return core::posix::exit::Status::success; } const std::map& core::trust::Daemon::Stub::known_remote_agent_factories() { static std::map lut { { std::string{Daemon::RemoteAgents::UnixDomainSocketRemoteAgent::name}, [](const std::string&, const core::trust::dbus::BusFactory::Ptr&, const Dictionary& dict) { if (dict.count("endpoint") == 0) throw std::runtime_error { "Missing endpoint specification for UnixDomainSocketRemoteAgent." }; core::trust::remote::posix::Stub::Configuration config { 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(), std::make_shared() }; return core::trust::remote::posix::Stub::create_stub_for_configuration(config); } }, { std::string{Daemon::RemoteAgents::SystemServiceDBusRemoteAgent::name}, [](const std::string& service_name, const core::trust::dbus::BusFactory::Ptr& bf, const 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; auto service = core::dbus::Service::add_service(bus, dbus_service_name); auto object = service->add_object_for_path( core::dbus::types::ObjectPath { core::trust::remote::dbus::default_agent_registry_path }); core::trust::remote::dbus::Agent::Stub::Configuration config { object, bus }; return std::make_shared(config); } } }; return lut; } core::trust::Daemon::Stub::Configuration core::trust::Daemon::Stub::Configuration::from_command_line(int argc, const char** argv) { Options::variables_map vm; Dictionary dict; Options::options_description options{"Known options"}; options.add_options() (Parameters::ForService::name, Options::value()->required(), Parameters::ForService::description) (Parameters::RemoteAgent::name, Options::value()->required(), Parameters::RemoteAgent::description); Options::command_line_parser parser { argc, argv }; try { auto parsed_options = parser.options(options).allow_unregistered().run(); Options::store(parsed_options, vm); Options::notify(vm); dict = fill_dictionary_from_unrecognized_options(parsed_options); } catch(const boost::exception& e) { throw std::runtime_error { "Error parsing command line: " + boost::diagnostic_information(e) }; } 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, bf, dict); return core::trust::Daemon::Stub::Configuration { service_name, remote_agent }; } namespace { // A very simple class to help with testing. // A user can feed a request to the stub. struct Shell : public std::enable_shared_from_this { Shell(const std::shared_ptr& agent, boost::asio::io_service& ios) : agent{agent}, 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() { std::cout << "This is the super simple, interactive shell of the trust::store Daemon" << std::endl; std::cout << "The following commands are known:" << std::endl; std::cout << " Enter a line like 'pid uid feature' to issue a query with the given parameters." << std::endl; start_read(); } // Stops any outstanding read operation from stdin. void stop() { stdin.cancel(); } // Prints the shell prompt and starts an asynchronous read on stdin. void start_read() { // Our shell prompt. std::cout << "> " << std::flush; // The async read operation boost::asio::async_read_until( stdin, // From stdin buffer, // Into a buffer '\n', // Until we get a newline boost::bind( &Shell::read_finished, shared_from_this(), boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred())); } // Invoked in case of errors or if one line has been read from stdin. void read_finished(const boost::system::error_code& ec, std::size_t) { if (ec == boost::asio::error::operation_aborted) return; if (ec) { start_read(); return; } core::trust::Agent::RequestParameters params; std::istream ss{&buffer}; ss >> params.application.pid.value >> params.application.uid.value >> params.feature.value; // We fix up the parameters. params.application.id = app_id_resolver(params.application.pid); std::cout << agent->authenticate_request_with_parameters(params) << std::endl; buffer.consume(buffer.size()); start_read(); } // The agent we query for incoming requests. std::shared_ptr agent; // Async descriptor for reading from stdin. boost::asio::posix::stream_descriptor stdin; // The buffer we read in. boost::asio::streambuf buffer; // We use some helpers to fix up the quite limited requests we parse from the // command line core::trust::remote::helpers::AppIdResolver app_id_resolver; }; } // Executes the daemon with the given configuration. 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, core::trust::Runtime::instance().service()); // We start up our shell shell->start(); // Wait until signal arrives. core::trust::Runtime::instance().run(); return core::posix::exit::Status::success; } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/0000755000015600001650000000000012647452606022073 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.h0000644000015600001650000000326612647452305032102 0ustar pbuserpbgroup00000000000000/* * 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_ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/config.h.in0000644000015600001650000000213512647452272024116 0ustar pbuserpbgroup00000000000000/* * 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_MIR_CONFIG_H_ #define CORE_TRUST_MIR_CONFIG_H_ namespace core { namespace trust { namespace mir { static constexpr const char* trust_prompt_executable_in_build_dir { "@CMAKE_BINARY_DIR@/src/trust-prompt" }; static constexpr const char* trust_prompt_executable_in_lib_dir { "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/trust-prompt" }; } } } #endif // CORE_TRUST_MIR_CONFIG_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/not_supported.cpp0000644000015600001650000000207412647452272025506 0ustar pbuserpbgroup00000000000000/* * 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 MirConnection* core::trust::mir::connect(const std::string&, const std::string&) { throw std::runtime_error { "Mir is not supported." }; } std::shared_ptr core::trust::mir::create_agent_for_mir_connection(MirConnection*) { throw std::runtime_error { "Mir is not supported." }; } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.cpp0000644000015600001650000002374312647452305023702 0ustar pbuserpbgroup00000000000000/* * 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 "agent.h" #include "prompt_main.h" #include #include #include #include // For getuid #include #include #include 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) { if (count == 0) return; auto ctxt = static_cast(context); if (not ctxt) return; ctxt->fd = fds[0]; // Upstart enables FD_CLOEXEC by default. We have to counteract. if (::fcntl(ctxt->fd, F_SETFD, 0) == -1) throw std::system_error { errno, std::system_category() }; } mir::PromptSessionVirtualTable::PromptSessionVirtualTable(MirPromptSession* prompt_session) : prompt_session(prompt_session) { if (not prompt_session) throw std::runtime_error { "Cannot create instance for null prompt_session" }; } mir::PromptSessionVirtualTable::PromptSessionVirtualTable() : prompt_session(nullptr) { } int mir::PromptSessionVirtualTable::new_fd_for_prompt_provider() { static const unsigned int fd_count = 1; mir::PromptSessionVirtualTable::Context context; mir_wait_for(mir_prompt_session_new_fds_for_prompt_providers( prompt_session, fd_count, PromptSessionVirtualTable::mir_client_fd_callback, &context)); if (context.fd == Context::invalid_fd) throw std::runtime_error { "Could not acquire pre-authenticated file descriptors for Mir prompt session." }; return context.fd; } void mir::PromptSessionVirtualTable::release_sync() { mir_prompt_session_release_sync(prompt_session); } mir::ConnectionVirtualTable::ConnectionVirtualTable(MirConnection* connection) : connection{connection} { if (not mir_connection_is_valid(connection)) throw InvalidMirConnection { "Cannot create instance for invalid connection to Mir." }; } mir::ConnectionVirtualTable::ConnectionVirtualTable() : connection{nullptr} { } mir::PromptSessionVirtualTable::Ptr mir::ConnectionVirtualTable::create_prompt_session_sync( // The process id of the requesting app/service core::trust::Pid app_pid, // Callback handling prompt session state changes. mir_prompt_session_state_change_callback cb, // Callback context void* context) { return PromptSessionVirtualTable::Ptr { new PromptSessionVirtualTable { mir_connection_create_prompt_session_sync(connection, app_pid.value, cb, context) } }; } mir::PromptProviderHelper::PromptProviderHelper( const mir::PromptProviderHelper::CreationArguments& args) : creation_arguments(args) { } core::posix::ChildProcess mir::PromptProviderHelper::exec_prompt_provider_with_arguments( const mir::PromptProviderHelper::InvocationArguments& args) { static auto child_setup = []() {}; 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_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 }; // We just copy the environment std::map env; core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value) { env.insert(std::make_pair(key, value)); }); auto result = core::posix::exec(creation_arguments.path_to_helper_executable, argv, env, core::posix::StandardStream::empty, child_setup); return result; } void mir::Agent::on_trust_session_changed_state( // The prompt session instance that just changed state. MirPromptSession* /*prompt_provider*/, // The new state of the prompt session instance. MirPromptSessionState state, // The context of type context. void* context) { if (mir_prompt_session_state_stopped != state) return; auto ctxt = static_cast(context); if (not ctxt) return; std::error_code ec; // If the trust session ended (for whatever reason), we send a SIG_KILL to the // prompt provider process. We hereby ensure that we never return Answer::granted // unless the prompt provider cleanly exited prior to the trust session stopping. ctxt->prompt_provider_process.send_signal(core::posix::Signal::sig_kill, ec); // The required wait for the child process happens in prompt_user_for_request(...). // TODO(tvoss): We should log ec in case of errors. } std::function mir::Agent::translator_only_accepting_exit_status_success() { return [](const core::posix::wait::Result& result) -> core::trust::Request::Answer { // We now analyze the result of the process execution. if (core::posix::wait::Result::Status::exited != result.status) throw std::logic_error { "The prompt provider process was signaled or stopped, " "unable to determine a conclusive answer from the user" }; // If the child process did not exit cleanly, we deny access to the resource. if (core::posix::exit::Status::failure == result.detail.if_exited.status) return core::trust::Request::Answer::denied; return core::trust::Request::Answer::granted; }; } 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 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 // instance here. mir::Agent::OnTrustSessionStateChangedCallbackContext cb_context { core::posix::ChildProcess::invalid() }; // We ensure that the prompt session is always released cleanly, either on return or on throw. struct Scope { ~Scope() { prompt_session->release_sync(); } mir::PromptSessionVirtualTable::Ptr prompt_session; } scope { // We setup the prompt session and wire up to our own internal callback helper. config.connection_vtable->create_prompt_session_sync( parameters.application.pid, Agent::on_trust_session_changed_state, &cb_context) }; // Acquire a new fd for the prompt provider. auto fd = scope.prompt_session->new_fd_for_prompt_provider(); // And prepare the actual execution in a child process. mir::PromptProviderHelper::InvocationArguments args { fd, config.app_info_resolver->resolve(parameters.application.id), parameters.description }; // Ask the helper to fire up the prompt provider. 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 config.translator(result); } bool mir::operator==(const mir::PromptProviderHelper::InvocationArguments& lhs, const mir::PromptProviderHelper::InvocationArguments& rhs) { 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) { return mir_connect_sync(endpoint.c_str(), name.c_str()); } std::shared_ptr mir::create_agent_for_mir_connection(MirConnection* connection) { mir::ConnectionVirtualTable::Ptr cvt { new mir::ConnectionVirtualTable { connection } }; mir::PromptProviderHelper::Ptr pph { new mir::PromptProviderHelper { mir::PromptProviderHelper::CreationArguments { core::trust::mir::trust_prompt_executable_in_lib_dir } } }; 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}}; } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.qml0000644000015600001650000000604312647452305025132 0ustar pbuserpbgroup00000000000000/* * 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 as published by * the Free Software Foundation; version 3. * * 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 . */ import QtQuick 2.0 import Ubuntu.Components 1.3 import Ubuntu.Components.Popups 1.3 Item { property var appIcon: icon property var appName: name property var appId: id property var serviceDescription: description signal quit(int code) Component { id: dialog 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) } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/click_desktop_entry_app_info_resolver.cpp0000644000015600001650000001033412647452305032427 0ustar pbuserpbgroup00000000000000/* * 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 }; } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/agent.h0000644000015600001650000002134012647452305023336 0ustar pbuserpbgroup00000000000000/* * 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_MIR_MIR_AGENT_H_ #define CORE_TRUST_MIR_MIR_AGENT_H_ #include #include #include #include #include #include #include #include #include namespace core { namespace trust { 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 { public: // Just a convenience typedef typedef std::shared_ptr Ptr; // Just a helper struct to be passed to client_fd_callbacks. struct Context { // Marks the value of an invalid fd. static constexpr const int invalid_fd{-1}; // The fd contained within this context instance. int fd{invalid_fd}; }; // Invoked whenever a request for creation of pre-authenticated fds succeeds. static void mir_client_fd_callback(MirPromptSession */*prompt_session*/, size_t count, int const* fds, void* context); // Create a MirPromptSessionVirtualTable for a given prompt session instance. // Please note that no change of ownwership is happening here. Instead, we expect // the calling code to handle object lifetimes. PromptSessionVirtualTable(MirPromptSession* prompt_session); virtual ~PromptSessionVirtualTable() = default; // Requests a new, pre-authenticated fd for associating prompt providers. // Returns the fd or throws std::runtime_error. virtual int new_fd_for_prompt_provider(); // Finalizes and releases the given prompt session instance. virtual void release_sync(); protected: // Mainly used in testing to circumvent any assertions on the // prompt_session pointer. PromptSessionVirtualTable(); private: // The underlying prompt session instance. MirPromptSession* prompt_session; }; class CORE_TRUST_DLL_PUBLIC ConnectionVirtualTable { public: // Just a convenience typedef typedef std::shared_ptr Ptr; // Create a new instance of MirConnectionVirtualTable // using a pre-existing connection to Mir. Please note // that we do not take ownership of the MirConnection but // expect the calling code to coordinate object lifetimes. ConnectionVirtualTable(MirConnection* connection); virtual ~ConnectionVirtualTable() = default; // Creates a new trusted prompt session instance synchronously. virtual PromptSessionVirtualTable::Ptr create_prompt_session_sync( // The process id of the requesting app/service Pid app_pid, // Callback handling prompt session state changes. mir_prompt_session_state_change_callback cb, // Callback context void* context); protected: // Mainly used in testing to circumvent any assertions on the // connection pointer. ConnectionVirtualTable(); private: // We do not take over ownership of the connection object. MirConnection* connection; }; // Abstracts common functionality required for running external helpers. struct CORE_TRUST_DLL_PUBLIC PromptProviderHelper { // Just a convenience typedef. typedef std::shared_ptr Ptr; // Creation-time arguments. struct CreationArguments { // Path to the helper executable that provides the prompting UI. std::string path_to_helper_executable; }; // Invocation arguments for exec_prompt_provider_with_arguments struct InvocationArguments { // The pre-authenticated fd that the helper // should use for connecting to Mir. int fd; // Application-specific information goes here. AppInfo app_info; // The extended description that should be presented to the user. std::string description; }; PromptProviderHelper(const CreationArguments& args); virtual ~PromptProviderHelper() = default; // Execs the executable provided at construction time for the arguments and // returns the corresponding child process. virtual core::posix::ChildProcess exec_prompt_provider_with_arguments(const InvocationArguments& args); // We store all arguments passed at construction. 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. struct CORE_TRUST_DLL_PUBLIC Agent : public core::trust::Agent { // 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 { // The process that provides the prompting UI. core::posix::ChildProcess prompt_provider_process; }; // Handles state changes of trust sessions and sigkills the child process // provided in context (of type OnTrustSessionStateChangedCallbackContext). static void on_trust_session_changed_state( // The prompt session instance that just changed state. MirPromptSession* prompt_provider, // The new state of the prompt session instance. MirPromptSessionState state, // The context of type context. void* context); // Returns a wait result -> trust::Request::Answer translator that only returns Answer::granted if // the prompt provider child process exits cleanly with status success. // 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 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 configured options. Configuration config; }; CORE_TRUST_DLL_PUBLIC bool operator==(const PromptProviderHelper::InvocationArguments&, const PromptProviderHelper::InvocationArguments&); } } } #endif // CORE_TRUST_MIR_MIR_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_config.h.in0000644000015600001650000000242312647452272025517 0ustar pbuserpbgroup00000000000000/* * 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 // Returns true if the application is called from its installed location. inline bool isRunningInstalled() { static bool installed { QCoreApplication::applicationDirPath() == QDir(("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@")).canonicalPath() }; return installed; } inline QString appDirectory() { return isRunningInstalled() ? QString("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@/core/trust/mir/") : QString("@CMAKE_SOURCE_DIR@/src/core/trust/mir/"); } trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.cpp0000644000015600001650000001715712647452305025133 0ustar pbuserpbgroup00000000000000/* * 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 . * * Authors: * Olivier Tilloy * Nick Dedekind * Thomas Voß */ // Qt #include #include #include #include #include #include #include #include #include #include #include #include "prompt_config.h" #include "prompt_main.h" #include namespace cli = core::trust::mir::cli; namespace env = core::trust::mir::env; namespace this_env = core::posix::this_process::env; namespace core { namespace trust { namespace mir { class SignalTrap : public QObject { Q_OBJECT public Q_SLOTS: void quit(int code) { QCoreApplication::exit(code); } }; } } } namespace { namespace testing { void validate_command_line_arguments(const boost::program_options::variables_map& vm) { // We are throwing exceptions here, which immediately calls abort and still gives a // helpful error message on the terminal. if (vm.count(cli::option_icon) == 0) throw std::logic_error { "Missing option icon." }; if (vm.count(cli::option_name) == 0) throw std::logic_error { "Missing option name." }; if (vm.count(cli::option_id) == 0) throw std::logic_error { "Missing option id." }; if (vm.count(cli::option_description) == 0) throw std::logic_error { "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://" }; } } } } int main(int argc, char** argv) { 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_testing, "Only checks command-line parameters and does not execute any actions.") (cli::option_testability, "Loads the Qt Testability plugin if provided."); auto parsed_options = boost::program_options::command_line_parser{argc, argv} .options(options) .allow_unregistered() .run(); // Consider the command line. boost::program_options::variables_map vm; boost::program_options::store(parsed_options, vm); boost::program_options::notify(vm); // And the environment for option passing. parsed_options = boost::program_options::parse_environment(options, "CORE_TRUST_MIR_PROMPT_"); 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) return 0; 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) { this_env::unset_or_throw(env::option_mir_socket); 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. core::trust::i18n::default_text_domain(); // We install a custom message handler to silence Qt's chattiness qInstallMessageHandler([](QtMsgType type, const QMessageLogContext&, const QString& msg) { switch (type) { // We only handle critical and fatal messages. case QtCriticalMsg: case QtFatalMsg: std::cerr << qPrintable(msg) << std::endl; break; // And just drop the rest. default: break; } }); // We already parsed the command line arguments and do not parse them // to the application. QGuiApplication app{argc, argv}; if (vm.count(cli::option_testability) > 0 || this_env::get(env::option_testability, "0") == "1") { // This initialization code is copy'n'pasted across multiple projects. We really should _not_ // do something like that and bundle initialization routines in autopilot-qt. // The testability driver is only loaded by QApplication but not by QGuiApplication. // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own. QLibrary testLib(QLatin1String("qttestability")); if (testLib.load()) { typedef void (*TasInitialize)(void); TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); if (initFunction) initFunction(); else qCritical("Library qttestability resolve failed!"); } else { qCritical("Library qttestability load failed!"); } } core::trust::mir::SignalTrap signal_trap; QQuickView* view = new QQuickView(); view->setResizeMode(QQuickView::SizeRootObjectToView); view->setTitle(QGuiApplication::applicationName()); // Make some properties known to the root context. 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. view->engine()->setBaseUrl(QUrl::fromLocalFile(appDirectory())); view->setSource(QUrl::fromLocalFile("prompt_main.qml")); view->show(); QObject::connect( view->rootObject(), SIGNAL(quit(int)), &signal_trap, SLOT(quit(int))); return app.exec(); } #include "prompt_main.moc" trust-store-2.0.0+16.04.20160119/src/core/trust/mir/prompt_main.h0000644000015600001650000000401312647452305024563 0ustar pbuserpbgroup00000000000000/* * 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_MIR_PROMPT_MAIN_H_ #define CORE_TRUST_MIR_PROMPT_MAIN_H_ namespace core { namespace trust { namespace mir { namespace env { /** @brief Name of the environment variable to pass Mir's endpoint in. */ static constexpr const char* option_mir_socket { "MIR_SOCKET" }; /** @brief Name of the environment variable that triggers loading of the testability plugin. */ static constexpr const char* option_testability { "QT_LOAD_TESTABILITY" }; } namespace cli { /** @brief Mir server socket to connect to. */ static constexpr const char* option_server_socket { "mir_server_socket" }; /** @brief Icon of the requesting app. */ static constexpr const char* option_icon { "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. */ static constexpr const char* option_description { "description" }; /** @brief Only checks command-line parameters and does not execute any actions. */ static constexpr const char* option_testing { "testing" }; /** @brief Loads the Qt Testability plugin if provided. */ static constexpr const char* option_testability { "testability" }; } } } } #endif // CORE_TRUST_MIR_PROMPT_MAIN_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/request.cpp0000644000015600001650000000607312647452272023505 0ustar pbuserpbgroup00000000000000/* * 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 core::trust::Request::Answer core::trust::process_trust_request(const core::trust::RequestParameters& params) { // We verify parameters first: if (not params.agent) throw std::logic_error { "Cannot operate without an agent implementation." }; if (not params.store) throw std::logic_error { "Cannot operate without a store implementation." }; // Let's see if the store has an answer for app-id and feature. auto query = params.store->query(); // Narrow it down to the specific app and the specific feature query->for_application_id(params.application_id); query->for_feature(params.feature); query->execute(); // We have got results and we take the most recent one as the most appropriate. if (query->status() == core::trust::Store::Query::Status::has_more_results) { // And we are returning early. return query->current().answer; } // We do not have results available in the store, prompting the user auto answer = params.agent->authenticate_request_with_parameters(core::trust::Agent::RequestParameters { params.application_uid, params.application_pid, params.application_id, params.feature, params.description }); params.store->add(core::trust::Request { params.application_id, params.feature, std::chrono::system_clock::now(), answer }); return answer; } bool core::trust::operator==(const core::trust::Request& lhs, const core::trust::Request& rhs) { return lhs.from == rhs.from && lhs.feature == rhs.feature && lhs.when == rhs.when && lhs.answer == rhs.answer; } std::ostream& core::trust::operator<<(std::ostream& out, const core::trust::Request::Answer& a) { switch (a) { case core::trust::Request::Answer::granted: out << "granted"; break; case core::trust::Request::Answer::denied: out << "denied"; break; } return out; } std::ostream& core::trust::operator<<(std::ostream& out, const core::trust::Request& r) { out << "Request(" << "from: " << r.from << ", " << "feature: " << r.feature << ", " << "when: " << r.when.time_since_epoch().count() << ", " << "answer: " << r.answer << ")"; return out; } trust-store-2.0.0+16.04.20160119/src/core/trust/preseed.cpp0000644000015600001650000000561012647452272023440 0ustar pbuserpbgroup00000000000000/* * 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 namespace Options = boost::program_options; std::istream& operator>>(std::istream& in, core::trust::Feature& f) { return in >> f.value; } std::istream& operator>>(std::istream& in, core::trust::Request::Answer& answer) { std::string s; in >> s; if (s == "denied") answer = core::trust::Request::Answer::denied; else if (s == "granted") answer = core::trust::Request::Answer::granted; else throw std::logic_error{"Could not parse answer: " + s}; return in; } core::trust::Preseed::Configuration core::trust::Preseed::Configuration::parse_from_command_line(int argc, const char** argv) { Options::variables_map vm; Options::options_description options{"Known options"}; options.add_options() (Parameters::ForService::name, Options::value()->required(), Parameters::ForService::description) (Parameters::Request::name, Options::value>()->composing(), Parameters::Request::description); Options::command_line_parser parser { argc, argv }; auto parsed_options = parser.options(options).allow_unregistered().run(); Options::store(parsed_options, vm); Options::notify(vm); auto service_name = vm[Parameters::ForService::name].as(); auto requests = vm[Parameters::Request::name].as>(); core::trust::Preseed::Configuration config { core::trust::create_default_store(service_name), {} // The empty set. }; for (const auto& request : requests) { std::stringstream ss{request}; core::trust::Request r; // Parse the request. ss >> r.from >> r.feature >> r.answer; // And set the timestamp to now. r.when = std::chrono::system_clock::now(); config.requests.push_back(r); } return config; } core::posix::exit::Status core::trust::Preseed::main(const core::trust::Preseed::Configuration& configuration) { for (const auto& request : configuration.requests) configuration.store->add(request); return core::posix::exit::Status::success; } trust-store-2.0.0+16.04.20160119/src/core/trust/expose.cpp0000644000015600001650000002544712647452272023326 0ustar pbuserpbgroup00000000000000/* * 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 "dbus/codec.h" #include "dbus/interface.h" #include #include #include #include #include namespace dbus = core::dbus; namespace { namespace detail { std::shared_ptr session_bus() { std::shared_ptr bus { new dbus::Bus(dbus::WellKnownBus::session) }; bus->install_executor(dbus::asio::make_executor(bus)); return bus; } template class Store { public: bool insert(const Key& key, const Value& value) { std::lock_guard lg(guard); bool result = false; std::tie(std::ignore, result) = map.insert(std::make_pair(key, value)); return result; } void erase(const Key& key) { std::lock_guard lg(guard); map.erase(key); } private: std::mutex guard; std::map map; }; struct Token : public core::trust::Token { Token(const std::string& service_name, const std::shared_ptr& bus, const std::shared_ptr& store) : store(store), bus(bus), service(dbus::Service::add_service(bus, service_name)), object(service->add_object_for_path(dbus::types::ObjectPath::root())) { object->install_method_handler([this](const core::dbus::Message::Ptr& msg) { handle_add(msg); }); object->install_method_handler([this](const core::dbus::Message::Ptr& msg) { handle_reset(msg); }); object->install_method_handler([this](const core::dbus::Message::Ptr& msg) { handle_add_query(msg); }); object->install_method_handler([this](const core::dbus::Message::Ptr& msg) { handle_remove_query(msg); }); worker = std::move(std::thread([this](){Token::bus->run();})); } ~Token() { object->uninstall_method_handler(); object->uninstall_method_handler(); object->uninstall_method_handler(); object->uninstall_method_handler(); bus->stop(); if (worker.joinable()) worker.join(); } void handle_add(const core::dbus::Message::Ptr& msg) { core::trust::Request request; msg->reader() >> request; try { store->add(request); } catch(const std::runtime_error& e) { auto error = dbus::Message::make_error( msg, core::trust::dbus::Store::Error::AddingRequest::name(), e.what()); bus->send(error); return; } auto reply = dbus::Message::make_method_return(msg); bus->send(reply); } void handle_reset(const core::dbus::Message::Ptr& msg) { try { store->reset(); } catch(const core::trust::Store::Errors::ErrorResettingStore& e) { auto error = core::dbus::Message::make_error( msg, core::trust::dbus::Store::Error::ResettingStore::name(), e.what()); bus->send(error); } auto reply = dbus::Message::make_method_return(msg); bus->send(reply); } void handle_add_query(const core::dbus::Message::Ptr& msg) { static std::uint64_t query_counter = 0; try { core::dbus::types::ObjectPath path{"/queries/" + std::to_string(query_counter++)}; auto query = store->query(); auto object = service->add_object_for_path(path); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { query->all(); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { try { auto request = query->current(); auto reply = core::dbus::Message::make_method_return(msg); reply->writer() << request; bus->send(reply); } catch(const core::trust::Store::Query::Errors::NoCurrentResult& e) { auto error = core::dbus::Message::make_error( msg, core::trust::dbus::Store::Query::Error::NoCurrentRequest::name(), e.what()); bus->send(error); } }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { query->erase(); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { query->execute(); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { core::trust::Request::Answer a; msg->reader() >> a; query->for_answer(a); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { std::string app_id; msg->reader() >> app_id; query->for_application_id(app_id); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { core::trust::Feature feature; msg->reader() >> feature; query->for_feature(feature); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { std::tuple interval; msg->reader() >> interval; auto begin = core::trust::Request::Timestamp{core::trust::Request::Duration{std::get<0>(interval)}}; auto end = core::trust::Request::Timestamp{core::trust::Request::Duration{std::get<1>(interval)}}; query->for_interval(begin, end); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { query->next(); auto reply = core::dbus::Message::make_method_return(msg); bus->send(reply); }); object->install_method_handler([this, query](const core::dbus::Message::Ptr& msg) { auto reply = core::dbus::Message::make_method_return(msg); reply->writer() << query->status(); bus->send(reply); }); query_store.insert(path, object); auto reply = dbus::Message::make_method_return(msg); reply->writer() << path; bus->send(reply); } catch(const std::runtime_error& e) { auto error = core::dbus::Message::make_error( msg, core::trust::dbus::Store::Error::CreatingQuery::name(), e.what()); bus->send(error); } } void handle_remove_query(const core::dbus::Message::Ptr& msg) { try { core::dbus::types::ObjectPath path; msg->reader() >> path; query_store.erase(path); auto reply = dbus::Message::make_method_return(msg); bus->send(reply); } catch(...) { } auto reply = dbus::Message::make_method_return(msg); reply->writer(); bus->send(reply); } std::shared_ptr store; std::shared_ptr bus; std::shared_ptr service; std::shared_ptr object; std::thread worker; detail::Store> query_store; }; } } std::unique_ptr core::trust::expose_store_to_bus_with_name( const std::shared_ptr& store, const std::shared_ptr& bus, const std::string& name) { if (name.empty()) throw Errors::ServiceNameMustNotBeEmpty{}; return std::move(std::unique_ptr { new detail::Token { "com.ubuntu.trust.store." + name, bus, store } }); } std::unique_ptr core::trust::expose_store_to_session_with_name( const std::shared_ptr& store, const std::string& name) { return std::move(core::trust::expose_store_to_bus_with_name(store, detail::session_bus(), name)); } trust-store-2.0.0+16.04.20160119/src/core/trust/app_id_formatting_trust_agent.cpp0000644000015600001650000000372312647452272030121 0ustar pbuserpbgroup00000000000000/* * 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 core::trust::AppIdFormattingTrustAgent::AppIdFormattingTrustAgent(const std::shared_ptr& impl) : impl{impl} { if (not impl) throw std::runtime_error { "Missing agent implementation." }; } // From core::trust::Agent core::trust::Request::Answer core::trust::AppIdFormattingTrustAgent::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& incoming_params) { auto params = incoming_params; // 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{"(.*)_(.*)_(.*)"}; static constexpr std::size_t index_package{1}; static constexpr std::size_t index_app{2}; // We store our matches here. std::smatch match; // See if the application id matches the pattern described in // https://wiki.ubuntu.com/AppStore/Interfaces/ApplicationId if (std::regex_match(params.application.id, match, regex)) { params.application.id = std::string{match[index_package]} + "_" + std::string{match[index_app]}; } return impl->authenticate_request_with_parameters(params); } trust-store-2.0.0+16.04.20160119/src/core/trust/daemon.h0000644000015600001650000002231212647452312022712 0ustar pbuserpbgroup00000000000000/* * 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_DAEMON_H_ #define CORE_TRUST_DAEMON_H_ #include #include #include #include #include #include #include #include #include namespace core { namespace trust { // Encapsulates an executable that allows services to run an out-of-process daemon for // managing trust to applications. The reason here is simple: Patching each and every // service in the system to use and link against the trust-store might not be feasible. // In those cases, an out-of-process store would be started given the services name. The // store exposes itself to the bus and subscribes to one or more request gates, processing // the incoming requests by leveraging an agent implementation. struct Daemon { // Just to safe some typing. typedef std::map Dictionary; // Collects all known local agents struct LocalAgents { LocalAgents() = delete; // 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. struct MirAgent { static constexpr const char* name { "MirAgent" }; }; // Implements the trust::Agent interface and dispatches calls to the user // leveraging whiptail to provide a dialog in a terminal. struct TerminalAgent { static constexpr const char* name { "TerminalAgent" }; }; }; // Collects all known remote agents struct RemoteAgents { RemoteAgents() = delete; // A remote agent implementation that exposes a unix domain socket in the // filesystem. The stub implementation exposes the socket and handles incoming // connections from its skeletons. For incoming requests, the stub selects the // handling skeleton based on the user id associated with the request. struct UnixDomainSocketRemoteAgent { static constexpr const char* name { "UnixDomainSocketRemoteAgent" }; }; // A remote agent implementation leveraging dbus. struct SystemServiceDBusRemoteAgent { static constexpr const char* name { "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" }; }; }; struct Skeleton { // Functor for creating trust::Agent instances. typedef std::function< std::shared_ptr( const std::string&, // The name of the service. 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( 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; // Returns a map for resolving names to local agent factories. static const std::map& known_local_agent_factories(); // Returns a map for resolving names to remote agent factories. static const std::map& known_remote_agent_factories(); // Command-line parameters, their name and their description struct Parameters { Parameters() = delete; struct StoreBus { static constexpr const char* name{"store-bus"}; static constexpr const char* description{"The bus that the remote store should be exposed on"}; }; struct ForService { static constexpr const char* name{"for-service"}; static constexpr const char* description{"The name of the service to handle trust for"}; }; struct WithTextDomain { static constexpr const char* name{"with-text-domain"}; static constexpr const char* description{"The text domain that should be used for translations"}; }; struct LocalAgent { static constexpr const char* name{"local-agent"}; static constexpr const char* description{"The local agent implementation"}; }; struct RemoteAgent { static constexpr const char* name{"remote-agent"}; static constexpr const char* description{"The remote agent implementation"}; }; }; // Collects all parameters for executing the daemon struct Configuration { // Parses the configuration from the given command line. static Configuration from_command_line(int argc, const char** argv); // The name of the service that the daemon should serve for. std::string service_name; // The bus instance to expose the remote store instance on. core::dbus::Bus::Ptr bus; // All local, i.e., actual implementations struct { // The store used for caching purposes. std::shared_ptr store; // The agent used for prompting the user. std::shared_ptr agent; } local; // All remote implementations for exposing the services // of this daemon instance. struct { std::shared_ptr agent; } remote; }; // Executes the daemon with the given configuration. static core::posix::exit::Status main(const Configuration& configuration); }; struct Stub { // Functor for creating trust::Agent instances. 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; // Returns a map for resolving names to remote agent factories. static const std::map& known_remote_agent_factories(); // Command-line parameters, their name and their description struct Parameters { Parameters() = delete; struct ForService { static constexpr const char* name{"for-service"}; static constexpr const char* description{"The name of the service to handle trust for"}; }; struct RemoteAgent { static constexpr const char* name{"remote-agent"}; static constexpr const char* description{"The remote agent implementation"}; }; }; // Collects all parameters for executing the daemon struct Configuration { // Parses the configuration from the given command line. static Configuration from_command_line(int argc, const char** argv); // The name of the service that the daemon should serve for. std::string service_name; // All remote agents. struct { // Trust requests are issued via this stub. std::shared_ptr agent; } remote; }; // Executes the daemon with the given configuration. static core::posix::exit::Status main(const Configuration& configuration); }; }; } } #endif // CORE_TRUST_DAEMON_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/daemon_skeleton_main.cpp0000644000015600001650000000252612647452272026167 0ustar pbuserpbgroup00000000000000/* * 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 int main(int argc, const char** argv) { google::InitGoogleLogging("core::trust::Daemon::Skeleton"); core::trust::Daemon::Skeleton::Configuration configuration; try { configuration = core::trust::Daemon::Skeleton::Configuration::from_command_line(argc, argv); } catch(std::exception const& e) { std::cerr << "Error during initialization and startup: " << boost::diagnostic_information(e) << std::endl; return EXIT_FAILURE; } return static_cast(core::trust::Daemon::Skeleton::main(configuration)); } trust-store-2.0.0+16.04.20160119/src/core/trust/preseed.h0000644000015600001650000000515112647452272023105 0ustar pbuserpbgroup00000000000000/* * 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_PRESEED_H_ #define CORE_TRUST_PRESEED_H_ #include #include #include namespace core { namespace trust { // A helper executable to inject cached answers into service specific trust caches. // Invoke it with: // trust-store-preseed // --for-service MyFunkyServiceName // --request "does.not.exist.app 0 granted" // --request "does.not.exist.app 1 granted" // --request "does.not.exist.app 2 denied" // --request "does.not.exist.app 3 granted" // --request "does.not.exist.app 4 granted" // --------------------------------------------- // | ---- app id ---- feature answer | struct Preseed { // Command-line parameters, their name and their description struct Parameters { Parameters() = delete; struct ForService { static constexpr const char* name{"for-service"}; static constexpr const char* description{"The name of the service to handle trust for."}; }; struct Request { static constexpr const char* name{"request"}; static constexpr const char* description{"Requests to be seeded into the trust store. Can be specified multiple times."}; }; }; // Parameters for execution of the preseed executable. struct Configuration { // Parses command line args and produces a configuration static Configuration parse_from_command_line(int argc, const char** argv); // The store that the answers should be inserted into. std::shared_ptr store; // The set of requests that should be preseeded into the store. std::vector requests; }; static core::posix::exit::Status main(const Configuration& configuration); }; } } #endif // CORE_TRUST_PRESEED_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/agent.cpp0000644000015600001650000000211512647452272023104 0ustar pbuserpbgroup00000000000000/* * 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 bool core::trust::operator==(const core::trust::Agent::RequestParameters& lhs, const core::trust::Agent::RequestParameters& rhs) { return std::tie(lhs.application.id, lhs.application.pid, lhs.application.uid, lhs.description, lhs.feature) == std::tie(rhs.application.id, rhs.application.pid, rhs.application.uid, rhs.description, rhs.feature); } trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.h0000644000015600001650000000440612647452305031274 0ustar pbuserpbgroup00000000000000/* * 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_ trust-store-2.0.0+16.04.20160119/src/core/trust/white_listing_agent.cpp0000644000015600001650000000326012647452272026037 0ustar pbuserpbgroup00000000000000/* * 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 core::trust::WhiteListingAgent::WhiteListingPredicate core::trust::WhiteListingAgent::always_grant_for_unconfined() { return [](const core::trust::Agent::RequestParameters& params) -> bool { return params.application.id == "unconfined"; }; } core::trust::WhiteListingAgent::WhiteListingAgent( core::trust::WhiteListingAgent::WhiteListingPredicate white_listing_predicate, const std::shared_ptr& impl) : white_listing_predicate{white_listing_predicate}, impl{impl} { if (not impl) throw std::runtime_error { "Missing agent implementation." }; } core::trust::Request::Answer core::trust::WhiteListingAgent::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) { if (white_listing_predicate(parameters)) return core::trust::Request::Answer::granted; return impl->authenticate_request_with_parameters(parameters); } trust-store-2.0.0+16.04.20160119/src/core/trust/daemon_stub_main.cpp0000644000015600001650000000251012647452272025311 0ustar pbuserpbgroup00000000000000/* * 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 int main(int argc, const char** argv) { google::InitGoogleLogging("core::trust::Daemon::Stub"); core::trust::Daemon::Stub::Configuration configuration; try { configuration = core::trust::Daemon::Stub::Configuration::from_command_line(argc, argv); } catch(const boost::exception& e) { std::cerr << "Error during initialization and startup: " << boost::diagnostic_information(e) << std::endl; return EXIT_FAILURE; } return static_cast(core::trust::Daemon::Stub::main(configuration)); } trust-store-2.0.0+16.04.20160119/src/core/trust/i18n.h0000644000015600001650000000276412647452272022244 0ustar pbuserpbgroup00000000000000/* * 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_I18N_H_ #define CORE_TRUST_I18N_H_ #include #include namespace core { namespace trust { namespace i18n { // Returns the default text domain of this package. CORE_TRUST_DLL_PUBLIC std::string default_text_domain(); // Returns the text domain of the service we are acting for CORE_TRUST_DLL_PUBLIC std::string service_text_domain(); // Adjusts the text domain of the service; CORE_TRUST_DLL_PUBLIC void set_service_text_domain(const std::string& domain); // Translates the given input string for the default domain. CORE_TRUST_DLL_PUBLIC std::string tr(const std::string& in); // Translates the given input string for the given domain. CORE_TRUST_DLL_PUBLIC std::string tr(const std::string& in, const std::string& domain); } } } #endif // CORE_TRUST_I18N_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/cached_agent.cpp0000644000015600001650000000620512647452272024377 0ustar pbuserpbgroup00000000000000/* * 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 void core::trust::CachedAgent::Reporter::report_cached_answer_found(const core::trust::Agent::RequestParameters&, const core::trust::Request&) { } void core::trust::CachedAgent::Reporter::report_user_prompted_for_trust(const core::trust::Agent::RequestParameters&, const core::trust::Request::Answer&) { } core::trust::CachedAgent::CachedAgent(const core::trust::CachedAgent::Configuration& configuration) : configuration(configuration) { // We verify parameters first: if (not configuration.agent) throw std::logic_error { "Cannot operate without an agent implementation." }; if (not configuration.store) throw std::logic_error { "Cannot operate without a store implementation." }; } // From core::trust::Agent core::trust::Request::Answer core::trust::CachedAgent::authenticate_request_with_parameters( const core::trust::Agent::RequestParameters& params) { // Let's see if the store has an answer for app-id and feature. auto query = configuration.store->query(); // Narrow it down to the specific app and the specific feature query->for_application_id(params.application.id); query->for_feature(params.feature); query->execute(); // We have got results and we take the most recent one as the most appropriate. if (query->status() == core::trust::Store::Query::Status::has_more_results) { // Tell the reporter that we found a cached answer. configuration.reporter->report_cached_answer_found(params, query->current()); // And we are returning early. return query->current().answer; } // We do not have results available in the store, prompting the user auto answer = configuration.agent->authenticate_request_with_parameters( core::trust::Agent::RequestParameters { params.application.uid, params.application.pid, params.application.id, params.feature, params.description }); // Tell the reporter that the user was successfully prompted for an answer. configuration.reporter->report_user_prompted_for_trust(params, answer); configuration.store->add(core::trust::Request { params.application.id, params.feature, std::chrono::system_clock::now(), answer }); return answer; } trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.h0000644000015600001650000000476512647452312023146 0ustar pbuserpbgroup00000000000000/* * 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_ trust-store-2.0.0+16.04.20160119/src/core/trust/privilege_escalation_prevention_agent.cpp0000644000015600001650000000343312647452305031626 0ustar pbuserpbgroup00000000000000/* * 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); } trust-store-2.0.0+16.04.20160119/src/core/trust/resolve.cpp0000644000015600001650000001710312647452272023470 0ustar pbuserpbgroup00000000000000/* * 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 #include "dbus/codec.h" #include "dbus/interface.h" #include #include #include namespace dbus = core::dbus; namespace { namespace detail { std::shared_ptr session_bus() { std::shared_ptr bus { new dbus::Bus(dbus::WellKnownBus::session) }; bus->install_executor(dbus::asio::make_executor(bus)); return bus; } struct Store : public core::trust::Store { Store(const std::shared_ptr& service, const std::shared_ptr& bus) : bus(bus), worker{[this]() { Store::bus->run(); }}, service(service), proxy(service->object_for_path(dbus::types::ObjectPath::root())) { } ~Store() { bus->stop(); if (worker.joinable()) worker.join(); } struct Query : public core::trust::Store::Query { core::dbus::types::ObjectPath path; std::shared_ptr parent; std::shared_ptr object; Query(const core::dbus::types::ObjectPath& path, const std::shared_ptr& parent, const std::shared_ptr& object) : path(path), parent(parent), object(object) { } ~Query() { try { parent->invoke_method_synchronously(path); } catch(...) { } } void all() { object->invoke_method_synchronously(); } core::trust::Request current() { auto result = object->invoke_method_synchronously< core::trust::dbus::Store::Query::Current, core::trust::Request>(); if (result.is_error()) { throw core::trust::Store::Query::Errors::NoCurrentResult{}; } return result.value(); } void erase() { auto result = object->invoke_method_synchronously(); if (result.is_error()) throw std::runtime_error(result.error().print()); } void execute() { auto result = object->invoke_method_synchronously(); if (result.is_error()) throw std::runtime_error(result.error().print()); } void for_answer(core::trust::Request::Answer answer) { auto result = object->invoke_method_synchronously(answer); if (result.is_error()) throw std::runtime_error(result.error().print()); } void for_application_id(const std::string &id) { auto result = object->invoke_method_synchronously(id); if (result.is_error()) throw std::runtime_error(result.error().print()); } void for_feature(core::trust::Feature feature) { auto result = object->invoke_method_synchronously(feature); if (result.is_error()) throw std::runtime_error(result.error().print()); } void for_interval(const core::trust::Request::Timestamp &begin, const core::trust::Request::Timestamp &end) { auto result = object->invoke_method_synchronously< core::trust::dbus::Store::Query::ForInterval, void>( std::make_tuple( begin.time_since_epoch().count(), end.time_since_epoch().count())); if (result.is_error()) throw std::runtime_error(result.error().print()); } void next() { auto result = object->invoke_method_synchronously(); if (result.is_error()) throw std::runtime_error(result.error().print()); } core::trust::Store::Query::Status status() const { auto result = object->invoke_method_synchronously< core::trust::dbus::Store::Query::Status, core::trust::Store::Query::Status>(); if (result.is_error()) throw std::runtime_error(result.error().print()); return result.value(); } }; void add(const core::trust::Request& r) { auto response = proxy->invoke_method_synchronously< core::trust::dbus::Store::Add, void>(r); if (response.is_error()) throw std::runtime_error(response.error().print()); } void reset() { try { auto response = proxy->invoke_method_synchronously< core::trust::dbus::Store::Reset, void>(); if (response.is_error()) { throw std::runtime_error(response.error().print()); } } catch(const std::runtime_error& e) { std::cout << e.what() << std::endl; } } std::shared_ptr query() { auto result = proxy->invoke_method_synchronously< core::trust::dbus::Store::AddQuery, core::dbus::types::ObjectPath>(); if (result.is_error()) throw std::runtime_error(result.error().print()); auto path = result.value(); auto query = std::shared_ptr(new detail::Store::Query { path, proxy, service->object_for_path(path) }); return query; } std::shared_ptr bus; std::thread worker; std::shared_ptr service; std::shared_ptr proxy; }; } } std::shared_ptr core::trust::resolve_store_on_bus_with_name( const std::shared_ptr& bus, const std::string& name) { if (name.empty()) throw Errors::ServiceNameMustNotBeEmpty{}; return std::shared_ptr { new detail::Store { core::dbus::Service::use_service(bus, "com.ubuntu.trust.store." + name), bus } }; } std::shared_ptr core::trust::resolve_store_in_session_with_name( const std::string& name) { return core::trust::resolve_store_on_bus_with_name(detail::session_bus(), name); } trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/0000755000015600001650000000000012647452606022241 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.h0000644000015600001650000000453012647452312024726 0ustar pbuserpbgroup00000000000000/* * 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_ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.cpp0000644000015600001650000000764012647452312024044 0ustar pbuserpbgroup00000000000000/* * 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} }; } trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent.h0000644000015600001650000000564612647452312023515 0ustar pbuserpbgroup00000000000000/* * 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_AGENT_H_ #define CORE_TRUST_DBUS_AGENT_H_ #include #include #include #include #include #include #include namespace core { namespace trust { namespace dbus { struct Agent { 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 { struct CouldNotDetermineConclusiveAnswer : public std::runtime_error { static constexpr const char* name { "core.trust.dbus.Agent.Errors.CouldNotDetermineConclusiveAnswer" }; CouldNotDetermineConclusiveAnswer(); }; }; // Just for scoping purposes struct Methods { // And thus not constructible Methods() = delete; DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(AuthenticateRequestWithParameters, Agent, 120000) }; class CORE_TRUST_DLL_PUBLIC Stub : public core::trust::Agent { public: Stub(const core::dbus::Object::Ptr& object); Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; private: core::dbus::Object::Ptr object; }; class CORE_TRUST_DLL_PUBLIC Skeleton : public core::trust::Agent { public: // All creation time parameters go here. struct Configuration { // The object that should implement core.trust.Agent core::dbus::Object::Ptr object; // The underlying bus instance core::dbus::Bus::Ptr bus; // The agent implementation std::function agent; }; Skeleton(const Configuration& config); Request::Answer authenticate_request_with_parameters(const RequestParameters& request) override; private: // We just store all creation time parameters. Configuration configuration; }; }; } } } #endif // CORE_TRUST_DBUS_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/bus_factory.cpp0000644000015600001650000000653512647452312025270 0ustar pbuserpbgroup00000000000000/* * 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; } trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/interface.h0000644000015600001650000002460612647452272024361 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_DBUS_INTERFACE_H_ #define CORE_TRUST_DBUS_INTERFACE_H_ #include #include #include #include #include #include namespace core { namespace dbus { namespace traits { template<> struct Service { static std::string interface_name() { return "core.trust.Store"; } }; template<> struct Service { static std::string interface_name() { return "core.trust.Store.Query"; } }; } } } namespace core { namespace trust { namespace dbus { struct Store { static const std::string& name() { static const std::string s{"com.ubuntu.trust.store"}; return s; } struct Error { struct AddingRequest { static const std::string& name() { static const std::string s { "core.trust.store.error.AddingRequest" }; return s; } typedef core::trust::Store Interface; }; struct ResettingStore { static const std::string& name() { static const std::string s { "core.trust.store.error.ResettingStore" }; return s; } typedef core::trust::Store Interface; }; struct CreatingQuery { static const std::string& name() { static const std::string s { "core.trust.store.error.CreatingQuery" }; return s; } typedef core::trust::Store Interface; }; }; struct Query { struct Error { struct NoCurrentRequest { static const std::string& name() { static const std::string s { "core.trust.store.query.error.NoCurrentRequest" }; return s; } typedef core::trust::Store Interface; }; }; struct Status { inline static const std::string& name() { static const std::string& s { "Status" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef core::trust::Store::Query::Status ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct ForApplicationId { inline static const std::string& name() { static const std::string& s { "ForApplicationId" }; return s; } typedef core::trust::Store::Query Interface; typedef std::string ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct ForFeature { inline static const std::string& name() { static const std::string& s { "ForFeature" }; return s; } typedef core::trust::Store::Query Interface; typedef std::uint64_t ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct ForInterval { inline static const std::string& name() { static const std::string& s { "ForInterval" }; return s; } typedef core::trust::Store::Query Interface; typedef std::tuple ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct ForAnswer { inline static const std::string& name() { static const std::string& s { "ForAnswer" }; return s; } typedef core::trust::Store::Query Interface; typedef core::trust::Request::Answer ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct All { inline static const std::string& name() { static const std::string& s { "All" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Execute { inline static const std::string& name() { static const std::string& s { "Execute" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Next { inline static const std::string& name() { static const std::string& s { "Next" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Erase { inline static const std::string& name() { static const std::string& s { "Erase" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Current { inline static const std::string& name() { static const std::string& s { "Current" }; return s; } typedef core::trust::Store::Query Interface; typedef void ArgumentType; typedef core::trust::Request ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; }; struct Add { inline static const std::string& name() { static const std::string& s { "Add" }; return s; } typedef core::trust::Store Interface; typedef core::trust::Request ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct Reset { inline static const std::string& name() { static const std::string& s { "Reset" }; return s; } typedef core::trust::Store Interface; typedef void ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct AddQuery { inline static const std::string& name() { static const std::string& s { "AddQuery" }; return s; } typedef core::trust::Store Interface; typedef void ArgumentType; typedef core::dbus::types::ObjectPath ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; struct RemoveQuery { inline static const std::string& name() { static const std::string& s { "RemoveQuery" }; return s; } typedef core::trust::Store Interface; typedef core::dbus::types::ObjectPath ArgumentType; typedef void ResultType; inline static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } }; }; } } } #endif // CORE_TRUST_DBUS_INTERFACE_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/codec.h0000644000015600001650000001052112647452272023465 0ustar pbuserpbgroup00000000000000/* * 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ß */ #ifndef CORE_TRUST_CODEC_H_ #define CORE_TRUST_CODEC_H_ #include #include #include #include #include #include #include namespace core { namespace dbus { template<> struct Codec { inline static void encode_argument(core::dbus::Message::Writer& writer, const core::trust::Request::Answer& arg) { writer.push_byte(static_cast(arg)); } inline static void decode_argument(core::dbus::Message::Reader& reader, core::trust::Request::Answer& arg) { arg = static_cast(reader.pop_byte()); } }; template<> struct Codec { inline static void encode_argument(core::dbus::Message::Writer& writer, const core::trust::Store::Query::Status& arg) { writer.push_byte(static_cast(arg)); } inline static void decode_argument(core::dbus::Message::Reader& reader, core::trust::Store::Query::Status& arg) { arg = static_cast(reader.pop_byte()); } }; template struct Codec> { inline static void encode_argument(core::dbus::Message::Writer& writer, const core::trust::TaggedInteger& arg) { writer.push_uint64(arg.value); } inline static void decode_argument(core::dbus::Message::Reader& reader, core::trust::TaggedInteger& arg) { arg.value = reader.pop_uint64(); } }; template<> struct Codec { inline static void encode_argument(core::dbus::Message::Writer& writer, const core::trust::Request& arg) { writer.push_stringn(arg.from.c_str(), arg.from.size()); writer.push_uint64(arg.feature.value); writer.push_uint64(std::chrono::duration_cast(arg.when.time_since_epoch()).count()); Codec::encode_argument(writer, arg.answer); } inline static void decode_argument(core::dbus::Message::Reader& reader, core::trust::Request& arg) { arg.from = reader.pop_string(); arg.feature.value = reader.pop_uint64(); arg.when = core::trust::Request::Timestamp{core::trust::Request::Duration{reader.pop_uint64()}}; Codec::decode_argument(reader, arg.answer); } }; template<> struct Codec { inline static void encode_argument(core::dbus::Message::Writer& writer, const core::trust::Agent::RequestParameters& arg) { Codec::encode_argument(writer, arg.application.uid); Codec::encode_argument(writer, arg.application.pid); Codec::encode_argument(writer, arg.application.id); Codec::encode_argument(writer, arg.feature); Codec::encode_argument(writer, arg.description); } inline static void decode_argument(core::dbus::Message::Reader& reader, core::trust::Agent::RequestParameters& arg) { Codec::decode_argument(reader, arg.application.uid); Codec::decode_argument(reader, arg.application.pid); Codec::decode_argument(reader, arg.application.id); Codec::decode_argument(reader, arg.feature); Codec::decode_argument(reader, arg.description); } }; } } #endif // CORE_TRUST_CODEC_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/dbus/agent_registry.h0000644000015600001650000003332012647452312025433 0ustar pbuserpbgroup00000000000000/* * 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_AGENT_REGISTRY_H_ #define CORE_TRUST_DBUS_AGENT_REGISTRY_H_ #include #include #include #include namespace core { namespace trust { // A thread-safe AgentRegistry implementation. class LockingAgentRegistry : public Agent::Registry { public: // From AgentRegistry void register_agent_for_user(const core::trust::Uid& uid, const std::shared_ptr& agent) override { std::lock_guard lg(guard); registered_agents[uid] = agent; } void unregister_agent_for_user(const core::trust::Uid& uid) override { std::lock_guard lg(guard); registered_agents.erase(uid); } // And some convenience // Returns true iff the registry knows about an agent for the given uid. bool has_agent_for_user(const core::trust::Uid& uid) const { std::lock_guard lg(guard); return registered_agents.count(uid) > 0; } // Returns the agent implementation for the given uid // or throws std::out_of_range if no agent is known for the uid. std::shared_ptr agent_for_user(const core::trust::Uid& uid) const { std::lock_guard lg(guard); return registered_agents.at(uid); } private: mutable std::mutex guard; std::map> registered_agents; }; namespace dbus { // Encapsulates stubs and skeletons for exposing/resolving an agent registry // over the bus. struct AgentRegistry { // To safe some typing typedef std::shared_ptr Ptr; // The interface name static const std::string& name() { static const std::string s { "core.trust.dbus.AgentRegistry" }; return s; } // Encapsulates errors that can occur when // using the stub or the skeleton. struct Errors { // The remote implementation could not register the // agent for the given user. struct CouldNotRegisterAgentForUser { static constexpr const char* name { "core.trust.dbus.AgentRegistry.CouldNotRegisterAgentForUser" }; }; }; // Encapsulates all methods known to the remote end. struct Methods { // Not constructible. Methods() = delete; // Maps to register_agent_for_user DBUS_CPP_METHOD_DEF(RegisterAgentForUser, AgentRegistry) // Maps to unregister_agent_for_user DBUS_CPP_METHOD_DEF(UnregisterAgentForUser, AgentRegistry) }; // A DBus stub implementation of core::trust::AgentRegistry. struct Stub : public core::trust::Agent::Registry { // Functor for generating unique object paths. typedef std::function ObjectPathGenerator; static ObjectPathGenerator counting_object_path_generator() { return [](const core::trust::Uid&) { static int counter{0}; return core::dbus::types::ObjectPath{"/core/trust/dbus/Agent/" + std::to_string(counter++)}; }; } // All creation time parameters go here. struct Configuration { // The remote object implementing core.trust.dbus.AgentRegistry. core::dbus::Object::Ptr object; // The object generator instance. ObjectPathGenerator object_path_generator; // The local service instance to add objects to. core::dbus::Service::Ptr service; // The underlying bus instance. core::dbus::Bus::Ptr bus; }; // Initializes stub access to the Stub. Stub(const Configuration& configuration) : configuration(configuration) { } // 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(const core::trust::Uid& uid, const std::shared_ptr& impl) override { // 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. auto result = configuration.object->transact_method(uid, path); if (result.is_error()) throw std::runtime_error { result.error().print() }; // All good, finally updating our local registry. 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 { auto result = configuration.object->transact_method(uid); // Updating our local registry even if the call to the remote end // might have failed. locking_agent_registry.unregister_agent_for_user(uid); if (result.is_error()) throw std::runtime_error { result.error().print() }; } // We just store all creation-time arguments. Configuration configuration; // Our local registry of agents LockingAgentRegistry locking_agent_registry; }; // A DBus skeleton implementation of core::trust::AgentRegistry. struct Skeleton : public core::trust::Agent::Registry { // Creation time parameters go here. struct Configuration { // Object to install an implementation of // core.trust.dbus.AgentRegistry on. core::dbus::Object::Ptr object; // Bus-connection for sending out replies. core::dbus::Bus::Ptr bus; // The actual implementation. core::trust::Agent::Registry& impl; }; // Setups up handlers for: // Methods::RegisterAgentForUser // Methods::UnregisterAgentForUser Skeleton(const Configuration& config) : configuration(config) { configuration.object->install_method_handler([this](const core::dbus::Message::Ptr& in) { core::trust::Uid uid; core::dbus::types::ObjectPath path; in->reader() >> uid >> path; // Assemble the stub Agent from the given parameters. auto service = core::dbus::Service::use_service(configuration.bus, in->sender()); auto object = service->object_for_path(path); std::shared_ptr agent { new core::trust::dbus::Agent::Stub { object } }; core::dbus::Message::Ptr reply; // Forward the registration request to the actual implementation. try { configuration.impl.register_agent_for_user(uid, agent); reply = core::dbus::Message::make_method_return(in); } catch(const std::exception&) { // TODO(tvoss): We should report the exception here. // For now, we silently drop it and return an empty description // to the sender to prevent from leaking any privacy/security-relevant // data to the other side. reply = core::dbus::Message::make_error( in, Errors::CouldNotRegisterAgentForUser::name, ""); } catch(...) { reply = core::dbus::Message::make_error( in, Errors::CouldNotRegisterAgentForUser::name, ""); } try { configuration.bus->send(reply); } catch(const std::exception&) { // TODO(tvoss): We should report the exception here. // We immediately remove the agent for the given user id // as the transaction to the other side did not complete. unregister_agent_for_user(uid); } catch(...) { // TODO(tvoss): We should report an issue here. // We immediately remove the agent for the given user id // as the transaction to the other side did not complete. unregister_agent_for_user(uid); } }); configuration.object->install_method_handler([this](const core::dbus::Message::Ptr& in) { core::trust::Uid uid; in->reader() >> uid; try { configuration.impl.unregister_agent_for_user(uid); } catch(const std::exception&) { // Just dropping the exception here. // We should definitely report any issues here, but // stay silent for now. } configuration.bus->send(core::dbus::Message::make_method_return(in)); }); } // Uninstalls method handlers. ~Skeleton() { configuration.object->uninstall_method_handler(); configuration.object->uninstall_method_handler(); } // Registers an agent for the given uid, // calls out to the implementation given at construction time. void register_agent_for_user(const core::trust::Uid& uid, const std::shared_ptr& agent) override { configuration.impl.register_agent_for_user(uid, agent); } // Removes the agent for the given uid from the registry, // calls out to the implementation given at construction time. void unregister_agent_for_user(const core::trust::Uid& uid) override { configuration.impl.unregister_agent_for_user(uid); } // We just store all creation time parameters Configuration configuration; }; }; } } } #endif // CORE_TRUST_DBUS_AGENT_REGISTRY_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/cached_agent_glog_reporter.h0000644000015600001650000000363712647452272027004 0ustar pbuserpbgroup00000000000000/* * 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_CACHED_AGENT_GLOG_REPORTER_H_ #define CORE_TRUST_CACHED_AGENT_GLOG_REPORTER_H_ #include namespace core { namespace trust { // Implements the CachedAgent::Reporter interface by leveraging Google Log. class CORE_TRUST_DLL_PUBLIC CachedAgentGlogReporter : public CachedAgent::Reporter { public: // All creation time arguments go here. struct Configuration { // By default, the implementation reports to syslog. // If this flag is set to true, logging also goes to stderr. bool also_log_to_stderr{true}; }; // Creates a reporter instance with the given configuration, and initializes Google logging. CachedAgentGlogReporter(const Configuration& configuration); // Invoked whenever the implementation was able to resolve a cached request. void report_cached_answer_found(const core::trust::Agent::RequestParameters& params, const core::trust::Request&); // Invoked whenever the implementation called out to an agent to prompt the user for trust. void report_user_prompted_for_trust(const core::trust::Agent::RequestParameters& params, const core::trust::Request::Answer&); }; } } #endif // CORE_TRUST_CACHED_AGENT_GLOG_REPORTER_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/terminal_agent.h0000644000015600001650000000627212647452272024454 0ustar pbuserpbgroup00000000000000/* * 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_TERMINAL_AGENT_H_ #define CORE_TRUST_TERMINAL_AGENT_H_ #include #include #include namespace core { namespace trust { // Agent implementation leveraging whiptail to display // a dialog box in the terminal. struct TerminalAgent : public core::trust::Agent { // Default width of the dialog box static constexpr int default_width{70}; // Default height of the dialog box static constexpr int default_height{10}; // Path to the whiptail executable. static constexpr const char* whiptail { "/bin/whiptail" }; // Constructs a new instance for the given service name. TerminalAgent(const std::string& service_name) : service_name{service_name} { } // From core::trust::Agent. Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override { std::map env; core::posix::this_process::env::for_each([&env](const std::string& k, const std::string& v) { env.insert(std::make_pair(k, v)); }); std::vector args { "--title", "\"Please audit access to: " + service_name + " by " + parameters.application.id + "\"", "--yes-button", "Grant", "--no-button", "Deny", "--yesno", "\"" + parameters.description + "\"", std::to_string(default_height), std::to_string(default_width) }; std::copy(args.begin(), args.end(), std::ostream_iterator(std::cout, " ")); auto whiptail_process = core::posix::exec( whiptail, args, env, core::posix::StandardStream::empty); auto result = whiptail_process.wait_for(core::posix::wait::Flags::untraced); // We now analyze the result of the process execution. if (core::posix::wait::Result::Status::exited != result.status) throw std::logic_error { "Unable to determine a conclusive answer from the user" }; // If the child process did not exit cleanly, we deny access to the resource. if (core::posix::exit::Status::failure == result.detail.if_exited.status) return core::trust::Request::Answer::denied; return core::trust::Request::Answer::granted; } // The name of the service we are acting for. std::string service_name; }; } } #endif // CORE_TRUST_TERMINAL_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/cached_agent_glog_reporter.cpp0000644000015600001650000000433212647452272027330 0ustar pbuserpbgroup00000000000000/* * 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 // Creates a reporter instance with the given configuration, and initializes Google logging. core::trust::CachedAgentGlogReporter::CachedAgentGlogReporter(const core::trust::CachedAgentGlogReporter::Configuration& configuration) { FLAGS_alsologtostderr = configuration.also_log_to_stderr; } // Invoked whenever the implementation was able to resolve a cached request. void core::trust::CachedAgentGlogReporter::report_cached_answer_found(const core::trust::Agent::RequestParameters& params, const core::trust::Request& r) { SYSLOG(INFO) << "CachedAgent::authenticate_request_with_parameters:" << " Application pid: " << params.application.pid << " Application uid: " << params.application.uid << " Application id: " << params.application.id << " Cached request: " << r; } // Invoked whenever the implementation called out to an agent to prompt the user for trust. void core::trust::CachedAgentGlogReporter::report_user_prompted_for_trust(const core::trust::Agent::RequestParameters& params, const core::trust::Request::Answer& a) { SYSLOG(INFO) << "CachedAgent::authenticate_request_with_parameters: No cached answer, prompted user for trust:" << " Application pid: " << params.application.pid << " Application uid: " << params.application.uid << " Application id: " << params.application.id << " User's answer: " << a; } trust-store-2.0.0+16.04.20160119/src/core/trust/runtime.cpp0000644000015600001650000000451112647452312023466 0ustar pbuserpbgroup00000000000000/* * 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); } trust-store-2.0.0+16.04.20160119/src/core/trust/white_listing_agent.h0000644000015600001650000000341612647452272025507 0ustar pbuserpbgroup00000000000000/* * 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_WHITE_LISTING_AGENT_H_ #define CORE_TRUST_WHITE_LISTING_AGENT_H_ #include namespace core { namespace trust { // An agent implementation that allows for selectively whitelisting app ids. class CORE_TRUST_DLL_PUBLIC WhiteListingAgent : public core::trust::Agent { public: // A functor that is evaluated for every incoming requests. // If it returns true, the request is immediately granted, otherwise passed on // to the next agent. typedef std::function WhiteListingPredicate; // Returns a predicate that returns true iff the app id is 'unconfined'. static WhiteListingPredicate always_grant_for_unconfined(); WhiteListingAgent(WhiteListingPredicate white_listing_predicate, const std::shared_ptr& impl); // From core::trust::Agent Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters) override; private: WhiteListingPredicate white_listing_predicate; std::shared_ptr impl; }; } } #endif // CORE_TRUST_WHITE_LISTING_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/impl/0000755000015600001650000000000012647452606022245 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/0000755000015600001650000000000012647452606023631 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.h0000644000015600001650000000255512647452305025141 0ustar pbuserpbgroup00000000000000/* * 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_ trust-store-2.0.0+16.04.20160119/src/core/trust/impl/sqlite3/store.cpp0000644000015600001650000005524612647452305025501 0ustar pbuserpbgroup00000000000000/* * 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 #include #include #include #include #include #include #include #include namespace fs = boost::filesystem; namespace core { 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) { case SQLITE_OK: case SQLITE_DONE: case SQLITE_ROW: return std::make_pair(result, false); break; default: return std::make_pair(result, true); } } struct Database; class PreparedStatement { public: enum class State { done = SQLITE_DONE, row = SQLITE_ROW }; PreparedStatement() : db(nullptr), statement(nullptr) { } PreparedStatement(const PreparedStatement&) = delete; PreparedStatement(PreparedStatement&& rhs) : db(rhs.db), statement(rhs.statement) { rhs.db = nullptr; rhs.statement = nullptr; } virtual ~PreparedStatement() { sqlite3_finalize(statement); } PreparedStatement& operator=(PreparedStatement&& rhs) { if (statement) { sqlite3_finalize(statement); } db = rhs.db; statement = rhs.statement; rhs.db = nullptr; rhs.statement = nullptr; return *this; } PreparedStatement& operator=(const PreparedStatement&) = delete; bool operator==(const PreparedStatement&) const = delete; template void bind_null() { int result; bool error; std::tie(result, error) = is_error(sqlite3_bind_null(statement, index)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } template void bind_double(double d) { int result; bool error; std::tie(result, error) = is_error(sqlite3_bind_double(statement, index, d)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } template void bind_text(const std::string& s) { if (s.empty()) return; auto memory = (char*)::malloc(s.size()); ::memcpy(memory, s.c_str(), s.size()); auto deleter = [](void* p) { if (p) ::free(p); }; int result; bool error; std::tie(result, error) = is_error(sqlite3_bind_text(statement, index, memory, s.size(), deleter)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } template void bind_int(std::int32_t i) { int result; bool error; std::tie(result, error) = is_error(sqlite3_bind_int(statement, index, i)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } template void bind_int64(std::int64_t i) { int result; bool error; std::tie(result, error) = is_error(sqlite3_bind_int64(statement, index, i)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } template std::int32_t column_int() { return sqlite3_column_int(statement, index); } template std::int64_t column_int64() { return sqlite3_column_int64(statement, index); } template std::string column_text() { auto ptr = reinterpret_cast(sqlite3_column_text(statement, index)); return (ptr ? ptr : ""); } void reset() { int result; bool error; std::tie(result, error) = is_error(sqlite3_reset(statement)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } void clear_bindings() { int result; bool error; std::tie(result, error) = is_error(sqlite3_clear_bindings(statement)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); } State step() { int result; bool error; std::tie(result, error) = is_error(sqlite3_step (statement)); if (error) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error_from_db()); return static_cast(result); } protected: friend struct Database; PreparedStatement(Database* db, sqlite3_stmt* statement) : db(db), statement(statement) { if (!statement) throw std::runtime_error("Cannot construct prepared statement for null statement."); } std::string error_from_db() const; Database* db; sqlite3_stmt* statement; }; template struct TaggedPreparedStatement : public PreparedStatement { TaggedPreparedStatement() : PreparedStatement() { } TaggedPreparedStatement(Database* db, sqlite3_stmt* statement) : PreparedStatement(db, statement) { } }; struct Database { Database(const std::string& fn) { auto result = sqlite3_open(fn.c_str(), &db); if (result != SQLITE_OK) { std::stringstream ss; ss << "Problem opening database file " << fn << ": " << sqlite3_errstr(result); throw std::runtime_error(ss.str()); }; sqlite3_extended_result_codes(db, 1); } Database(const Database&) = delete; ~Database() { sqlite3_close(db); } Database& operator=(const Database&) = delete; bool operator==(const Database&) = delete; void set_version(std::int32_t version) { std::string pragma = "PRAGMA user_version=" + std::to_string(version) + ";"; prepare_statement(pragma).step(); } std::int32_t get_version() { auto stmt = prepare_statement("PRAGMA user_version;"); stmt.step(); return stmt.column_int<0>(); } PreparedStatement prepare_statement(const std::string& statement) { sqlite3_stmt* stmt = nullptr; int result; bool e; std::tie(result, e) = is_error( sqlite3_prepare( db, statement.c_str(), statement.size(), &stmt, nullptr)); if (e) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error()); return PreparedStatement(this, stmt); } template TaggedPreparedStatement prepare_tagged_statement() { sqlite3_stmt* stmt = nullptr; int result; bool e; std::tie(result, e) = is_error( sqlite3_prepare( db, Statement::statement().c_str(), Statement::statement().size(), &stmt, nullptr)); if (e) throw std::runtime_error(sqlite3_errstr(result) + std::string(": ") + error()); return TaggedPreparedStatement(this, stmt); } std::string error() const { auto msg = sqlite3_errmsg(db); return std::string{(msg ? msg : "")}; } sqlite3* db = nullptr; }; std::string PreparedStatement::error_from_db() const { return db->error(); } // A store implementation persisting requests in an sqlite database. struct Store : public core::trust::Store, public std::enable_shared_from_this { // Our schema version constant. static constexpr const std::int32_t version{1}; // Describes the table and its schema for storing requests. struct RequestsTable { RequestsTable() = delete; // The name of the table. static const std::string& name() { static const std::string s{"requests"}; return s; } // Collects all columns, their names and indices. // // |-------------------------------------------------------------------------------------| // | Id : int | ApplicationId : Text | Feature : int | Timestamp : int64 | Answer : int | // |-------------------------------------------------------------------------------------| struct Column { Column() = delete; struct Id { static const std::string& name() { static const std::string s{"'Id'"}; return s; } static const int index = 0; }; struct ApplicationId { static const std::string& name() { static const std::string s{"'ApplicationId'"}; return s; } static const int index = 1; }; struct Feature { static const std::string& name() { static const std::string s{"'Feature'"}; return s; } static const int index = 2; }; struct Timestamp { static const std::string& name() { static const std::string s{"'Timestamp'"}; return s; } static const int index = 3; }; struct Answer { static const std::string& name() { static const std::string s{"'Answer'"}; return s; } static const int index = 4; }; }; }; struct Statements { struct CreateDataTableIfNotExists { static const std::string& statement() { static const std::string s { "CREATE TABLE IF NOT EXISTS " + sqlite::Store::RequestsTable::name() + " (" + sqlite::Store::RequestsTable::Column::Id::name() + " INTEGER PRIMARY KEY ASC, " + sqlite::Store::RequestsTable::Column::ApplicationId::name() + " TEXT NOT NULL, " + sqlite::Store::RequestsTable::Column::Feature::name() + " BIGINT, " + sqlite::Store::RequestsTable::Column::Timestamp::name() + " BIGINT, " + sqlite::Store::RequestsTable::Column::Answer::name() + " INTEGER);" }; return s; } }; struct Delete { static const std::string& statement() { static const std::string s { "DELETE FROM " + sqlite::Store::RequestsTable::name() }; return s; } }; struct Insert { static const std::string& statement() { static const std::string s { "INSERT INTO " + Store::RequestsTable::name() + " ('ApplicationId','Feature','Timestamp','Answer') VALUES (?,?,?,?);" }; return s; } }; }; // An implementation of the query interface for the SQLite-based store. struct Query : public core::trust::Store::Query { struct Statements { // Encodes the parameter-index for the prepared delete statement. struct Delete { static const std::string& statement() { static const std::string s { "DELETE FROM " + Store::RequestsTable::name() + " WHERE Id=?;" }; return s; } struct Parameter { struct Id { static const int index = 1; }; }; }; // Encodes the parameter-indices for the prepared select statement. struct Select { static const std::string& statement() { static const std::string select { "SELECT * FROM " + Store::RequestsTable::name() + " WHERE ApplicationId=IFNULL(?,ApplicationId) AND" " Feature=IFNULL(?,Feature) AND" " (Timestamp BETWEEN IFNULL(?, Timestamp) AND IFNULL(?,Timestamp)) AND" " Answer=IFNULL(?,Answer)" " ORDER BY Timestamp DESC;" }; return select; } struct Parameter { struct ApplicationId { static const int index = 1; }; struct Feature { static const int index = ApplicationId::index + 1; }; struct Timestamp { struct LowerBound { static const int index = Feature::index + 1; }; struct UpperBound { static const int index = LowerBound::index + 1; }; }; struct Answer { static const int index = Timestamp::UpperBound::index + 1; }; }; }; }; // Constructs the query and associates it with its store. // That is: As long as a query is alive, the store is kept alive, too. Query(const std::shared_ptr& store) : d{store} { // A freshly constructed query finds all entries. all(); } Status status() const { return d.status; } void for_application_id(const std::string& id) { d.select_statement.bind_text< Statements::Select::Parameter::ApplicationId::index >(id); } void for_feature(core::trust::Feature feature) { d.select_statement.bind_int64< Statements::Select::Parameter::Feature::index >(feature.value); } void for_interval(const Request::Timestamp& begin, const Request::Timestamp& end) { d.select_statement.bind_int64< Statements::Select::Parameter::Timestamp::LowerBound::index >(begin.time_since_epoch().count()); d.select_statement.bind_int64< Statements::Select::Parameter::Timestamp::UpperBound::index >(end.time_since_epoch().count()); } void for_answer(Request::Answer answer) { d.select_statement.bind_int< Statements::Select::Parameter::Answer::index >(static_cast(answer)); } void all() { d.select_statement.reset(); d.select_statement.clear_bindings(); } void execute() { d.select_statement.reset(); auto result = d.select_statement.step(); switch(result) { case TaggedPreparedStatement::State::done: d.status = Status::eor; break; case TaggedPreparedStatement::State::row: d.status = Status::has_more_results; break; } } void next() { auto result = d.select_statement.step(); switch(result) { case TaggedPreparedStatement::State::done: d.status = Status::eor; break; case TaggedPreparedStatement::State::row: d.status = Status::has_more_results; break; } } void erase() { if (Status::eor == d.status) throw std::runtime_error("Cannot delete request as query points beyond the result set."); auto id = d.select_statement.column_int(); d.delete_statement.reset(); d.delete_statement.bind_int(id); d.delete_statement.step(); next(); } Request current() { switch(d.status) { case Status::error: throw Errors::QueryIsInErrorState{}; case Status::eor: throw Errors::NoCurrentResult{}; case Status::armed: throw Errors::NoCurrentResult{}; default: { trust::Request request { d.select_statement.column_text(), trust::Feature { static_cast(d.select_statement.column_int()) }, std::chrono::system_clock::time_point { std::chrono::system_clock::duration { d.select_statement.column_int64() } }, (Request::Answer)d.select_statement.column_int() }; return request; } } throw std::runtime_error("Oops ... we should never reach here."); } struct Private { Private(const std::shared_ptr& store) : store(store), delete_statement(store->db.prepare_tagged_statement()), select_statement(store->db.prepare_tagged_statement()) { } ~Private() { } std::shared_ptr store; TaggedPreparedStatement delete_statement; TaggedPreparedStatement select_statement; Status status = Status::armed; std::string error; } d; }; Store(const std::string &service_name, xdg::BaseDirSpecification& spec); ~Store(); // Handles upgrades to the underlying database if the schema changes. void upgrade(std::int32_t from_version); const char* error() const; // Creates the data table holding all requests if it not already exists. void create_data_table_if_not_exists(); // From core::trust::Store void reset(); void add(const Request& request); std::shared_ptr query(); std::mutex guard; Database db; TaggedPreparedStatement create_data_table_statement; TaggedPreparedStatement delete_statement; TaggedPreparedStatement insert_statement; }; } } } } namespace trust = core::trust; namespace sqlite = core::trust::impl::sqlite; 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()); delete_statement = db.prepare_tagged_statement(); insert_statement = db.prepare_tagged_statement(); } sqlite::Store::~Store() { } void sqlite::Store::upgrade(std::int32_t from_version) { switch (from_version) { case 0: create_data_table_if_not_exists(); db.set_version(Store::version); break; default: break; } } void sqlite::Store::create_data_table_if_not_exists() { create_data_table_statement.step(); } void sqlite::Store::reset() { std::lock_guard lg(guard); try { delete_statement.reset(); delete_statement.step(); } catch(const std::runtime_error& e) { throw trust::Store::Errors::ErrorResettingStore{e.what()}; } } void sqlite::Store::add(const trust::Request& request) { std::lock_guard lg(guard); insert_statement.reset(); insert_statement.bind_text(request.from); insert_statement.bind_int(request.feature.value); insert_statement.bind_int64(request.when.time_since_epoch().count()); insert_statement.bind_int(static_cast(request.answer)); insert_statement.step(); } std::shared_ptr sqlite::Store::query() { return std::shared_ptr{new sqlite::Store::Query{shared_from_this()}}; } std::shared_ptr core::trust::impl::sqlite::create_for_service(const std::string& name, xdg::BaseDirSpecification& spec) { if (name.empty()) throw core::trust::Errors::ServiceNameMustNotBeEmpty(); 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()); } trust-store-2.0.0+16.04.20160119/src/core/trust/remote/0000755000015600001650000000000012647452606022577 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/src/core/trust/remote/helpers.h0000644000015600001650000000301612647452272024411 0ustar pbuserpbgroup00000000000000/* * 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_REMOTE_HELPERS_H_ #define CORE_TRUST_REMOTE_HELPERS_H_ #include #include #include #include namespace core { namespace trust { namespace remote { namespace helpers { // Functor abstracting pid -> process start time resolving typedef std::function ProcessStartTimeResolver; // Queries the start time of a process by reading /proc/{PID}/stat. CORE_TRUST_DLL_PUBLIC ProcessStartTimeResolver proc_stat_start_time_resolver(); // Functor abstracting pid -> app name resolving typedef std::function AppIdResolver; // Queries the app armor confinement profile to resolve the application id. CORE_TRUST_DLL_PUBLIC AppIdResolver aa_get_task_con_app_id_resolver(); } } } } #endif // CORE_TRUST_REMOTE_HELPERS_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/remote/helpers.cpp0000644000015600001650000000445312647452272024752 0ustar pbuserpbgroup00000000000000/* * 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 namespace trust = core::trust; namespace remote = core::trust::remote; // Queries the start time of a process by reading /proc/{PID}/stat. remote::helpers::ProcessStartTimeResolver remote::helpers::proc_stat_start_time_resolver() { return [](trust::Pid pid) { core::posix::Process process{pid.value}; core::posix::linux::proc::process::Stat stat; process >> stat; return stat.start_time; }; } remote::helpers::AppIdResolver remote::helpers::aa_get_task_con_app_id_resolver() { return [](trust::Pid pid) { static const int app_armor_error{-1}; // We make sure to clean up the returned string. struct Scope { ~Scope() { if (con) ::free(con); } char* con{nullptr}; char* mode{nullptr}; } scope; // Reach out to apparmor auto rc = aa_gettaskcon(pid.value, &scope.con, &scope.mode); // From man aa_gettaskcon: // On success size of data placed in the buffer is returned, this includes the mode if //present and any terminating characters. On error, -1 is returned, and errno(3) is //set appropriately. if (rc == app_armor_error) throw std::system_error { errno, std::system_category() }; // Safely construct the string return std::string { scope.con ? scope.con : "" }; }; } trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.cpp0000644000015600001650000000737212647452312024243 0ustar pbuserpbgroup00000000000000/* * 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 core::trust::remote::dbus::Agent::Stub::Stub(const core::trust::remote::dbus::Agent::Stub::Configuration& configuration) : agent_registry_skeleton { core::trust::dbus::AgentRegistry::Skeleton::Configuration { configuration.object, configuration.bus, agent_registry } } { } core::trust::Request::Answer core::trust::remote::dbus::Agent::Stub::send(const core::trust::Agent::RequestParameters& parameters) { if (not agent_registry.has_agent_for_user(parameters.application.uid)) return core::trust::Request::Answer::denied; auto agent = agent_registry.agent_for_user(parameters.application.uid); return agent->authenticate_request_with_parameters(parameters); } 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 { config.agent_registry_object, core::trust::dbus::AgentRegistry::Stub::counting_object_path_generator(), config.service, config.bus } } { 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) { return remote::Agent::Skeleton::authenticate_request_with_parameters(parameters); } std::shared_ptr core::trust::dbus::create_multi_user_agent_for_bus_connection( const std::shared_ptr& connection, const std::string& service_name) { auto dbus_service_name = core::trust::remote::dbus::default_service_name_prefix + std::string{"."} + service_name; auto service = core::dbus::Service::add_service(connection, dbus_service_name); auto object = service->add_object_for_path(core::dbus::types::ObjectPath { core::trust::remote::dbus::default_agent_registry_path }); core::trust::remote::dbus::Agent::Stub::Configuration config { object, connection }; return std::shared_ptr { new core::trust::remote::dbus::Agent::Stub { config } }; } trust-store-2.0.0+16.04.20160119/src/core/trust/remote/agent.cpp0000644000015600001650000000244512647452272024405 0ustar pbuserpbgroup00000000000000/* * 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 "core/trust/remote/agent.h" namespace trust = core::trust; namespace remote = core::trust::remote; core::trust::Request::Answer remote::Agent::Stub::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) { return send(parameters); } remote::Agent::Skeleton::Skeleton(const std::shared_ptr& impl) : impl{impl} { } core::trust::Request::Answer remote::Agent::Skeleton::authenticate_request_with_parameters(const core::trust::Agent::RequestParameters& parameters) { return impl->authenticate_request_with_parameters(parameters); } trust-store-2.0.0+16.04.20160119/src/core/trust/remote/posix.h0000644000015600001650000002267612647452272024126 0ustar pbuserpbgroup00000000000000/* * 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_REMOTE_POSIX_H_ #define CORE_TRUST_REMOTE_POSIX_H_ #include #include #include #include #include #include #include #include #include #include #include namespace core { namespace trust { namespace remote { // A remote agent implementation that exposes a unix domain socket in the // filesystem. The stub implementation exposes the socket and handles incoming // connections from its skeletons. For incoming requests, the stub selects the // handling skeleton based on the user id associated with the request. namespace posix { // Our distilled-down request that we share between stub and skeleton. struct CORE_TRUST_DLL_PUBLIC Request { // Id of the user that the requesting app is running under. Uid app_uid; // The process id of the requesting app. Pid app_pid; // The service-specific feature. Feature feature; // We want to prevent from spoofing and send over the process start time. // In seconds since the epoch. std::int64_t app_start_time; }; // Models the sending end of a remote agent, meant to be used by trusted helpers. class CORE_TRUST_DLL_PUBLIC Stub : public core::trust::remote::Agent::Stub, public std::enable_shared_from_this { public: // Just for convenience typedef std::shared_ptr Ptr; // Functor resolving a socket's peer's credentials typedef std::function< std::tuple< Uid, // The user ID of the peer Pid, // The process ID of the peer Gid // The group ID of the peer >(int) // Handle to the socket > PeerCredentialsResolver; // Returns a peer credentials resolver that leverages getsockopt. static PeerCredentialsResolver get_sock_opt_credentials_resolver(); // We create a session per incoming connection. struct Session { // Just for convenience typedef std::shared_ptr Ptr; // A fancy map implementing the monitor pattern. // All functions in this class are thread-safe, but _not_ reentrant. class Registry { public: typedef std::shared_ptr Ptr; Registry() = default; virtual ~Registry() = default; // Returns true iff the registry instance contains a session for the given user id. virtual bool has_session_for_uid(Uid uid) const; // Adds the given session for the given uid to the registry. virtual void add_session_for_uid(Uid uid, Session::Ptr session); // Removes the session instance for the given user id. virtual void remove_session_for_uid(Uid uid); // Queries the session for the given user id. // Throws std::out_of_range if no session is known for the user id. virtual Session::Ptr resolve_session_for_uid(Uid uid); private: mutable std::mutex guard; std::map sessions; }; // Creates a new session. Session(boost::asio::io_service& io_service); // The socket we are operating on. boost::asio::local::stream_protocol::socket socket; // We have to synchronize requests per session. std::mutex lock; }; // All creation time arguments go here. struct Configuration { // The runtime instance to associate to. boost::asio::io_service& io_service; // The endpoint in the filesystem. boost::asio::local::stream_protocol::endpoint endpoint; // Helper to map pid -> process start time helpers::ProcessStartTimeResolver start_time_resolver; // Helper to resolve peer credentials PeerCredentialsResolver peer_credentials_resolver; // A synchronized registry of all known sessions. Session::Registry::Ptr session_registry; }; // Creates a stub instance for the given configuration. // The returned instance is waiting for incoming connections. static Ptr create_stub_for_configuration(const Configuration& config); // Frees all resources and cancels any outstanding async operation // on the endpoint. virtual ~Stub(); // From core::trust::remote::Agent::Stub. core::trust::Request::Answer send(const core::trust::Agent::RequestParameters& parameters) override; // For testing purposes bool has_session_for_uid(Uid uid) const; private: // Creates a new instance with the given configuration. // Throws in case of errors. Stub(Configuration configuration); // Starts listening on the endpoint configured at creation time // for incoming connections. void start_accept(); // Called in case of an incoming connection. void on_new_session(const boost::system::error_code& ec, const Session::Ptr& session); // Interprets the given error code, carrying out maintenance on the Session::Registry // before rethrowing as a std::system_error. void handle_error_from_socket_operation_for_uid(const boost::system::error_code& ec, Uid uid); // The io dispatcher that this instance is associated with. boost::asio::io_service& io_service; // The endpoint that this instance is bound to. boost::asio::local::stream_protocol::endpoint end_point; // The acceptor object for handling incoming connection requests. boost::asio::local::stream_protocol::acceptor acceptor; // Helper to map pid -> process start time. helpers::ProcessStartTimeResolver start_time_resolver; // Helper for resolving a socket's peer's credentials. PeerCredentialsResolver peer_credentials_resolver; // A synchronized registry of all known sessions. Session::Registry::Ptr session_registry; }; // Models the receiving end of a remote agent, meant to be used by the trust store daemon. class CORE_TRUST_DLL_PUBLIC Skeleton : public core::trust::remote::Agent::Skeleton, public std::enable_shared_from_this { public: // Just for convenience typedef std::shared_ptr Ptr; // All creation-time arguments go here. struct Configuration { // The agent impl. std::shared_ptr impl; // The runtime instance to associate to. boost::asio::io_service& io_service; // The endpoint in the filesystem. boost::asio::local::stream_protocol::endpoint endpoint; // Helper for resolving a pid to the process's start time. helpers::ProcessStartTimeResolver start_time_resolver; // Helper for resolving a pid to an application id. helpers::AppIdResolver app_id_resolver; // Pattern for assembling the prompt dialog's description given // an app id. std::string description_format; // If set to true, enforces spoofing-prevention by inspecting and comparing // process start times. This causes issues for the case of crossing the // Android/Ubuntu boundary and we have to make it configurable. bool verify_process_start_time; }; static Ptr create_skeleton_for_configuration(const Configuration& configuration); virtual ~Skeleton(); private: // Constructs a new Skeleton instance, installing impl for handling actual requests. Skeleton(const Configuration& configuration); // Called to initiate an async read operation. void start_read(); // Called whenever a read operation from the socket finishes. void on_read_finished(const boost::system::error_code& ec, std::size_t size); // Handles an incoming request, reaching out to the super class implementation // to obtain an answer to the trust request. core::trust::Request::Answer process_incoming_request(const posix::Request& request); // Request object that we read into. posix::Request request; // Helper for resolving pid -> start time. helpers::ProcessStartTimeResolver start_time_resolver; // Helper for resolving pid -> application id. helpers::AppIdResolver app_id_resolver; // Pattern for assembling the prompt dialog's description given // an app id. std::string description_pattern; // If set to true, enforces spoofing-prevention by inspecting and comparing // process start times. This causes issues for the case of crossing the // Android/Ubuntu boundary and we have to make it configurable. bool verify_process_start_time; // The endpoint in the filesystem that we are connected with. boost::asio::local::stream_protocol::endpoint endpoint; // The actual socket for communication with the service. boost::asio::local::stream_protocol::socket socket; }; } } } } #endif // CORE_TRUST_REMOTE_POSIX_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/remote/posix.cpp0000644000015600001650000002364012647452272024451 0ustar pbuserpbgroup00000000000000/* * 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 #include #include #include #include #include namespace trust = core::trust; namespace remote = core::trust::remote; remote::posix::Stub::PeerCredentialsResolver remote::posix::Stub::get_sock_opt_credentials_resolver() { return [](int socket) { static const int get_sock_opt_error = -1; ::ucred peer_credentials { 0, 0, 0 }; ::socklen_t len = sizeof(peer_credentials); auto rc = ::getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &peer_credentials, &len); if (rc == get_sock_opt_error) throw std::system_error { errno, std::system_category() }; return std::make_tuple( core::trust::Uid{peer_credentials.uid}, core::trust::Pid{peer_credentials.pid}, core::trust::Gid{peer_credentials.gid}); }; } bool remote::posix::Stub::Session::Registry::has_session_for_uid(core::trust::Uid uid) const { std::lock_guard lg(guard); return sessions.count(uid) > 0; } void remote::posix::Stub::Session::Registry::add_session_for_uid(core::trust::Uid uid, Session::Ptr session) { if (not session) throw std::logic_error { "Cannot add null session to registry." }; std::lock_guard lg(guard); sessions[uid] = session; } void remote::posix::Stub::Session::Registry::remove_session_for_uid(core::trust::Uid uid) { std::lock_guard lg(guard); sessions.erase(uid); } remote::posix::Stub::Session::Ptr remote::posix::Stub::Session::Registry::resolve_session_for_uid(core::trust::Uid uid) { std::lock_guard lg(guard); return sessions.at(uid); } remote::posix::Stub::Session::Session(boost::asio::io_service& io_service) : socket{io_service} { } remote::posix::Stub::Ptr remote::posix::Stub::create_stub_for_configuration(const Configuration& config) { remote::posix::Stub::Ptr stub { new remote::posix::Stub { config } }; stub->start_accept(); return stub; } // Creates a new instance with the given configuration. // Throws in case of errors. remote::posix::Stub::Stub(remote::posix::Stub::Configuration configuration) : io_service(configuration.io_service), end_point{configuration.endpoint}, acceptor{io_service, end_point}, start_time_resolver{configuration.start_time_resolver}, peer_credentials_resolver{configuration.peer_credentials_resolver}, session_registry{configuration.session_registry} { } void remote::posix::Stub::start_accept() { remote::posix::Stub::Session::Ptr session { new remote::posix::Stub::Session{io_service} }; acceptor.async_accept( session->socket, boost::bind(&remote::posix::Stub::on_new_session, shared_from_this(), boost::asio::placeholders::error(), session)); } remote::posix::Stub::~Stub() { acceptor.cancel(); } core::trust::Request::Answer remote::posix::Stub::send( const core::trust::Agent::RequestParameters& parameters) { // We consider the process start time to prevent from spoofing. auto start_time_before_query = start_time_resolver(parameters.application.pid); // This call will throw if there is no session known for the uid. Session::Ptr session = session_registry->resolve_session_for_uid(parameters.application.uid); remote::posix::Request request { parameters.application.uid, parameters.application.pid, parameters.feature, start_time_before_query }; boost::system::error_code ec; boost::asio::write( session->socket, boost::asio::buffer(&request, sizeof(request)), ec); if (ec) handle_error_from_socket_operation_for_uid(ec, parameters.application.uid); core::trust::Request::Answer answer { core::trust::Request::Answer::denied }; boost::asio::read( session->socket, boost::asio::buffer(&answer, sizeof(answer)), ec); if (ec) handle_error_from_socket_operation_for_uid(ec, parameters.application.uid); // And finally, we check on the process start time. auto start_time_after_query = start_time_resolver(parameters.application.pid); // We consider the process start time to prevent from spoofing. That is, // if the process start times differ here, we would authenticate a different process and // with that potentially a different app. if (start_time_before_query != start_time_after_query) throw std::runtime_error { "Detected a spoofing attempt, process start times before" "and after authentication do not match." }; // We will only ever return if we encountered no errors during communication // with the other side. return answer; } // Called in case of an incoming connection. void remote::posix::Stub::on_new_session( const boost::system::error_code& ec, const remote::posix::Stub::Session::Ptr& session) { if (ec == boost::asio::error::operation_aborted) return; if (ec) { start_accept(); return; } auto pc = peer_credentials_resolver(session->socket.native_handle()); session_registry->add_session_for_uid(std::get<0>(pc), session); start_accept(); } void remote::posix::Stub::handle_error_from_socket_operation_for_uid(const boost::system::error_code& ec, trust::Uid uid) { switch (ec.value()) { // We treat all the following errors as indications for the peer having // gone away. For that, we update the Session::Registry case boost::asio::error::basic_errors::access_denied: case boost::asio::error::basic_errors::broken_pipe: case boost::asio::error::basic_errors::connection_aborted: case boost::asio::error::basic_errors::connection_refused: case boost::asio::error::basic_errors::connection_reset: session_registry->remove_session_for_uid(uid); break; default: break; } // By default, we just rethrow. throw std::system_error{ec.value(), std::system_category()}; } bool remote::posix::Stub::has_session_for_uid(trust::Uid uid) const { return session_registry->has_session_for_uid(uid); } remote::posix::Skeleton::Ptr remote::posix::Skeleton::create_skeleton_for_configuration( const remote::posix::Skeleton::Configuration& configuration) { remote::posix::Skeleton::Ptr skeleton { new remote::posix::Skeleton { configuration } }; skeleton->start_read(); return skeleton; } remote::posix::Skeleton::Skeleton(const Configuration& configuration) : core::trust::remote::Agent::Skeleton{configuration.impl}, start_time_resolver{configuration.start_time_resolver}, app_id_resolver{configuration.app_id_resolver}, description_pattern{configuration.description_format}, verify_process_start_time{configuration.verify_process_start_time}, endpoint{configuration.endpoint}, socket{configuration.io_service} { try { socket.connect(configuration.endpoint); } catch(const boost::exception& e) { throw std::runtime_error { "Could not connect to endpoint: " + endpoint.path() }; } } remote::posix::Skeleton::~Skeleton() { socket.cancel(); } void remote::posix::Skeleton::start_read() { Ptr sp{shared_from_this()}; boost::asio::async_read( socket, boost::asio::buffer(&request, sizeof(request)), [sp](const boost::system::error_code& ec, std::size_t size) { sp->on_read_finished(ec, size); }); } void remote::posix::Skeleton::on_read_finished(const boost::system::error_code& ec, std::size_t size) { if (ec == boost::asio::error::operation_aborted) return; if (ec) { start_read(); return; } if (size != sizeof(request)) return; auto answer = process_incoming_request(request); // We send back our answer, we might throw here and just let the // exception propagate through the stack. boost::asio::write(socket, boost::asio::buffer(&answer, sizeof(answer))); // And restart reading. start_read(); } core::trust::Request::Answer remote::posix::Skeleton::process_incoming_request(const core::trust::remote::posix::Request& request) { if (verify_process_start_time) { // We first validate the process start time again. if (start_time_resolver(request.app_pid) != request.app_start_time) throw std::runtime_error { "Potential spoofing detected on incoming request." }; } auto app_id = app_id_resolver(request.app_pid); // And reach out to the user. // TODO(tvoss): How to handle exceptions here? return authenticate_request_with_parameters(core::trust::Agent::RequestParameters { request.app_uid, request.app_pid, app_id, request.feature, description_pattern }); } trust-store-2.0.0+16.04.20160119/src/core/trust/remote/agent.h0000644000015600001650000000464112647452272024052 0ustar pbuserpbgroup00000000000000/* * 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_REMOTE_AGENT_H_ #define CORE_TRUST_REMOTE_AGENT_H_ #include #include #include #include namespace core { namespace trust { namespace remote { // Abstracts listeners for incoming requests, possible implementations: // * Listening to a socket // * DBus struct Agent { // Models the sending end of a remote agent, meant to be used by trusted helpers. struct CORE_TRUST_DLL_PUBLIC Stub : public core::trust::Agent { Stub() = default; virtual ~Stub() = default; // From core::trust::Agent virtual Request::Answer authenticate_request_with_parameters(const RequestParameters& request); // Sends out the request to the receiving end, either returning an answer // or throwing an exception if no conclusive answer could be obtained from // the user. virtual core::trust::Request::Answer send(const RequestParameters& parameters) = 0; }; // Models the receiving end of a remote agent, meant to be used by the trust store daemon. struct CORE_TRUST_DLL_PUBLIC Skeleton : public core::trust::Agent { // Constructs a new Skeleton instance, installing impl for handling actual requests. Skeleton(const std::shared_ptr& impl); virtual ~Skeleton() = default; // From core::trust::Agent, dispatches to the actual implementation. virtual core::trust::Request::Answer authenticate_request_with_parameters(const RequestParameters& parameters); // The actual agent implementation that we are dispatching to. std::shared_ptr impl; }; }; } } } #endif // CORE_TRUST_REMOTE_AGENT_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/remote/dbus.h0000644000015600001650000000765212647452312023711 0ustar pbuserpbgroup00000000000000/* * 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_REMOTE_DBUS_H_ #define CORE_TRUST_REMOTE_DBUS_H_ #include #include #include #include #include #include #include namespace core { namespace trust { namespace remote { namespace dbus { constexpr const char* default_service_name_prefix { "core.trust.dbus.Agent" }; constexpr const char* default_agent_registry_path { "/core/trust/dbus/AgentRegistry" }; // Abstracts listeners for incoming requests, possible implementations: // * Listening to a socket // * DBus struct CORE_TRUST_DLL_PUBLIC Agent { // Models the sending end of a remote agent, meant to be used by trusted helpers. struct Stub : public core::trust::remote::Agent::Stub { // All creation time parameters go here. struct Configuration { // Object to install an implementation of // core.trust.dbus.AgentRegistry on. core::dbus::Object::Ptr object; // Bus-connection for sending out replies. core::dbus::Bus::Ptr bus; }; // Sets up the stub. Stub(const Configuration& configuration); // Delivers the request described by the given parameters to the other side. core::trust::Request::Answer send(const RequestParameters& parameters) override; // Our actual agent registry implementation. core::trust::LockingAgentRegistry agent_registry; // That we expose over the bus. core::trust::dbus::AgentRegistry::Skeleton agent_registry_skeleton; }; // Models the receiving end of a remote agent, meant to be used by the trust store daemon. struct Skeleton : public core::trust::remote::Agent::Skeleton { // All creation time parameters go here. struct Configuration { // The actual local agent implementation. 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. core::dbus::Bus::Ptr bus; // A helper for querying the application id for a given uid. helpers::AppIdResolver resolve_app_id; }; // Constructs a new Skeleton instance, installing impl for handling actual requests. 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; }; }; } } } } #endif // CORE_TRUST_REMOTE_DBUS_H_ trust-store-2.0.0+16.04.20160119/src/core/trust/preseed_main.cpp0000644000015600001650000000174012647452272024444 0ustar pbuserpbgroup00000000000000/* * 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 int main(int argc, const char** argv) { auto result = core::trust::Preseed::main(core::trust::Preseed::Configuration::parse_from_command_line(argc, argv)); return result == core::posix::exit::Status::success ? EXIT_SUCCESS : EXIT_FAILURE; } trust-store-2.0.0+16.04.20160119/src/core/trust/i18n.cpp0000644000015600001650000000406712647452272022575 0ustar pbuserpbgroup00000000000000/* * 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 namespace { static constexpr const char* this_text_domain { "trust-store" }; std::string& mutable_service_text_domain() { static std::string s{this_text_domain}; return s; } bool init() { // Make sure that *gettext calls work correctly. std::setlocale(LC_ALL, ""); ::bindtextdomain(this_text_domain, nullptr); ::textdomain(this_text_domain); return true; } bool is_initialized() { static const bool initialized = init(); return initialized; } } std::string core::trust::i18n::default_text_domain() { if (not is_initialized()) return std::string{}; return this_text_domain; } // Returns the text domain of the service we are acting for std::string core::trust::i18n::service_text_domain() { return mutable_service_text_domain(); } // Adjusts the text domain of the service; void core::trust::i18n::set_service_text_domain(const std::string& domain) { mutable_service_text_domain() = domain; } std::string core::trust::i18n::tr(const std::string& in) { if (not is_initialized()) return in; return ::gettext(in.c_str()); } std::string core::trust::i18n::tr(const std::string& in, const std::string& domain) { if (not is_initialized()) return in; return ::dgettext(domain.c_str(), in.c_str()); } trust-store-2.0.0+16.04.20160119/src/CMakeLists.txt0000644000015600001650000001451312647452312021731 0ustar pbuserpbgroup00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss find_package(Qt5Core REQUIRED) find_package(Qt5Qml REQUIRED) find_package(Qt5Quick REQUIRED) 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) set(CMAKE_INCLUDE_CURRENT_DIR ON) include_directories( ${DBUS_CPP_INCLUDE_DIRS} ${DBUS_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} ${LIBAPPARMOR_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIRS} ) set( TRUST_STORE_AGENT_SOURCES # Translation helper core/trust/i18n.h core/trust/i18n.cpp # An agent-implementation transforming ensuring legible application ids. 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. core/trust/cached_agent.cpp core/trust/cached_agent_glog_reporter.cpp # Agent implementations for handling request out of process. core/trust/remote/agent.h core/trust/remote/agent.cpp core/trust/remote/helpers.h core/trust/remote/helpers.cpp # An implementation relying on dbus core/trust/remote/dbus.h core/trust/remote/dbus.cpp # An implementation relying on unix sockets, to be used for # inclusion with the android Camera Service. core/trust/remote/posix.h core/trust/remote/posix.cpp ) if (TRUST_STORE_MIR_AGENT_ENABLED) set( TRUST_STORE_AGENT_SOURCES ${TRUST_STORE_AGENT_SOURCES} # An agent-implementation leveraging Mir's trusted prompting support # 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'. add_definitions(-DQT_NO_KEYWORDS) # We need this for building the Qt-based prompt UI set(CMAKE_AUTOMOC ON) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/core/trust/mir/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/core/trust/mir/config.h @ONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/core/trust/mir/prompt_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/core/trust/mir/prompt_config.h @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}/core/trust/mir/) add_executable( trust-prompt # Translation helper core/trust/i18n.h core/trust/i18n.cpp core/trust/mir/prompt_main.cpp ) qt5_use_modules(trust-prompt Core Gui Qml Quick) target_link_libraries( trust-prompt ${Boost_LIBRARIES} ${PROCESS_CPP_LDFLAGS} ) install( TARGETS trust-prompt RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( FILES core/trust/mir/prompt_main.qml DESTINATION ${CMAKE_INSTALL_DATADIR}/core/trust/mir ) else() set( TRUST_STORE_AGENT_SOURCES ${TRUST_STORE_AGENT_SOURCES} core/trust/mir/not_supported.cpp ) endif() add_library( trust-store SHARED core/trust/agent.cpp 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 # The default implementation leverages SQLite3 to persist # requests. core/trust/impl/sqlite3/store.cpp # And pull in all our agent sources. ${TRUST_STORE_AGENT_SOURCES} ) # Just a helper to avoid recompilation of the daemon add_library( trust-stored core/trust/daemon.cpp core/trust/runtime.h core/trust/runtime.cpp ) add_executable( trust-stored-skeleton core/trust/daemon_skeleton_main.cpp ) add_executable( trust-stored-stub core/trust/daemon_stub_main.cpp ) add_library( trust-store-preseed-helper core/trust/preseed.h core/trust/preseed.cpp ) add_executable( trust-store-preseed core/trust/preseed_main.cpp ) target_link_libraries( 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} ${SQLITE3_LIBRARIES} ) target_link_libraries( trust-stored trust-store ${MIR_CLIENT_LDFLAGS} ) target_link_libraries( trust-stored-skeleton trust-stored ) target_link_libraries( trust-stored-stub trust-stored ) target_link_libraries( trust-store-preseed-helper trust-store ) target_link_libraries( trust-store-preseed trust-store-preseed-helper ) # We compile with all symbols visible by default. For the shipping library, we strip # out all symbols that are not in core::trust::* set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map") set_target_properties( trust-store PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}" LINK_DEPENDS ${symbol_map}) set_target_properties( trust-store PROPERTIES VERSION ${TRUST_STORE_VERSION_MAJOR}.${TRUST_STORE_VERSION_MINOR}.${TRUST_STORE_VERSION_PATCH} SOVERSION ${TRUST_STORE_VERSION_MAJOR} ) install( TARGETS trust-store LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( TARGETS trust-stored-skeleton RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install( TARGETS trust-stored-stub RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install( TARGETS trust-store-preseed RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) trust-store-2.0.0+16.04.20160119/po/0000755000015600001650000000000012647452606017022 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/po/pl.po0000644000015600001650000000204112647452272017771 0ustar pbuserpbgroup00000000000000# Polish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Aplikacja %1% próbuje uzyskać dostęp" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Odmów" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Zezwól" trust-store-2.0.0+16.04.20160119/po/bs.po0000644000015600001650000000176412647452272017775 0ustar pbuserpbgroup00000000000000# Bosnian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-17 20:06+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Bosnian \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" #: /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 "Zabrani" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Dozvoli" trust-store-2.0.0+16.04.20160119/po/pa.po0000644000015600001650000000200712647452272017760 0ustar pbuserpbgroup00000000000000# Punjabi translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-16 03:00+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Punjabi \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" #: /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 "ਮਨਜ਼ੂਰ" trust-store-2.0.0+16.04.20160119/po/hy.po0000644000015600001650000000201012647452272017772 0ustar pbuserpbgroup00000000000000# Armenian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-27 13:50+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Armenian \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" #: /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 "Թույլատրել" trust-store-2.0.0+16.04.20160119/po/az.po0000644000015600001650000000200112647452272017764 0ustar pbuserpbgroup00000000000000# Azerbaijani 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-02-01 05:39+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Azerbaijani \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" #: /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 "Rədd et" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "İcazə ver" trust-store-2.0.0+16.04.20160119/po/gl.po0000644000015600001650000000202212647452272017757 0ustar pbuserpbgroup00000000000000# Galician translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-22 22:10+0000\n" "Last-Translator: Marcos Lans \n" "Language-Team: Galician \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-23 06:33+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "O aplicativo %1% tenta acceder" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Rexeitar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitir" trust-store-2.0.0+16.04.20160119/po/nl.po0000644000015600001650000000176112647452272017777 0ustar pbuserpbgroup00000000000000# Dutch translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 13:13+0000\n" "Last-Translator: rob \n" "Language-Team: Dutch \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" #: /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 "Weigeren" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Toestaan" trust-store-2.0.0+16.04.20160119/po/ca.po0000644000015600001650000000205312647452272017744 0ustar pbuserpbgroup00000000000000# Catalan translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "L'aplicació %1% està intentant accedir" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Denega" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permet" trust-store-2.0.0+16.04.20160119/po/ia.po0000644000015600001650000000177612647452272017765 0ustar pbuserpbgroup00000000000000# Interlingua 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-04-28 22:29+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Interlingua \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" #: /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 "Denegar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitter" trust-store-2.0.0+16.04.20160119/po/zh_TW.po0000644000015600001650000000203612647452272020415 0ustar pbuserpbgroup00000000000000# Chinese (Traditional) 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-03-01 10:43+0000\n" "Last-Translator: Cheng-Chia Tseng \n" "Language-Team: Chinese (Traditional) \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" #: /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 "允許" trust-store-2.0.0+16.04.20160119/po/ca@valencia.po0000644000015600001650000000204412647452272021547 0ustar pbuserpbgroup00000000000000# Catalan (Valencian) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-17 14:29+0000\n" "Last-Translator: David Planella \n" "Language-Team: Catalan (Valencian) \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" #: /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 "Denega" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permet" trust-store-2.0.0+16.04.20160119/po/nb.po0000644000015600001650000000204712647452272017763 0ustar pbuserpbgroup00000000000000# Norwegian Bokmal translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-26 11:30+0000\n" "Last-Translator: Åka Sikrom \n" "Language-Team: Norwegian Bokmal \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-27 05:48+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Programmet %1% prøver å få tilgang til" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Nekt" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Tillat" trust-store-2.0.0+16.04.20160119/po/trust-store.pot0000644000015600001650000000157112647452305022061 0ustar pbuserpbgroup00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Canonical Ltd. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: \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=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/daemon.cpp:266 msgid "is trying to access" msgstr "" #: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/mir/prompt_main.qml:78 msgid "Allow" msgstr "" #: /home/tvoss/ubuntu/scratch/fix-1532870/src/core/trust/mir/prompt_main.qml:83 msgid "Don’t Allow" msgstr "" trust-store-2.0.0+16.04.20160119/po/et.po0000644000015600001650000000175012647452272017774 0ustar pbuserpbgroup00000000000000# Estonian 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-02-28 13:10+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Estonian \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/cs.po0000644000015600001650000000176712647452272020001 0ustar pbuserpbgroup00000000000000# Czech 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-02-11 00:07+0000\n" "Last-Translator: Texis \n" "Language-Team: Czech \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" #: /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 "Zakázat" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Povolit" trust-store-2.0.0+16.04.20160119/po/ny.po0000644000015600001650000000202012647452272020001 0ustar pbuserpbgroup00000000000000# Chewa; Chichewa; Nyanja 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-03-09 11:36+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Chewa; Chichewa; Nyanja \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" #: /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 "Kana" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Vomela" trust-store-2.0.0+16.04.20160119/po/fa.po0000644000015600001650000000210012647452272017740 0ustar pbuserpbgroup00000000000000# Persian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-22 11:16+0000\n" "Last-Translator: Danial Behzadi \n" "Language-Team: Persian \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-23 06:33+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "کارهٔ %1% در حال تلاش برای دسترسی است" #: /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 "اجازه" trust-store-2.0.0+16.04.20160119/po/pt.po0000644000015600001650000000204012647452272020000 0ustar pbuserpbgroup00000000000000# Portuguese translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-22 12:15+0000\n" "Last-Translator: Ivo Xavier \n" "Language-Team: Portuguese \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-23 06:33+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "%1% está a tentar aceder" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Recusar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitir" trust-store-2.0.0+16.04.20160119/po/en_GB.po0000644000015600001650000000206512647452272020336 0ustar pbuserpbgroup00000000000000# English (United Kingdom) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 08:58+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom) \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" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Application %1% is trying to access" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Deny" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Allow" trust-store-2.0.0+16.04.20160119/po/sq.po0000644000015600001650000000176012647452272020010 0ustar pbuserpbgroup00000000000000# Albanian 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-03-02 20:14+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Albanian \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" #: /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 "Moho" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Lejo" trust-store-2.0.0+16.04.20160119/po/pt_BR.po0000644000015600001650000000202012647452272020361 0ustar pbuserpbgroup00000000000000# Brazilian Portuguese translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-13 14:43+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Brazilian Portuguese \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" #: /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 "Negar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitir" trust-store-2.0.0+16.04.20160119/po/ta.po0000644000015600001650000000177512647452272017777 0ustar pbuserpbgroup00000000000000# Tamil translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-14 07:00+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Tamil \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" #: /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 "அனுமதி" trust-store-2.0.0+16.04.20160119/po/sk.po0000644000015600001650000000174412647452272020004 0ustar pbuserpbgroup00000000000000# Slovak 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-02-19 19:57+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Slovak \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/oc.po0000644000015600001650000000201612647452272017761 0ustar pbuserpbgroup00000000000000# Occitan (post 1500) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-11-11 12:14+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Occitan (post 1500) \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" #: /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 "Refusar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Autorizar" trust-store-2.0.0+16.04.20160119/po/ku.po0000644000015600001650000000177212647452272020007 0ustar pbuserpbgroup00000000000000# Kurdish 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-06-28 21:20+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Kurdish \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" #: /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 "Red bike" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Destûr bide" trust-store-2.0.0+16.04.20160119/po/mk.po0000644000015600001650000000175412647452272017777 0ustar pbuserpbgroup00000000000000# Macedonian 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-02-14 19:53+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Macedonian \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/sv.po0000644000015600001650000000203012647452272020004 0ustar pbuserpbgroup00000000000000# Swedish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-25 05:41+0000\n" "Last-Translator: Josef Andersson \n" "Language-Team: Swedish \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-26 06:14+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Programmet %1% försöker att komma åt" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Neka" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Tillåt" trust-store-2.0.0+16.04.20160119/po/lv.po0000644000015600001650000000176212647452272020010 0ustar pbuserpbgroup00000000000000# Latvian 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-05-05 08:29+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Latvian \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" #: /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 "Liegt" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Atļaut" trust-store-2.0.0+16.04.20160119/po/id.po0000644000015600001650000000177012647452272017762 0ustar pbuserpbgroup00000000000000# Indonesian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-29 04:05+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Indonesian \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" #: /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 "Tolak" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Izinkan" trust-store-2.0.0+16.04.20160119/po/mr.po0000644000015600001650000000204112647452272017774 0ustar pbuserpbgroup00000000000000# Marathi 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-04-04 03:54+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Marathi \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" #: /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 "परवानगी द्या" trust-store-2.0.0+16.04.20160119/po/ar.po0000644000015600001650000000174412647452272017771 0ustar pbuserpbgroup00000000000000# Arabic translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-11-02 21:00+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Arabic \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/th.po0000644000015600001650000000174012647452272017776 0ustar pbuserpbgroup00000000000000# Thai translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-23 07:48+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Thai \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/kn.po0000644000015600001650000000203112647452272017765 0ustar pbuserpbgroup00000000000000# Kannada translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-12-20 06:26+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Kannada \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" #: /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 "ಅನುಮತಿಸು" trust-store-2.0.0+16.04.20160119/po/uz.po0000644000015600001650000000177012647452272020024 0ustar pbuserpbgroup00000000000000# Uzbek 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-04-01 01:15+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Uzbek \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" #: /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 "Rad etish" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Ruxsat berish" trust-store-2.0.0+16.04.20160119/po/ko.po0000644000015600001650000000176012647452272017776 0ustar pbuserpbgroup00000000000000# Korean translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-11 14:34+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Korean \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" #: /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 "허용" trust-store-2.0.0+16.04.20160119/po/hu.po0000644000015600001650000000210412647452272017772 0ustar pbuserpbgroup00000000000000# Hungarian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-08-23 15:51+0000\n" "Last-Translator: Richard Somlói \n" "Language-Team: Hungarian \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-24 05:21+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "A(z) %1% alkalmazás hozzá szeretne férni ehhez:" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Elutasítás" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Engedélyezés" trust-store-2.0.0+16.04.20160119/po/br.po0000644000015600001650000000204412647452272017764 0ustar pbuserpbgroup00000000000000# Breton 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-08-25 13:29+0000\n" "Last-Translator: Fohanno Thierry \n" "Language-Team: Breton \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-26 06:14+0000\n" "X-Generator: Launchpad (build 17690)\n" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Emañ an arload %1% o klask mont" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Nac'h" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Aotren" trust-store-2.0.0+16.04.20160119/po/ne.po0000644000015600001650000000174412647452272017771 0ustar pbuserpbgroup00000000000000# 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 "" trust-store-2.0.0+16.04.20160119/po/my.po0000644000015600001650000000202612647452272020006 0ustar pbuserpbgroup00000000000000# Burmese 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-07-25 07:12+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Burmese \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" #: /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 "ခွင့်ပြု" trust-store-2.0.0+16.04.20160119/po/sl.po0000644000015600001650000000176612647452272020011 0ustar pbuserpbgroup00000000000000# Slovenian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 08:13+0000\n" "Last-Translator: Damir Jerovšek \n" "Language-Team: Slovenian \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" #: /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 "Zavrni" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Dovoli" trust-store-2.0.0+16.04.20160119/po/cy.po0000644000015600001650000000174212647452272020000 0ustar pbuserpbgroup00000000000000# Welsh 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-08-17 06:05+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Welsh \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/ga.po0000644000015600001650000000176412647452272017760 0ustar pbuserpbgroup00000000000000# Irish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-12-15 18:55+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Irish \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" #: /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 "Diúltaigh" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Ceadaigh" trust-store-2.0.0+16.04.20160119/po/it.po0000644000015600001650000000206712647452272020002 0ustar pbuserpbgroup00000000000000# Italian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "L'applicazione %1% sta tentando di accedere" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Non consentire" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Consenti" trust-store-2.0.0+16.04.20160119/po/gd.po0000644000015600001650000000207212647452272017754 0ustar pbuserpbgroup00000000000000# Gaelic; Scottish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Tha aplacaid %1% a' feuchainn ri inntrigeadh fhaighinn dha" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Diùlt" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Ceadaich" trust-store-2.0.0+16.04.20160119/po/bg.po0000644000015600001650000000175212647452272017756 0ustar pbuserpbgroup00000000000000# Bulgarian 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-02-23 09:27+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Bulgarian \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/km.po0000644000015600001650000000201412647452272017765 0ustar pbuserpbgroup00000000000000# Khmer translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-13 06:57+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Khmer \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" #: /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 "អនុញ្ញាត" trust-store-2.0.0+16.04.20160119/po/el.po0000644000015600001650000000217412647452272017765 0ustar pbuserpbgroup00000000000000# Greek translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Η εφαμογή %1% προσπαθεί να αποκτήσει πρόσβαση" #: /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 "Να επιτρέπεται" trust-store-2.0.0+16.04.20160119/po/sr.po0000644000015600001650000000207712647452272020013 0ustar pbuserpbgroup00000000000000# Serbian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Програм %1% покушава да приступи" #: /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 "Допусти" trust-store-2.0.0+16.04.20160119/po/ms.po0000644000015600001650000000175212647452272020005 0ustar pbuserpbgroup00000000000000# Malay translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-11 09:43+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Malay \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" #: /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 "Nafi" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Izin" trust-store-2.0.0+16.04.20160119/po/da.po0000644000015600001650000000175712647452272017757 0ustar pbuserpbgroup00000000000000# Danish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-11 11:17+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Danish \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" #: /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 "Nægt" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Tillad" trust-store-2.0.0+16.04.20160119/po/eu.po0000644000015600001650000000176612647452272020004 0ustar pbuserpbgroup00000000000000# Basque translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 23:36+0000\n" "Last-Translator: Ibai Oihanguren Sala \n" "Language-Team: Basque \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" #: /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 "Ukatu" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Baimendu" trust-store-2.0.0+16.04.20160119/po/tr.po0000644000015600001650000000177212647452272020015 0ustar pbuserpbgroup00000000000000# Turkish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 19:58+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Turkish \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" #: /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 "İzin Verme" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "İzin ver" trust-store-2.0.0+16.04.20160119/po/hr.po0000644000015600001650000000176412647452272020002 0ustar pbuserpbgroup00000000000000# Croatian 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-01-28 14:20+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Croatian \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" #: /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 "Odbij" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Dopusti" trust-store-2.0.0+16.04.20160119/po/is.po0000644000015600001650000000177412647452272020005 0ustar pbuserpbgroup00000000000000# Icelandic translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-14 02:57+0000\n" "Last-Translator: Sveinn í Felli \n" "Language-Team: Icelandic \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" #: /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 "Hafna" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Leyfa" trust-store-2.0.0+16.04.20160119/po/en_AU.po0000644000015600001650000000207112647452272020350 0ustar pbuserpbgroup00000000000000# English (Australia) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Application %1% is trying to access" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Deny" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Allow" trust-store-2.0.0+16.04.20160119/po/eo.po0000644000015600001650000000175212647452272017771 0ustar pbuserpbgroup00000000000000# Esperanto 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-02-15 19:55+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Esperanto \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/lb.po0000644000015600001650000000200112647452272017747 0ustar pbuserpbgroup00000000000000# Luxembourgish 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-05-31 16:05+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Luxembourgish \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" #: /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 "Ofleenen" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Erlaben" trust-store-2.0.0+16.04.20160119/po/uk.po0000644000015600001650000000214112647452272017776 0ustar pbuserpbgroup00000000000000# Ukrainian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 11:07+0000\n" "Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \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" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Програма %1% намагається отримати доступ" #: /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 "Дозволити" trust-store-2.0.0+16.04.20160119/po/tg.po0000644000015600001650000000174212647452272017777 0ustar pbuserpbgroup00000000000000# Tajik 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-03-10 04:55+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Tajik \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/fi.po0000644000015600001650000000176012647452272017763 0ustar pbuserpbgroup00000000000000# Finnish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 16:31+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Finnish \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" #: /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 "Estä" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Salli" trust-store-2.0.0+16.04.20160119/po/ru.po0000644000015600001650000000201212647452272020002 0ustar pbuserpbgroup00000000000000# Russian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-11 10:48+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Russian \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" #: /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 "Разрешить" trust-store-2.0.0+16.04.20160119/po/ro.po0000644000015600001650000000206512647452272020004 0ustar pbuserpbgroup00000000000000# Romanian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "Aplicaţia %1% încearcă să acceseze" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Refuzați" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permiteți" trust-store-2.0.0+16.04.20160119/po/fr_CA.po0000644000015600001650000000201112647452272020325 0ustar pbuserpbgroup00000000000000# French (Canada) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-15 14:57+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: French (Canada) \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" #: /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 "Refuser" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permettre" trust-store-2.0.0+16.04.20160119/po/he.po0000644000015600001650000000176612647452272017767 0ustar pbuserpbgroup00000000000000# Hebrew translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-17 06:34+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Hebrew \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" #: /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 "קבלה" trust-store-2.0.0+16.04.20160119/po/am.po0000644000015600001650000000206612647452272017762 0ustar pbuserpbgroup00000000000000# Amharic translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-11 00:43+0000\n" "Last-Translator: samson \n" "Language-Team: Amharic \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" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "መተግበሪያ %1% ለ መድረስ እየሞከረ ነው" #: /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 "መፍቀጃ" trust-store-2.0.0+16.04.20160119/po/es.po0000644000015600001650000000204212647452272017766 0ustar pbuserpbgroup00000000000000# Spanish translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "La aplicación %1% está intentando acceder a" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Denegar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitir" trust-store-2.0.0+16.04.20160119/po/ug.po0000644000015600001650000000177712647452272020010 0ustar pbuserpbgroup00000000000000# Uyghur translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-14 02:21+0000\n" "Last-Translator: Gheyret T.Kenji \n" "Language-Team: Uyghur \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" #: /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 "ئىجازەت" trust-store-2.0.0+16.04.20160119/po/CMakeLists.txt0000644000015600001650000000214012647452272021556 0ustar pbuserpbgroup00000000000000include(FindGettext REQUIRED) find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) set(DOMAIN trust-store) set(POT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${DOMAIN}.pot) file(GLOB PO_FILES *.po) # We look through all source files and find # usages of i18n::tr. file( GLOB_RECURSE I18N_CPP_SRC_FILES ${CMAKE_SOURCE_DIR}/src/*.cpp ${CMAKE_SOURCE_DIR}/src/*.qml) list(SORT I18N_CPP_SRC_FILES) add_custom_target( trust-store-pot COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --default-domain=trust-store --output=${POT_FILE} --from-code=UTF-8 --c++ --add-comments=TRANSLATORS --keyword='tr' --boost --package-name=trust-store --copyright-holder='Canonical Ltd.' ${I18N_CPP_SRC_FILES}) foreach(PO_FILE ${PO_FILES}) get_filename_component(LANG ${PO_FILE} NAME_WE) gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE}) set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/${LANG}/LC_MESSAGES) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo DESTINATION ${INSTALL_DIR} RENAME ${DOMAIN}.mo) endforeach(PO_FILE) trust-store-2.0.0+16.04.20160119/po/fr.po0000644000015600001650000000203412647452272017767 0ustar pbuserpbgroup00000000000000# French translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 19:43+0000\n" "Last-Translator: Anne \n" "Language-Team: French \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" #: /tmp/trust-store-i18n/src/core/trust/daemon.cpp:265 #, boost-format msgid "Application %1% is trying to access" msgstr "Application %1% essaie d'accéder à" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Refuser" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Autoriser" trust-store-2.0.0+16.04.20160119/po/af.po0000644000015600001650000000176712647452272017762 0ustar pbuserpbgroup00000000000000# Afrikaans 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-02-25 20:41+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Afrikaans \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" #: /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 "Weier" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Laat toe" trust-store-2.0.0+16.04.20160119/po/vi.po0000644000015600001650000000175412647452272020006 0ustar pbuserpbgroup00000000000000# Vietnamese 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-04-02 18:44+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Vietnamese \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" #: /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 "" trust-store-2.0.0+16.04.20160119/po/ja.po0000644000015600001650000000177612647452272017766 0ustar pbuserpbgroup00000000000000# Japanese translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-10 13:44+0000\n" "Last-Translator: Shushi Kurose \n" "Language-Team: Japanese \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" #: /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 "許可" trust-store-2.0.0+16.04.20160119/po/zh_HK.po0000644000015600001650000000201512647452272020362 0ustar pbuserpbgroup00000000000000# Chinese (Hong Kong) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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: 2014-10-26 11:31+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Chinese (Hong Kong) \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" #: /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 "允許" trust-store-2.0.0+16.04.20160119/po/de.po0000644000015600001650000000165312647452272017756 0ustar pbuserpbgroup00000000000000# Copyright (C) 2014 Canonical Ltd. # This file is distributed under the same license as the PACKAGE package. # msgid "" msgstr "" "Project-Id-Version: trust-store\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-08-20 13:41-0400\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-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 "Anwendung »%1%« versucht, zuzugreifen auf" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Verbieten" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Erlauben" trust-store-2.0.0+16.04.20160119/po/be.po0000644000015600001650000000201612647452272017746 0ustar pbuserpbgroup00000000000000# Belarusian 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-01-28 05:53+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Belarusian \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" #: /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 "Дазволіць" trust-store-2.0.0+16.04.20160119/po/zh_CN.po0000644000015600001650000000202712647452272020363 0ustar pbuserpbgroup00000000000000# Chinese (Simplified) translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-01-13 14:28+0000\n" "Last-Translator: TianxiangWang \n" "Language-Team: Chinese (Simplified) \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" #: /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 "允许" trust-store-2.0.0+16.04.20160119/po/aa.po0000644000015600001650000000175112647452272017746 0ustar pbuserpbgroup00000000000000# Afar 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-04-05 19:43+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Afar \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" #: /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 "Cina" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Oggol" trust-store-2.0.0+16.04.20160119/po/ast.po0000644000015600001650000000205212647452272020147 0ustar pbuserpbgroup00000000000000# Asturian translation for trust-store # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the trust-store package. # FIRST AUTHOR , 2014. # 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-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-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 "La aplicación %1% ta intentando l'accesu" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:42 msgid "Deny" msgstr "Refugar" #: /tmp/trust-store-i18n/src/core/trust/mir/prompt_main.qml:49 msgid "Allow" msgstr "Permitir" trust-store-2.0.0+16.04.20160119/COPYING0000644000015600001650000001674312647452272017451 0ustar pbuserpbgroup00000000000000 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. trust-store-2.0.0+16.04.20160119/data/0000755000015600001650000000000012647452606017315 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/data/trust-store.pc.in0000644000015600001650000000060012647452272022554 0ustar pbuserpbgroup00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${exec_prefix}/include Name: @CMAKE_PROJECT_NAME@ Description: Provides a common implementation of a trust store to be used by trusted helpers. Version: @TRUST_STORE_VERSION_MAJOR@.@TRUST_STORE_VERSION_MINOR@.@TRUST_STORE_VERSION_PATCH@ Libs: -L${libdir} -ltrust-store Cflags: -I${includedir} trust-store-2.0.0+16.04.20160119/data/CMakeLists.txt0000644000015600001650000000150312647452272022053 0ustar pbuserpbgroup00000000000000# Copyright © 2013 Canonical Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authored by: Thomas Voss configure_file( trust-store.pc.in trust-store.pc @ONLY ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/trust-store.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) trust-store-2.0.0+16.04.20160119/3rd_party/0000755000015600001650000000000012647452606020313 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/3rd_party/xdg/0000755000015600001650000000000012647452606021075 5ustar pbuserpbgroup00000000000000trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg_test.cpp0000644000015600001650000001133112647452305023415 0ustar pbuserpbgroup00000000000000// 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); } trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.h0000644000015600001650000001006012647452305022021 0ustar pbuserpbgroup00000000000000// 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_ trust-store-2.0.0+16.04.20160119/3rd_party/xdg/LICENSE0000644000015600001650000001674412647452305022112 0ustar pbuserpbgroup00000000000000 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. trust-store-2.0.0+16.04.20160119/3rd_party/xdg/README.md0000644000015600001650000000410212647452305022345 0ustar pbuserpbgroup00000000000000# 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(); } ``` trust-store-2.0.0+16.04.20160119/3rd_party/xdg/xdg.cpp0000644000015600001650000001165312647452305022365 0ustar pbuserpbgroup00000000000000// 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(); } trust-store-2.0.0+16.04.20160119/3rd_party/xdg/CMakeLists.txt0000644000015600001650000000105312647452305023630 0ustar pbuserpbgroup00000000000000project(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) trust-store-2.0.0+16.04.20160119/symbols.map0000644000015600001650000000040212647452272020566 0ustar pbuserpbgroup00000000000000{ global: extern "C++" { core::trust::*; typeinfo?for?core::trust::*; typeinfo?name?for?core::trust::*; VTT?for?core::trust::*; virtual?thunk?to?core::trust::*; vtable?for?core::trust::*; }; local: extern "C++" { *; }; };trust-store-2.0.0+16.04.20160119/CMakeLists.txt0000644000015600001650000000641312647452305021144 0ustar pbuserpbgroup00000000000000cmake_minimum_required(VERSION 2.8) 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) include(cmake/PrePush.cmake) include(GNUInstallDirs) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -pedantic -Wextra -fPIC -fvisibility=hidden -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra -fPIC -pthread") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") ##################################################################### # Enable code coverage calculation with gcov/gcovr/lcov # Usage: # * Switch build type to coverage (use ccmake or cmake-gui) # * Invoke make, make test, make coverage # * Find html report in subdir coveragereport # * Find xml report feasible for jenkins in coverage.xml ##################################################################### IF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE]) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" ) SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" ) ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE]) find_package(PkgConfig) find_package(Boost COMPONENTS filesystem program_options system REQUIRED) add_subdirectory(3rd_party/xdg) option( TRUST_STORE_MIR_AGENT_ENABLED "Enables a local agent implementation relying on Mir's trusted prompting" ON) if (TRUST_STORE_MIR_AGENT_ENABLED) pkg_check_modules(MIR_CLIENT mirclient REQUIRED) include_directories( ${MIR_CLIENT_INCLUDE_DIRS} ) endif() pkg_check_modules(GLOG libglog REQUIRED) pkg_check_modules(PROCESS_CPP process-cpp REQUIRED) include(CTest) include_directories( include/ 3rd_party/xdg ${GFLAGS_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ) add_subdirectory(doc) add_subdirectory(data) add_subdirectory(include) add_subdirectory(po) add_subdirectory(src) add_subdirectory(tests) enable_coverage_report(trust_store_test)