From 1a2fb481d36e439ef419ecc270238542cae80cfd Mon Sep 17 00:00:00 2001 From: basebuilder_pel7ppc64bebuilder0 Date: Tue, 29 May 2018 17:08:54 +0200 Subject: [PATCH] usbguard initial package creation Signed-off-by: basebuilder_pel7ppc64bebuilder0 --- .../usbguard-0.7.0-covscan-uninit-ctor.patch | 26 + SOURCES/usbguard-0.7.0-daemonization.patch | 472 + ...-fixed-usbguard-daemon-conf-man-page.patch | 88 + ...0.7.0-fixed-usbguard-daemon-man-page.patch | 59 + SOURCES/usbguard-0.7.0-kernel-4.13-fix.patch | 68 + SOURCES/usbguard-0.7.0-libaudit-version.patch | 12 + ...bguard-0.7.0-linux-audit-integration.patch | 1197 ++ ....7.0-make-full-testsuite-conditional.patch | 99 + ...d-0.7.0-strict-configuration-parsing.patch | 59 + SOURCES/usbguard-0.7.0-upstream-compat.patch | 16939 ++++++++++++++++ SOURCES/usbguard-daemon.conf | 173 + SPECS/usbguard.spec | 301 + 12 files changed, 19493 insertions(+) create mode 100644 SOURCES/usbguard-0.7.0-covscan-uninit-ctor.patch create mode 100644 SOURCES/usbguard-0.7.0-daemonization.patch create mode 100644 SOURCES/usbguard-0.7.0-fixed-usbguard-daemon-conf-man-page.patch create mode 100644 SOURCES/usbguard-0.7.0-fixed-usbguard-daemon-man-page.patch create mode 100644 SOURCES/usbguard-0.7.0-kernel-4.13-fix.patch create mode 100644 SOURCES/usbguard-0.7.0-libaudit-version.patch create mode 100644 SOURCES/usbguard-0.7.0-linux-audit-integration.patch create mode 100644 SOURCES/usbguard-0.7.0-make-full-testsuite-conditional.patch create mode 100644 SOURCES/usbguard-0.7.0-strict-configuration-parsing.patch create mode 100644 SOURCES/usbguard-0.7.0-upstream-compat.patch create mode 100644 SOURCES/usbguard-daemon.conf create mode 100644 SPECS/usbguard.spec diff --git a/SOURCES/usbguard-0.7.0-covscan-uninit-ctor.patch b/SOURCES/usbguard-0.7.0-covscan-uninit-ctor.patch new file mode 100644 index 00000000..e8bd27c5 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-covscan-uninit-ctor.patch @@ -0,0 +1,26 @@ +diff --git a/src/Library/DeviceManagerPrivate.cpp b/src/Library/DeviceManagerPrivate.cpp +index d9f3395..579b3c7 100644 +--- a/src/Library/DeviceManagerPrivate.cpp ++++ b/src/Library/DeviceManagerPrivate.cpp +@@ -41,6 +41,7 @@ namespace usbguard { + std::unique_lock local_device_map_lock(_device_map_mutex); + std::unique_lock remote_device_map_lock(rhs._device_map_mutex); + _device_map = rhs._device_map; ++ _restore_controller_device_state = rhs._restore_controller_device_state; + return *this; + } + +diff --git a/src/Library/Exception.hpp b/src/Library/Exception.hpp +index 02e9622..f27dd63 100644 +--- a/src/Library/Exception.hpp ++++ b/src/Library/Exception.hpp +@@ -128,7 +128,8 @@ namespace usbguard + { + public: + IPCException() +- : Exception("", "", "") ++ : Exception("", "", ""), ++ _message_id(0) + { + } + diff --git a/SOURCES/usbguard-0.7.0-daemonization.patch b/SOURCES/usbguard-0.7.0-daemonization.patch new file mode 100644 index 00000000..1e97166f --- /dev/null +++ b/SOURCES/usbguard-0.7.0-daemonization.patch @@ -0,0 +1,472 @@ +diff --git a/Makefile.am b/Makefile.am +index 1852983..b7aa1a3 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -15,6 +15,7 @@ + ## along with this program. If not, see . + ## + ## Authors: Daniel Kopecek ++## Jiri Vymazal + ## + SUBDIRS=src/Tests/ + +diff --git a/doc/usbguard-daemon.8 b/doc/usbguard-daemon.8 +index 18c72fe..dfdb285 100644 +--- a/doc/usbguard-daemon.8 ++++ b/doc/usbguard-daemon.8 +@@ -1,4 +1,4 @@ +-.\" Automatically generated by Pandoc 1.17.0.3 ++.\" Automatically generated by Pandoc 1.19.1 + .\" + .TH "USBGUARD\-DAEMON" "8" "June 2016" "" "" + .hy +@@ -25,6 +25,11 @@ Enable debugging messages in the log. + .RS + .RE + .TP ++.B \f[B]\-f\f[] ++Enable classical daemon behavior (fork at start, sysV compliant). ++.RS ++.RE ++.TP + .B \f[B]\-s\f[] + Log to syslog. + .RS +@@ -41,7 +46,8 @@ Log to a file at \f[I]path\f[]. + .RE + .TP + .B \f[B]\-p\f[] <\f[I]path\f[]> +-Write PID to a file at \f[I]path\f[]. ++Write PID to a file at \f[I]path\f[] (default: ++\f[I]/var/run/usbguard.pid\f[]). + .RS + .RE + .TP +diff --git a/doc/usbguard-daemon.8.md b/doc/usbguard-daemon.8.md +index 3e2fcaf..581613d 100644 +--- a/doc/usbguard-daemon.8.md ++++ b/doc/usbguard-daemon.8.md +@@ -19,6 +19,9 @@ The **usbguard-daemon** is the main component of the USBGuard software framework + **-d** + : Enable debugging messages in the log. + ++**-f** ++: Enable classical daemon behavior (fork at start, sysV compliant). ++ + **-s** + : Log to syslog. + +@@ -29,7 +32,7 @@ The **usbguard-daemon** is the main component of the USBGuard software framework + : Log to a file at *path*. + + **-p** <*path*> +-: Write PID to a file at *path*. ++: Write PID to a file at *path* (default: */var/run/usbguard.pid*). + + **-c** <*path*> + : Load configuration from a file at *path* (default: */etc/usbguard/usbguard-daemon.conf*). +diff --git a/src/Common/Utility.cpp b/src/Common/Utility.cpp +index f84d2a8..237acfb 100644 +--- a/src/Common/Utility.cpp ++++ b/src/Common/Utility.cpp +@@ -42,56 +42,6 @@ + namespace usbguard + { + +- void daemonize() +- { +- const ::pid_t pid = fork(); +- +- switch(pid) { +- case 0: /* child */ +- break; +- case -1: /* error */ +- ::exit(EXIT_FAILURE); +- default: /* parent */ +- ::exit(EXIT_SUCCESS); +- } +- // +- // Decouple from parent environment +- // - chdir to / +- // - create new process session +- // - reset umask +- // - cleanup file descriptors +- // - ??? +- // - consider using libdaemon +- // +- if (::chdir("/") != 0) { +- ::exit(EXIT_FAILURE); +- } +- const ::pid_t sid = ::setsid(); +- if (sid != 0) { +- ::exit(EXIT_FAILURE); +- } +- ::umask(::umask(077)|022); +- struct rlimit rlim; +- if (::getrlimit(RLIMIT_NOFILE, &rlim) != 0) { +- ::exit(EXIT_FAILURE); +- } +- const int maxfd = (rlim.rlim_max == RLIM_INFINITY ? 1024 : rlim.rlim_max); +- for (int fd = 0; fd < maxfd; ++fd) { +- ::close(fd); +- } +- return; +- } +- +- bool writePID(const std::string& filepath) +- { +- std::ofstream pidstream(filepath, std::ios_base::trunc); +- if (!pidstream) { +- return false; +- } +- pidstream << numberToString(getpid()) << std::endl; +- return true; +- } +- + static void runCommandExecChild(const std::string& path, const std::vector& args) + { + struct rlimit rlim; +diff --git a/src/Common/Utility.hpp b/src/Common/Utility.hpp +index f722b22..54e1ea1 100644 +--- a/src/Common/Utility.hpp ++++ b/src/Common/Utility.hpp +@@ -41,25 +41,6 @@ + namespace usbguard + { + /** +- * Create a background process. +- * +- * Performs the following actions: +- * 1) fork a new process (parent process exists with 0) +- * 2) chdir to / +- * 3) creates a new process session +- * 4) resets umask +- * 5) closes all file descriptors +- * 6) Reinitialize logging for the child +- */ +- void daemonize(void); +- +- /** +- * Writes the current PID to a file at filepath. +- * Returns true on success, otherwise returns false. +- */ +- bool writePID(const std::string& filepath); +- +- /** + * Wrappers for the __builtin_expect function. + */ + #if defined(__GNUC__) +diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp +index b317c85..2a9a37c 100644 +--- a/src/Daemon/Daemon.cpp ++++ b/src/Daemon/Daemon.cpp +@@ -15,6 +15,7 @@ + // along with this program. If not, see . + // + // Authors: Daniel Kopecek ++// Jiri Vymazal + // + #ifdef HAVE_BUILD_CONFIG_H + #include +@@ -27,6 +28,8 @@ + #include "usbguard/RuleParser.hpp" + #include "usbguard/Audit.hpp" + ++#include ++ + #include + #include + #include +@@ -112,6 +115,8 @@ namespace usbguard + + _device_rules_with_port = false; + _restore_controller_device_state = false; ++ ++ pid_fd = -1; + } + + Daemon::~Daemon() +@@ -402,6 +407,10 @@ namespace usbguard + } + } while(!exit_loop); + ++ if (pid_fd != -1) { ++ lockf(pid_fd, F_ULOCK, 0); ++ close(pid_fd); ++ } + IPCServer::stop(); + _dm->stop(); + USBGUARD_LOG(Trace) << "Leaving main loop."; +@@ -411,6 +420,73 @@ namespace usbguard + { + } + ++ void Daemon::daemonize(const std::string &pid_file) ++ { ++ USBGUARD_LOG(Trace) << "Starting daemonization"; ++ ++ pid_t pid = 0; ++ pid_t original_pid = getpid(); ++ ++ sigset_t mask; ++ sigemptyset(&mask); ++ sigaddset(&mask, SIGUSR1); ++ sigprocmask(SIG_BLOCK, &mask, nullptr); ++ USBGUARD_SYSCALL_THROW("Daemonize", (pid = fork()) < 0); ++ if (pid > 0) { ++ constexpr int timeout_val = 5; ++ struct timespec timeout {timeout_val,0}; ++ const time_t start = time(nullptr); ++ siginfo_t info; ++ do { ++ const int signum = sigtimedwait(&mask, &info, &timeout); ++ if (signum == SIGUSR1 && info.si_signo == SIGUSR1 && info.si_pid == pid) { ++ USBGUARD_LOG(Trace) << "Finished daemonization"; ++ exit(EXIT_SUCCESS); ++ } ++ if (signum == -1 && errno == EAGAIN) { ++ break; /* timed out */ ++ } ++ timeout.tv_sec = timeout_val - difftime(time(nullptr), start); /* avoid potentially endless loop */ ++ } while(true); ++ throw Exception("Deamonize", "signal", "Waiting on pid file write timeout!"); ++ } ++ ++ /* Now we are forked */ ++ USBGUARD_SYSCALL_THROW("Daemonize", setsid() < 0); ++ signal(SIGCHLD, SIG_IGN); ++ ++ USBGUARD_SYSCALL_THROW("Daemonize", (pid_fd = open(pid_file.c_str(), O_RDWR|O_CREAT, 0640)) < 0); ++ USBGUARD_SYSCALL_THROW("Daemonize", (lockf(pid_fd, F_TLOCK, 0)) < 0); ++ USBGUARD_SYSCALL_THROW("Daemonize", (pid = fork()) < 0); ++ if (pid > 0) { ++ try { ++ std::string pid_str = std::to_string(pid); ++ USBGUARD_SYSCALL_THROW("Daemonize", write(pid_fd, pid_str.c_str(), pid_str.size()) != static_cast(pid_str.size())); ++ kill(original_pid, SIGUSR1); ++ exit(EXIT_SUCCESS); ++ } ++ catch(...) { ++ kill(pid, SIGKILL); ++ throw; ++ } ++ } ++ ++ /* Now we are forked 2nd time */ ++ umask(0047); /* no need for world-accessible or executable files */ ++ chdir("/"); ++ const std::array std_fds {{STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}}; ++ int fd_null; ++ USBGUARD_SYSCALL_THROW("Daemonize", (fd_null = open("/dev/null", O_RDWR)) < 0); ++ /* We do not need to close all fds because there is only logging open at this point */ ++ for (auto fd : std_fds) { ++ USBGUARD_SYSCALL_THROW("Daemonize", close(fd)); ++ USBGUARD_SYSCALL_THROW("Daemonize", (dup2(fd_null, fd)) < 0); ++ } ++ close(fd_null); ++ ++ USBGUARD_SYSCALL_THROW("Daemonize", (lockf(pid_fd, F_LOCK, 0)) < 0); ++ } ++ + uint32_t Daemon::assignID() + { + return _ruleset.assignID(); +diff --git a/src/Daemon/Daemon.hpp b/src/Daemon/Daemon.hpp +index cfd02d9..065deaf 100644 +--- a/src/Daemon/Daemon.hpp ++++ b/src/Daemon/Daemon.hpp +@@ -15,6 +15,7 @@ + // along with this program. If not, see . + // + // Authors: Daniel Kopecek ++// Jiri Vymazal + // + #pragma once + #ifdef HAVE_BUILD_CONFIG_H +@@ -72,6 +73,8 @@ namespace usbguard + void run(); + /* Stop the daemon */ + void quit(); ++ /* Handle process daemonization */ ++ void daemonize(const std::string& pid_file); + + uint32_t assignID(); + uint32_t upsertRule(const std::string& match_spec, const std::string& rule_spec, bool parent_insensitive = false); +@@ -112,6 +115,8 @@ namespace usbguard + ConfigFile _config; + RuleSet _ruleset; + ++ int pid_fd; ++ + std::string _device_manager_backend; + std::shared_ptr _dm; + +diff --git a/src/Daemon/main.cpp b/src/Daemon/main.cpp +index 869c2e2..4b9b351 100644 +--- a/src/Daemon/main.cpp ++++ b/src/Daemon/main.cpp +@@ -15,6 +15,7 @@ + // along with this program. If not, see . + // + // Authors: Daniel Kopecek ++// Jiri Vymazal + // + #ifdef HAVE_BUILD_CONFIG_H + #include +@@ -37,9 +38,13 @@ + static void setupCapabilities(void); + #endif + ++#ifndef USBGUARD_PID_FILE ++#define USBGUARD_PID_FILE "/var/run/usbguard.pid" ++#endif ++ + using namespace usbguard; + +-const char * const G_optstring = "dskl:p:c:hWC"; ++const char * const G_optstring = "dfskl:p:c:hWC"; + + static void printUsage(std::ostream& stream, const char *arg0) + { +@@ -47,6 +52,7 @@ static void printUsage(std::ostream& stream, const char *arg0) + stream << "Usage: " << filenameFromPath(std::string(arg0), true) << " [OPTIONS]" << std::endl; + stream << std::endl; + stream << " -d Enable debugging messages in the log." << std::endl; ++ stream << " -f Enable classical daemon forking behavior." << std::endl; + stream << " -s Log to syslog." << std::endl; + stream << " -k Log to console." << std::endl; + stream << " -l Log to a file at `path'." << std::endl; +@@ -68,8 +74,9 @@ int main(int argc, char *argv[]) + bool log_file = false; + bool use_seccomp_whitelist = false; + bool drop_capabilities = false; ++ bool daemonize = false; + std::string log_file_path; +- std::string pid_file; ++ std::string pid_file = USBGUARD_PID_FILE; + std::string conf_file = "/etc/usbguard/usbguard-daemon.conf"; + int opt; + +@@ -79,6 +86,9 @@ int main(int argc, char *argv[]) + case 'd': + debug_mode = true; + break; ++ case 'f': ++ daemonize = true; ++ break; + case 's': + log_syslog = true; + break; +@@ -144,6 +154,13 @@ int main(int argc, char *argv[]) + if (!conf_file.empty()) { + daemon.loadConfiguration(conf_file); + } ++ if (daemonize) { ++ if (log_console && !log_syslog && !log_file) { ++ USBGUARD_LOG(Warning) << "You have selected to fork and log only to \ ++ console, nothing will be logged after forking!"; ++ } ++ daemon.daemonize(pid_file); ++ } + daemon.run(); + ret = EXIT_SUCCESS; + } +diff --git a/src/Tests/Makefile.am b/src/Tests/Makefile.am +index 7d93474..a952d18 100644 +--- a/src/Tests/Makefile.am ++++ b/src/Tests/Makefile.am +@@ -40,6 +40,7 @@ EXTRA_DIST=\ + $(top_srcdir)/src/Tests/UseCase/001_cli_policy.sh \ + $(top_srcdir)/src/Tests/UseCase/002_cli_devices.sh \ + $(top_srcdir)/src/Tests/UseCase/003_cli_devices_dummy.sh \ ++ $(top_srcdir)/src/Tests/UseCase/004_daemonize.sh \ + $(top_srcdir)/src/Tests/UseCase/DummyDevices + + LOG_DRIVER=\ +@@ -62,7 +63,8 @@ TESTS=\ + UseCase/000_executable.sh \ + UseCase/001_cli_policy.sh \ + UseCase/002_cli_devices.sh \ +- UseCase/003_cli_devices_dummy.sh ++ UseCase/003_cli_devices_dummy.sh \ ++ UseCase/004_daemonize.sh + + check_PROGRAMS=\ + test-unit \ +diff --git a/src/Tests/UseCase/004_daemonize.sh b/src/Tests/UseCase/004_daemonize.sh +new file mode 100755 +index 0000000..d59dad1 +--- /dev/null ++++ b/src/Tests/UseCase/004_daemonize.sh +@@ -0,0 +1,55 @@ ++#!/bin/bash ++# ++# ++# Copyright (C) 2016 Red Hat, Inc. ++# ++# 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 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 General Public License ++# along with this program. If not, see . ++# ++# Authors: Jiri Vymazal ++# ++# Test whether the binaries are executable as expected (no linker errors, etc.) ++# ++source "${USBGUARD_TESTLIB_BASH}" || exit 129 ++ ++# TODO? Move to testlib ++export USBGUARD_TESTLIB_TMPDIR="$(mktemp -d --tmpdir usbguard-test.XXXXXX)" ++ ++export config_path="${USBGUARD_TESTLIB_TMPDIR}/daemon.conf" ++export pidfile_path="${USBGUARD_TESTLIB_TMPDIR}/usbguard.pid" ++export logfile="${USBGUARD_TESTLIB_TMPDIR}/daemon.log" ++ ++function test_cli_daemonize() ++{ ++ sleep 5 ++ ++ if [ ! -f "$pidfile_path" ]; then ++ echo "Test error: PID file for usbguard not present" ++ exit 1 ++ fi ++ ++ if [ ! `pgrep usbguard` == `cat $pidfile_path` ]; then ++ echo "Test error: PID of usbguard daemon not present in PID file" ++ exit 1 ++ fi ++} ++ ++cat > "$config_path" < +Date: Fri, 12 May 2017 13:15:30 +0200 +Subject: [PATCH 1/2] Fixed usbguard-daemon.conf man page + +--- + doc/usbguard-daemon.conf.5 | 22 +++++++++++++++------- + doc/usbguard-daemon.conf.5.md | 6 +++--- + 2 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/doc/usbguard-daemon.conf.5 b/doc/usbguard-daemon.conf.5 +index f7434b1..476a31e 100644 +--- a/doc/usbguard-daemon.conf.5 ++++ b/doc/usbguard-daemon.conf.5 +@@ -1,4 +1,7 @@ ++.\" Automatically generated by Pandoc 1.17.0.3 ++.\" + .TH "USBGUARD\-DAEMON.CONF" "5" "April 2017" "" "" ++.hy + .SH NAME + .PP + \f[B]usbguard\-daemon.conf\f[] \-\- USBGuard daemon configuration file +@@ -52,8 +55,8 @@ One of \f[C]block\f[], \f[C]reject\f[], \f[C]apply\-policy\f[]. + .B \f[B]RestoreControllerDeviceState\f[]=<\f[I]boolean\f[]> + The USBGuard daemon modifies some attributes of controller devices like + the default authorization state of new child device instances. +-Using this setting, you can controll whether the daemon will try to +-restore the attribute values to the state before modificaton on ++Using this setting, you can control whether the daemon will try to ++restore the attribute values to the state before modification on + shutdown. + .RS + .RE +@@ -70,11 +73,6 @@ connections from. + .RS + .RE + .TP +-.B \f[B]IPCAccessControlFiles\f[]=<\f[I]path\f[]> +-Path to a directory holding the IPC access control files. +-.RS +-.RE +-.TP + .B \f[B]DeviceManagerBackend\f[]=<\f[I]backend\f[]> + Which device manager backend implementation to use. + Backend should be one of \f[C]uevent\f[] (default) or \f[C]dummy\f[]. +@@ -88,6 +86,16 @@ See the \f[B]IPC ACCESS CONTROL\f[] section for more details. + .RS + .RE + .TP ++.B \f[B]DeviceRulesWithPort\f[]=<\f[I]boolean\f[]> ++Generate device specific rules including the "via\-port" attribute. ++This option modifies the behavior of the allowDevice action. ++When instructed to generate a permanent rule, the action can generate a ++port specific rule. ++Because some systems have unstable port numbering, the generated rule ++might not match the device after rebooting the system. ++.RS ++.RE ++.TP + .B \f[B]AuditFilePath\f[]=<\f[I]filepath\f[]> + USBGuard audit events log file path. + .RS +diff --git a/doc/usbguard-daemon.conf.5.md b/doc/usbguard-daemon.conf.5.md +index ea86ad1..58ca0ba 100644 +--- a/doc/usbguard-daemon.conf.5.md ++++ b/doc/usbguard-daemon.conf.5.md +@@ -36,15 +36,15 @@ The **usbguard-daemon.conf** file is loaded by the USBGuard daemon after it pars + **IPCAllowedGroups**=<*groupname*> [<*groupname*> ...] + : A space delimited list of groupnames that the daemon will accept IPC connections from. + +-**IPCAccessControlFiles**=<*path*> +-: Path to a directory holding the IPC access control files. +- + **DeviceManagerBackend**=<*backend*> + : Which device manager backend implementation to use. Backend should be one of `uevent` (default) or `dummy`. + + **IPCAccessControlFiles**=<*path*> + : The files at this location will be interpreted by the daemon as IPC access control definition files. See the **IPC ACCESS CONTROL** section for more details. + ++**DeviceRulesWithPort**=<*boolean*> ++: Generate device specific rules including the "via-port" attribute. This option modifies the behavior of the allowDevice action. When instructed to generate a permanent rule, the action can generate a port specific rule. Because some systems have unstable port numbering, the generated rule might not match the device after rebooting the system. ++ + **AuditFilePath**=<*filepath*> + : USBGuard audit events log file path. + +-- +2.9.3 + diff --git a/SOURCES/usbguard-0.7.0-fixed-usbguard-daemon-man-page.patch b/SOURCES/usbguard-0.7.0-fixed-usbguard-daemon-man-page.patch new file mode 100644 index 00000000..f4ebe211 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-fixed-usbguard-daemon-man-page.patch @@ -0,0 +1,59 @@ +From b6e6d374a5da571314e4b185ff8fdb38974aa9b0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20Kope=C4=8Dek?= +Date: Fri, 12 May 2017 13:20:55 +0200 +Subject: [PATCH 2/2] Fixed usbguard-daemon man page + +--- + doc/usbguard-daemon.8 | 13 +++++++++++++ + doc/usbguard-daemon.8.md | 6 ++++++ + 2 files changed, 19 insertions(+) + +diff --git a/doc/usbguard-daemon.8 b/doc/usbguard-daemon.8 +index ad9a2a9..18c72fe 100644 +--- a/doc/usbguard-daemon.8 ++++ b/doc/usbguard-daemon.8 +@@ -1,4 +1,7 @@ ++.\" Automatically generated by Pandoc 1.17.0.3 ++.\" + .TH "USBGUARD\-DAEMON" "8" "June 2016" "" "" ++.hy + .SH NAME + .PP + \f[B]usbguard\-daemon\f[] \-\- USBGuard daemon +@@ -48,6 +51,16 @@ Load configuration from a file at \f[I]path\f[] (default: + .RS + .RE + .TP ++.B \f[B]\-C\f[] ++Drop capabilities to limit privileges of the process. ++.RS ++.RE ++.TP ++.B \f[B]\-W\f[] ++Use a seccomp whitelist to limit available syscalls to the process. ++.RS ++.RE ++.TP + .B \f[B]\-h\f[] + Show the help/usage screen. + .RS +diff --git a/doc/usbguard-daemon.8.md b/doc/usbguard-daemon.8.md +index 40dc4be..3e2fcaf 100644 +--- a/doc/usbguard-daemon.8.md ++++ b/doc/usbguard-daemon.8.md +@@ -34,6 +34,12 @@ The **usbguard-daemon** is the main component of the USBGuard software framework + **-c** <*path*> + : Load configuration from a file at *path* (default: */etc/usbguard/usbguard-daemon.conf*). + ++**-C** ++: Drop capabilities to limit privileges of the process. ++ ++**-W** ++: Use a seccomp whitelist to limit available syscalls to the process. ++ + **-h** + : Show the help/usage screen. + +-- +2.9.3 + diff --git a/SOURCES/usbguard-0.7.0-kernel-4.13-fix.patch b/SOURCES/usbguard-0.7.0-kernel-4.13-fix.patch new file mode 100644 index 00000000..688235f2 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-kernel-4.13-fix.patch @@ -0,0 +1,68 @@ +diff -up usbguard-0.7.0/src/Library/SysFSDevice.cpp.kernel-fix usbguard-0.7.0/src/Library/SysFSDevice.cpp +--- usbguard-0.7.0/src/Library/SysFSDevice.cpp.kernel-fix 2017-11-27 15:26:34.895791778 +0100 ++++ usbguard-0.7.0/src/Library/SysFSDevice.cpp 2017-11-27 15:29:20.723171663 +0100 +@@ -130,6 +130,20 @@ namespace usbguard + return fd; + } + ++ bool SysFSDevice::hasAttribute(const std::string& name) const ++ { ++ struct ::stat st; ++ ++ if (::fstatat(_sysfs_dirfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) != 0) { ++ if (errno == ENOENT) { ++ return false; ++ } ++ throw ErrnoException("SysFSDevice::hasAttribute", name, errno); ++ } ++ ++ return S_ISREG(st.st_mode); ++ } ++ + std::string SysFSDevice::readAttribute(const std::string& name, bool strip_last_null, bool optional) const + { + USBGUARD_LOG(Trace) << "name=" << name; +diff -up usbguard-0.7.0/src/Library/SysFSDevice.hpp.kernel-fix usbguard-0.7.0/src/Library/SysFSDevice.hpp +--- usbguard-0.7.0/src/Library/SysFSDevice.hpp.kernel-fix 2017-11-27 15:26:34.896791775 +0100 ++++ usbguard-0.7.0/src/Library/SysFSDevice.hpp 2017-11-27 15:28:10.778433223 +0100 +@@ -42,6 +42,7 @@ namespace usbguard + const std::string& getName() const; + const UEvent& getUEvent() const; + const std::string& getParentPath() const; ++ bool hasAttribute(const std::string& name) const; + std::string readAttribute(const std::string& name, bool strip_last_null = false, bool optional = false) const; + void setAttribute(const std::string& name, const std::string& value); + int openAttribute(const std::string& name) const; +diff -up usbguard-0.7.0/src/Library/UEventDeviceManager.cpp.kernel-fix usbguard-0.7.0/src/Library/UEventDeviceManager.cpp +--- usbguard-0.7.0/src/Library/UEventDeviceManager.cpp.kernel-fix 2017-11-27 15:24:29.034262440 +0100 ++++ usbguard-0.7.0/src/Library/UEventDeviceManager.cpp 2017-11-27 15:26:34.897791771 +0100 +@@ -580,7 +580,12 @@ namespace usbguard { + const std::string devtype = uevent.getAttribute("DEVTYPE"); + const std::string action = uevent.getAttribute("ACTION"); + +- if (subsystem != "usb" || devtype != "usb_device") { ++ /* ++ * We don't care about the event if it's not from the "usb" subsystem. ++ * The device type attribute value is checked later based on the data ++ * read from the sysfs uevent file in the device directory. ++ */ ++ if (subsystem != "usb") { + USBGUARD_LOG(Debug) << "Ignoring non-USB device:" + << " subsystem=" << subsystem + << " devtype=" << devtype +@@ -610,8 +615,13 @@ namespace usbguard { + if (sysfs_device.getUEvent().hasAttribute("DEVTYPE")) { + const std::string devtype = sysfs_device.getUEvent().getAttribute("DEVTYPE"); + if (devtype != "usb_device") { +- USBGUARD_LOG(Warning) << sysfs_devpath << ": UEvent DEVTYPE mismatch." +- << " Expected \"usb_device\", got \"" << devtype << "\""; ++ USBGUARD_LOG(Debug) << sysfs_devpath << ": UEvent DEVTYPE != usb_device. Ignoring event."; ++ return; ++ } ++ } ++ else { ++ if (!sysfs_device.hasAttribute("descriptors")) { ++ USBGUARD_LOG(Debug) << sysfs_devpath << ": UEvent doesn't refer to a device with a descriptors file. Ignoring event."; + return; + } + } diff --git a/SOURCES/usbguard-0.7.0-libaudit-version.patch b/SOURCES/usbguard-0.7.0-libaudit-version.patch new file mode 100644 index 00000000..a16c2141 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-libaudit-version.patch @@ -0,0 +1,12 @@ +diff -up usbguard-0.7.0/configure.ac.libaudit-version usbguard-0.7.0/configure.ac +--- usbguard-0.7.0/configure.ac.libaudit-version 2017-12-13 10:31:18.738471922 +0100 ++++ usbguard-0.7.0/configure.ac 2017-12-13 10:32:10.763256142 +0100 +@@ -230,7 +230,7 @@ AC_SUBST([crypto_LIBS]) + # + # Check for optional libraries + # +-PKG_CHECK_MODULES([audit], [audit >= 2.7.7], ++PKG_CHECK_MODULES([audit], [audit >= 2.7.0], + [AC_DEFINE([HAVE_LINUX_AUDIT], [1], [Linux Audit API available]) + AC_CHECK_DECLS([audit_encode_nv_string], [], [], [[#include]]) + libaudit_summary="system-wide; $audit_LIBS"], diff --git a/SOURCES/usbguard-0.7.0-linux-audit-integration.patch b/SOURCES/usbguard-0.7.0-linux-audit-integration.patch new file mode 100644 index 00000000..94ecdff4 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-linux-audit-integration.patch @@ -0,0 +1,1197 @@ +diff --git a/Makefile.am b/Makefile.am +index 37273fb..37508d4 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -310,18 +310,24 @@ usbguard_daemon_SOURCES=\ + src/Daemon/Seccomp.c \ + src/Daemon/Seccomp.h \ + src/Common/Utility.hpp \ +- src/Common/Utility.cpp ++ src/Common/Utility.cpp \ ++ src/Daemon/FileAuditBackend.hpp \ ++ src/Daemon/FileAuditBackend.cpp \ ++ src/Daemon/LinuxAuditBackend.hpp \ ++ src/Daemon/LinuxAuditBackend.cpp + + usbguard_daemon_CPPFLAGS=\ + -fPIE \ + $(AM_CPPFLAGS) \ + @seccomp_CFLAGS@ \ +- @libcapng_CFLAGS@ ++ @libcapng_CFLAGS@ \ ++ @audit_CFLAGS@ + + usbguard_daemon_LDADD=\ + $(top_builddir)/libusbguard.la \ + @seccomp_LIBS@ \ +- @libcapng_LIBS@ ++ @libcapng_LIBS@ \ ++ @audit_LIBS@ + + EXTRA_DIST +=\ + README.md \ +diff --git a/configure.ac b/configure.ac +index 6ab0d9b..3298929 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -230,6 +230,14 @@ AC_SUBST([crypto_LIBS]) + # + # Check for optional libraries + # ++PKG_CHECK_MODULES([audit], [audit >= 2.7.7], ++[AC_DEFINE([HAVE_LINUX_AUDIT], [1], [Linux Audit API available]) ++AC_CHECK_DECLS([audit_encode_nv_string], [], [], [[#include]]) ++libaudit_summary="system-wide; $audit_LIBS"], ++[AC_MSG_NOTICE([libaudit development files not found! Linux Audit support wille be turned OFF]) ++libaudit_summary="not found"] ++) ++ + PKG_CHECK_MODULES([seccomp], [libseccomp >= 2.0.0], + [AC_DEFINE([HAVE_SECCOMP], [1], [seccomp API usable]) + libseccomp_summary="system-wide; $seccomp_LIBS"], +@@ -752,6 +760,7 @@ echo "## Libraries" + echo + echo " libqb: $libqb_summary" + echo " crypto: $crypto_summary" ++echo " libaudit: $libaudit_summary" + echo " libseccomp: $libseccomp_summary" + echo " libcap-ng: $libcap_ng_summary" + echo " protobuf: $protobuf_summary" +diff --git a/doc/usbguard-daemon.conf.5 b/doc/usbguard-daemon.conf.5 +index 476a31e..313f5fb 100644 +--- a/doc/usbguard-daemon.conf.5 ++++ b/doc/usbguard-daemon.conf.5 +@@ -96,6 +96,12 @@ might not match the device after rebooting the system. + .RS + .RE + .TP ++.B \f[B]AuditBackend\f[]=<\f[I]backend\f[]> ++USBGuard audit events log backend. ++Backend should be one of \f[C]FileAudit\f[] or \f[C]LinuxAudit\f[]. ++.RS ++.RE ++.TP + .B \f[B]AuditFilePath\f[]=<\f[I]filepath\f[]> + USBGuard audit events log file path. + .RS +diff --git a/doc/usbguard-daemon.conf.5.md b/doc/usbguard-daemon.conf.5.md +index 58ca0ba..ef9ca7c 100644 +--- a/doc/usbguard-daemon.conf.5.md ++++ b/doc/usbguard-daemon.conf.5.md +@@ -45,6 +45,9 @@ The **usbguard-daemon.conf** file is loaded by the USBGuard daemon after it pars + **DeviceRulesWithPort**=<*boolean*> + : Generate device specific rules including the "via-port" attribute. This option modifies the behavior of the allowDevice action. When instructed to generate a permanent rule, the action can generate a port specific rule. Because some systems have unstable port numbering, the generated rule might not match the device after rebooting the system. + ++**AuditBackend**=<*backend*> ++: USBGuard audit events log backend. Backend should be one of `FileAudit` or `LinuxAudit`. ++ + **AuditFilePath**=<*filepath*> + : USBGuard audit events log file path. + +diff --git a/src/Common/Utility.cpp b/src/Common/Utility.cpp +index 237acfb..af9585f 100644 +--- a/src/Common/Utility.cpp ++++ b/src/Common/Utility.cpp +@@ -365,6 +365,25 @@ namespace usbguard + } + } + ++ bool hasSuffix(const std::string& value, const std::string& suffix) ++ { ++ if (suffix.size() > value.size()) { ++ return false; ++ } ++ const auto pos = value.size() - suffix.size(); ++ const auto cmp = value.compare(pos, suffix.size(), suffix); ++ return cmp == 0; ++ } ++ ++ bool hasPrefix(const std::string& value, const std::string& prefix) ++ { ++ if (prefix.size() > value.size()) { ++ return false; ++ } ++ const auto cmp = value.compare(0, prefix.size(), prefix); ++ return cmp == 0; ++ } ++ + std::string symlinkPath(const std::string& linkpath, struct stat *st_user) + { + struct stat st = { }; +diff --git a/src/Common/Utility.hpp b/src/Common/Utility.hpp +index 54e1ea1..2458930 100644 +--- a/src/Common/Utility.hpp ++++ b/src/Common/Utility.hpp +@@ -185,6 +185,12 @@ namespace usbguard + std::string removePrefix(const std::string& prefix, const std::string& value); + + /** ++ * Test whether a string value has a prefix/suffix. ++ */ ++ bool hasSuffix(const std::string& value, const std::string& suffix); ++ bool hasPrefix(const std::string& value, const std::string& prefix); ++ ++ /** + * Read symlink destination. + */ + std::string symlinkPath(const std::string& linkpath, struct stat *st_user = nullptr); +diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp +index 89d60b3..91c0483 100644 +--- a/src/Daemon/Daemon.cpp ++++ b/src/Daemon/Daemon.cpp +@@ -22,6 +22,8 @@ + #endif + + #include "Daemon.hpp" ++#include "FileAuditBackend.hpp" ++#include "LinuxAuditBackend.hpp" + #include "Common/Utility.hpp" + + #include "usbguard/Logger.hpp" +@@ -62,7 +64,8 @@ namespace usbguard + "RestoreControllerDeviceState", + "DeviceManagerBackend", + "IPCAccessControlFiles", +- "AuditFilePath" ++ "AuditFilePath", ++ "AuditBackend" + }; + + static const std::vector > device_policy_method_strings = { +@@ -95,7 +98,8 @@ namespace usbguard + + Daemon::Daemon() + : _config(G_config_known_names), +- _ruleset(this) ++ _ruleset(this), ++ _audit(_audit_identity) + { + sigset_t signal_set; + sigfillset(&signal_set); +@@ -245,11 +249,48 @@ namespace usbguard + loadIPCAccessControlFiles(value); + } + +- /* AuditFilePath */ +- if (_config.hasSettingValue("AuditFilePath")) { +- const std::string value = _config.getSettingValue("AuditFilePath"); +- USBGUARD_LOG(Debug) << "Setting AuditFilePath to " << value; +- USBGUARD_LOGGER.setAuditFile(true, value); ++ /* AuditBackend */ ++ if (_config.hasSettingValue("AuditBackend")) { ++ const std::string value = _config.getSettingValue("AuditBackend"); ++ USBGUARD_LOG(Debug) << "Setting AuditBackend to " << value; ++ ++ if (value == "LinuxAudit") { ++ std::unique_ptr backend(new LinuxAuditBackend()); ++ _audit.setBackend(std::move(backend)); ++ } ++ else if (value == "FileAudit") { ++ if (_config.hasSettingValue("AuditFilePath")) { ++ const std::string value = _config.getSettingValue("AuditFilePath"); ++ USBGUARD_LOG(Debug) << "Setting AuditFilePath to " << value; ++ USBGUARD_LOGGER.setAuditFile(true, value); ++ } ++ else { ++ /* AuditFilePath value is required is AuditBackend is set to FileAudit */ ++ throw Exception("Configuration", "AuditBackend", "AuditFilePath not set"); ++ } ++ ++ std::unique_ptr backend(new FileAuditBackend()); ++ _audit.setBackend(std::move(backend)); ++ } ++ else { ++ throw Exception("Configuration", "AuditBackend", "Invalid value"); ++ } ++ } ++ else { ++ /* ++ * Left for backwards compatibility. If AuditBackend is NOT set, but ++ * AuditFilePath is, we set the backend to FileAudit automatically. ++ */ ++ ++ /* AuditFilePath */ ++ if (_config.hasSettingValue("AuditFilePath")) { ++ const std::string value = _config.getSettingValue("AuditFilePath"); ++ USBGUARD_LOG(Debug) << "Setting AuditFilePath to " << value; ++ USBGUARD_LOGGER.setAuditFile(true, value); ++ ++ std::unique_ptr backend(new LinuxAuditBackend()); ++ _audit.setBackend(std::move(backend)); ++ } + } + + USBGUARD_LOG(Info) << "Configuration loaded successfully."; +@@ -605,7 +646,7 @@ namespace usbguard + USBGUARD_LOG(Trace) << "event=" << DeviceManager::eventTypeToString(event) + << " device_ptr=" << device.get(); + +- auto audit_event = Audit::deviceEvent(_audit_identity, device, event); ++ auto audit_event = _audit.deviceEvent(device, event); + + std::shared_ptr device_rule = \ + device->getDeviceRule(/*with_port*/true, +@@ -648,8 +689,7 @@ namespace usbguard + USBGUARD_LOG(Trace) << "device_ptr=" << device.get() + << " matched_rule_ptr=" << matched_rule.get(); + +- auto audit_event = Audit::policyEvent(_audit_identity, +- device, device->getTarget(), matched_rule->getTarget()); ++ auto audit_event = _audit.policyEvent(device, device->getTarget(), matched_rule->getTarget()); + + const Rule::Target target_old = device->getTarget(); + std::shared_ptr device_post = \ +diff --git a/src/Daemon/Daemon.hpp b/src/Daemon/Daemon.hpp +index 065deaf..6461f45 100644 +--- a/src/Daemon/Daemon.hpp ++++ b/src/Daemon/Daemon.hpp +@@ -129,5 +129,6 @@ namespace usbguard + bool _restore_controller_device_state; + + AuditIdentity _audit_identity; ++ Audit _audit; + }; + } /* namespace usbguard */ +diff --git a/src/Daemon/FileAuditBackend.cpp b/src/Daemon/FileAuditBackend.cpp +new file mode 100644 +index 0000000..2d53008 +--- /dev/null ++++ b/src/Daemon/FileAuditBackend.cpp +@@ -0,0 +1,47 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#include "FileAuditBackend.hpp" ++ ++#include ++ ++namespace usbguard ++{ ++ void FileAuditBackend::write(const AuditEvent& event) ++ { ++ std::string message; ++ ++ message.append("uid="); ++ message.append(numberToString(event.identity().uid())); ++ message.append(" "); ++ ++ message.append("pid="); ++ message.append(numberToString(event.identity().pid())); ++ message.append(" "); ++ ++ for (const auto& kv_pair : event.keys()) { ++ message.append(kv_pair.first); ++ message.append("='"); ++ message.append(kv_pair.second); ++ message.append("' "); ++ } ++ ++ USBGUARD_LOG(Audit) << message; ++ } ++} ++/* vim: set ts=2 sw=2 et */ +\ No newline at end of file +diff --git a/src/Daemon/FileAuditBackend.hpp b/src/Daemon/FileAuditBackend.hpp +new file mode 100644 +index 0000000..d29a1fe +--- /dev/null ++++ b/src/Daemon/FileAuditBackend.hpp +@@ -0,0 +1,31 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include ++ ++namespace usbguard ++{ ++ class FileAuditBackend : public AuditBackend ++ { ++ public: ++ void write(const AuditEvent& event); ++ }; ++} ++/* vim: set ts=2 sw=2 et */ +\ No newline at end of file +diff --git a/src/Daemon/LinuxAuditBackend.cpp b/src/Daemon/LinuxAuditBackend.cpp +new file mode 100644 +index 0000000..cbd4e2c +--- /dev/null ++++ b/src/Daemon/LinuxAuditBackend.cpp +@@ -0,0 +1,305 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "LinuxAuditBackend.hpp" ++ ++#include ++#include ++#include "Common/Utility.hpp" ++#include "Library/Utility.hpp" ++ ++#include ++ ++#if defined(HAVE_LINUX_AUDIT) ++#include ++ ++#ifndef AUDIT_USER_DEVICE ++#define AUDIT_USER_DEVICE 1137 /* User space hotplug device changes */ ++#endif ++ ++#if !defined(HAVE_DECL_AUDIT_ENCODE_NV_STRING) ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#include ++#include ++#include ++ /* ++ * Audit message encoding functions based on: ++ * https://github.com/linux-audit/audit-userspace/blob/f7cd4d6/lib/audit_logging.c#L125 ++ */ ++ ++ /* ++ * This function checks a string to see if it needs encoding. ++ * It returns true if needed and false if not. ++ */ ++ static bool audit_value_needs_encoding(const char *str, unsigned int size) ++ { ++ if (str == NULL) { ++ return false; ++ } ++ ++ for (unsigned int i = 0; i < size; i++) { ++ // we don't test for > 0x7f because str[] is signed. ++ if (str[i] == '"' || str[i] < 0x21 || str[i] == 0x7F) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ /* ++ * This function does encoding of "untrusted" names just like the kernel ++ */ ++ static char *audit_encode_value(char *final, const char *buf, unsigned int size) ++ { ++ char *ptr = final; ++ const char *hex = "0123456789ABCDEF"; ++ ++ if (final == NULL) ++ return NULL; ++ ++ if (buf == NULL) { ++ *final = 0; ++ return final; ++ } ++ ++ for (unsigned int i = 0; i < size; i++) { ++ *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */ ++ *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */ ++ } ++ *ptr = 0; ++ return final; ++ } ++ ++ static char *audit_encode_nv_string(const char *name, const char *value, unsigned int vlen) ++ { ++ char *str = nullptr; ++ if (vlen == 0 && value) { ++ vlen = ::strlen(value); ++ } ++ if (value && audit_value_needs_encoding(value, vlen)) { ++ char *tmp = reinterpret_cast(::malloc(2*vlen + 1)); ++ if (tmp) { ++ audit_encode_value(tmp, value, vlen); ++ if (::asprintf(&str, "%s=%s", name, tmp) < 0) { ++ str = nullptr; ++ } ++ free(tmp); ++ } ++ else { ++ str = nullptr; ++ } ++ } ++ else { ++ if (::asprintf(&str, "%s=\"%s\"", name, value ? value : "?") < 0) { ++ str = nullptr; ++ } ++ } ++ return str; ++ } ++#endif /* HAVE_DECL_AUDIT_ENCODE_NV_STRING */ ++#endif /* HAVE_LINUX_AUDIT */ ++ ++namespace usbguard ++{ ++#if defined(HAVE_LINUX_AUDIT) ++ static std::string encodeMessageNVPair(const std::string& key, const std::string& value) ++ { ++ std::unique_ptr encoded_cstr(audit_encode_nv_string(key.c_str(), value.c_str(), value.size())); ++ std::string encoded(encoded_cstr.get()); ++ return encoded; ++ } ++ ++ static void appendToMessage(std::string& message, const std::string& key, const std::string& value) ++ { ++ if (message.size() > 0) { ++ message.append(" "); ++ } ++ message.append(encodeMessageNVPair(key, value)); ++ } ++ ++ static std::string translateTypeValue(const std::string& value) ++ { ++ if (hasPrefix(value, "Policy.Device.")) { ++ /* device policy events */ ++ if (hasSuffix(value, "Update")) { ++ return "changed-authorization-state-for"; ++ } ++ throw std::runtime_error("LinuxAuditBackend: unexpected Policy.Device event"); ++ } ++ else if (hasPrefix(value, "Device.")) { ++ /* device events */ ++ if (hasSuffix(value, "Present")) { ++ return "discovered-device"; ++ } ++ if (hasSuffix(value, "Insert")) { ++ return "inserted-device"; ++ } ++ if (hasSuffix(value, "Update")) { ++ return "updated-device"; ++ } ++ if (hasSuffix(value, "Remove")) { ++ return "removed-device"; ++ } ++ throw std::runtime_error("LinuxAuditBackend: unexpected Device event"); ++ } ++ else if (hasPrefix(value, "Policy.")) { ++ /* rule set modification events */ ++ if (hasSuffix(value, "Insert")) { ++ return "inserted-policy-rule"; ++ } ++ if (hasSuffix(value, "Update")) { ++ return "updated-policy-rule"; ++ } ++ if (hasSuffix(value, "Remove")) { ++ return "removed-policy-rule"; ++ } ++ throw std::runtime_error("LinuxAuditBackend: unexpected Policy event"); ++ } ++ ++ throw std::runtime_error("LinuxAuditBackend: unexpected type= key value"); ++ } ++#endif ++ ++ LinuxAuditBackend::LinuxAuditBackend() ++ { ++#if defined(HAVE_LINUX_AUDIT) ++ USBGUARD_LOG(Debug) << "Opening Linux Audit socket"; ++ if ((_audit_fd = audit_open()) < 0) { ++ throw ErrnoException("LinuxAuditBackend", "audit_open", errno); ++ } ++#else ++ (void)_audit_fd; ++ throw std::runtime_error("LinuxAuditBackend: not supported"); ++#endif ++ } ++ ++ LinuxAuditBackend::~LinuxAuditBackend() ++ { ++#if defined(HAVE_LINUX_AUDIT) ++ USBGUARD_LOG(Debug) << "Closing Linux Audit socket"; ++ audit_close(_audit_fd); ++#endif ++ } ++ ++ void LinuxAuditBackend::write(const AuditEvent& event) ++ { ++#if defined(HAVE_LINUX_AUDIT) ++ std::string message; ++ /* ++ * Linux Audit event result ++ * 0 = failed ++ * 1 = success ++ */ ++ int result = 0; ++ auto kvals = event.keys(); ++ ++ std::string audit_key; ++ std::string audit_value; ++ ++ if (kvals.count("type") > 0) { ++ audit_key = "op"; ++ audit_value = translateTypeValue(kvals["type"]); ++ appendToMessage(message, audit_key, audit_value); ++ kvals.erase("type"); ++ } ++ else { ++ throw std::runtime_error("missing required type field in the audit event"); ++ } ++ ++ if (kvals.count("result") > 0) { ++ if (kvals["result"] == "SUCCESS") { ++ result = 1; ++ } ++ kvals.erase("result"); ++ } ++ else { ++ throw std::runtime_error("missing required result field in the audit event"); ++ } ++ ++ if (kvals.count("device.system_name") > 0) { ++ audit_key = "device"; ++ audit_value = kvals["device.system_name"]; ++ appendToMessage(message, audit_key, audit_value); ++ kvals.erase("device.system_name"); ++ } ++ ++ if (kvals.count("rule") > 0) { ++ audit_key = "rule"; ++ audit_value = kvals["rule"]; ++ appendToMessage(message, audit_key, audit_value); ++ kvals.erase("rule"); ++ } ++ ++ for (const auto& kv_pair : kvals) { ++ const std::string& key = kv_pair.first; ++ const std::string& value = kv_pair.second; ++ ++ audit_key.clear(); ++ audit_value.clear(); ++ ++ if (key == "device.rule") { ++ audit_key = "device_rule"; ++ audit_value = value; ++ } ++ else if (key == "device.rule.new") { ++ audit_key = "device_rule"; ++ audit_value = value; ++ } ++ else if (key == "target") { ++ audit_key = "target"; ++ audit_value = value; ++ } ++ else if (key == "target.new") { ++ audit_key = "target"; ++ audit_value = value; ++ } ++ else if (key == "rule.id") { ++ audit_key = "rule_id"; ++ audit_value = value; ++ } ++ else if (key == "rule.new") { ++ audit_key = "rule"; ++ audit_value = value; ++ } ++ /* ++ * Skip appending the key=value pair to the message, if the ++ * audit_key string is empty. This is used to skip key=value ++ * pairs that we don't want to include in the Linux Audit trail. ++ */ ++ if (!audit_key.empty()) { ++ appendToMessage(message, audit_key, audit_value); ++ } ++ } ++ ++ USBGUARD_LOG(Debug) << "Writing Linux Audit message: " << message; ++ audit_log_user_message(_audit_fd, AUDIT_USER_DEVICE, message.c_str(), ++ /*hostname=*/nullptr, /*addr=*/nullptr, /*tty=*/nullptr, result); ++#else ++ (void)event; ++ throw std::runtime_error("LinuxAuditBackend::write: not supported"); ++#endif ++ } ++} ++/* vim: set ts=2 sw=2 et */ +\ No newline at end of file +diff --git a/src/Daemon/LinuxAuditBackend.hpp b/src/Daemon/LinuxAuditBackend.hpp +new file mode 100644 +index 0000000..647c045 +--- /dev/null ++++ b/src/Daemon/LinuxAuditBackend.hpp +@@ -0,0 +1,37 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include ++ ++namespace usbguard ++{ ++ class LinuxAuditBackend : public AuditBackend ++ { ++ public: ++ LinuxAuditBackend(); ++ ~LinuxAuditBackend(); ++ ++ void write(const AuditEvent& event); ++ ++ private: ++ int _audit_fd{-1}; ++ }; ++} ++/* vim: set ts=2 sw=2 et */ +\ No newline at end of file +diff --git a/src/Library/UEventDeviceManager.cpp b/src/Library/UEventDeviceManager.cpp +index bdf4ad0..2f44ff0 100644 +--- a/src/Library/UEventDeviceManager.cpp ++++ b/src/Library/UEventDeviceManager.cpp +@@ -149,6 +149,11 @@ namespace usbguard { + return hub_interface.appliesTo(getInterfaceTypes()[0]); + } + ++ std::string UEventDevice::getSystemName() const ++ { ++ return getSysPath(); ++ } ++ + void UEventDevice::parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) + { + USBGUARD_LOG(Trace); +diff --git a/src/Library/UEventDeviceManager.hpp b/src/Library/UEventDeviceManager.hpp +index b7adb60..7de6951 100644 +--- a/src/Library/UEventDeviceManager.hpp ++++ b/src/Library/UEventDeviceManager.hpp +@@ -49,6 +49,7 @@ namespace usbguard { + SysFSDevice& sysfsDevice(); + const std::string& getSysPath() const; + bool isController() const override; ++ std::string getSystemName() const override; + + private: + void parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) override; +diff --git a/src/Library/public/usbguard/Audit.cpp b/src/Library/public/usbguard/Audit.cpp +index e692733..60bbd1b 100644 +--- a/src/Library/public/usbguard/Audit.cpp ++++ b/src/Library/public/usbguard/Audit.cpp +@@ -41,73 +41,120 @@ namespace usbguard + _pid = pid; + } + ++ uid_t AuditIdentity::uid() const ++ { ++ return _uid; ++ } ++ ++ pid_t AuditIdentity::pid() const ++ { ++ return _pid; ++ } ++ + std::string AuditIdentity::toString() const + { + std::string identity_string; + + identity_string.append("{ uid="); +- identity_string.append(numberToString(_uid)); ++ identity_string.append(numberToString(uid())); + identity_string.append(" pid="); +- identity_string.append(numberToString(_pid)); ++ identity_string.append(numberToString(pid())); + identity_string.append(" }"); + + return identity_string; + } + +- AuditEvent::AuditEvent(const AuditIdentity& identity) +- : _confirmed(false), +- _identity(identity) ++ AuditEvent::AuditEvent(const AuditIdentity& identity, std::shared_ptr& backend) ++ : _commited(false), ++ _identity(identity), ++ _backend(backend) + { +- + } + + AuditEvent::AuditEvent(AuditEvent&& event) +- : _confirmed(event._confirmed), ++ : _commited(event._commited), + _identity(std::move(event._identity)), +- _message(std::move(event._message)) ++ _backend(std::move(event._backend)), ++ _keys(std::move(event._keys)) + { +- event.setConfirmed(true); ++ /* ++ * Mark the source event as commited so that ++ * when it gets destructed, it won't be commited ++ * to the backend. ++ */ ++ event.setCommited(true); + } + + AuditEvent::~AuditEvent() + { +- if (!_confirmed) { ++ /* ++ * If the event was not commited explicitly, assume ++ * that that the result is a failure. ++ */ ++ if (!_commited) { + failure(); + } + } + +- void AuditEvent::confirm(const std::string& result) ++ void AuditEvent::commit(const std::string& result) + { +- USBGUARD_LOG(Audit) << "result=" << result \ +- << " identity=" << _identity.toString() \ +- << " " << _message; +- setConfirmed(true); ++ setKey("result", result); ++ _backend->commit(*this); ++ setCommited(true); + } + + void AuditEvent::success() + { +- confirm("SUCCESS"); ++ commit("SUCCESS"); + } + + void AuditEvent::failure() + { +- confirm("FAILURE"); ++ commit("FAILURE"); ++ } ++ ++ const AuditIdentity& AuditEvent::identity() const ++ { ++ return _identity; + } + +- void AuditEvent::setConfirmed(bool state) ++ const AuditEvent::Keys& AuditEvent::keys() const + { +- _confirmed = state; ++ return _keys; + } + +- std::string& AuditEvent::refMessage() ++ void AuditEvent::setCommited(bool state) + { +- return _message; ++ _commited = state; ++ } ++ ++ void AuditEvent::setKey(const std::string& key, const std::string& value) ++ { ++ _keys.emplace(key, value); ++ } ++ ++ AuditBackend::AuditBackend() ++ { ++ } ++ ++ AuditBackend::~AuditBackend() ++ { ++ } ++ ++ void AuditBackend::commit(const AuditEvent& event) ++ { ++ std::unique_lock lock(_mutex); ++ write(event); + } + + Audit::Audit(const AuditIdentity& identity) + : _identity(identity) + { ++ } + ++ void Audit::setBackend(std::unique_ptr backend) ++ { ++ _backend = std::shared_ptr(std::move(backend)); + } + + AuditEvent Audit::policyEvent(std::shared_ptr rule, Policy::EventType event) +@@ -140,116 +187,74 @@ namespace usbguard + return deviceEvent(_identity, new_device, old_device); + } + +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event) ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event_type) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy."; +- message += Policy::eventTypeToString(event); +- +- message += " rule.id="; +- message += numberToString(rule->getRuleID()); +- +- message += " rule='"; +- message += rule->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Policy.") + Policy::eventTypeToString(event_type)); ++ event.setKey("rule.id", numberToString(rule->getRuleID())); ++ event.setKey("rule", rule->toString()); ++ ++ return event; + } + + AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr new_rule, std::shared_ptr old_rule) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy."; +- message += Policy::eventTypeToString(Policy::EventType::Update); +- +- message += " rule.id="; +- message += numberToString(old_rule->getRuleID()); +- +- message += " rule.old='"; +- message += old_rule->toString(); +- message += "'"; +- +- message += " rule.new='"; +- message += new_rule->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Policy.") + Policy::eventTypeToString(Policy::EventType::Update)); ++ event.setKey("rule.id", numberToString(old_rule->getRuleID())); ++ event.setKey("rule.old", old_rule->toString()); ++ event.setKey("rule.new", new_rule->toString()); ++ ++ return event; + } + +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event) ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event_type) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy.Device."; +- message += Policy::eventTypeToString(event); +- +- message += " target="; +- message += Rule::targetToString(device->getTarget()); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Policy.Device.") + Policy::eventTypeToString(event_type)); ++ event.setKey("target", Rule::targetToString(device->getTarget())); ++ event.setKey("device.system_name", device->getSystemName()); ++ event.setKey("device.rule", device->getDeviceRule()->toString()); ++ ++ return event; + } + + AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr device, Rule::Target old_target, Rule::Target new_target) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy.Device."; +- message += Policy::eventTypeToString(Policy::EventType::Update); +- +- message += " target.old="; +- message += Rule::targetToString(old_target); +- +- message += " target.new="; +- message += Rule::targetToString(new_target); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Policy.Device.") + Policy::eventTypeToString(Policy::EventType::Update)); ++ event.setKey("target.old", Rule::targetToString(old_target)); ++ event.setKey("target.new", Rule::targetToString(new_target)); ++ event.setKey("device.system_name", device->getSystemName()); ++ event.setKey("device.rule", device->getDeviceRule()->toString()); ++ ++ return event; + } + +- AuditEvent Audit::deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event) ++ AuditEvent Audit::deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event_type) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Device."; +- message += DeviceManager::eventTypeToString(event); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Device.") + DeviceManager::eventTypeToString(event_type)); ++ event.setKey("device.system_name", device->getSystemName()); ++ event.setKey("device.rule", device->getDeviceRule()->toString()); ++ ++ return event; + } + + AuditEvent Audit::deviceEvent(const AuditIdentity& identity, std::shared_ptr new_device, std::shared_ptr old_device) + { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Device."; +- message += DeviceManager::eventTypeToString(DeviceManager::EventType::Update); +- +- message += " device.old='"; +- message += old_device->getDeviceRule()->toString(); +- message += "'"; +- +- message += " device.new='"; +- message += new_device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; ++ AuditEvent event(identity, _backend); ++ ++ event.setKey("type", std::string("Device.") + DeviceManager::eventTypeToString(DeviceManager::EventType::Update)); ++ event.setKey("device.system_name", new_device->getSystemName()); ++ event.setKey("device.rule.old", old_device->getDeviceRule()->toString()); ++ event.setKey("device.rule.new", new_device->getDeviceRule()->toString()); ++ ++ return event; + } + } /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Audit.hpp b/src/Library/public/usbguard/Audit.hpp +index 398d4c2..991a451 100644 +--- a/src/Library/public/usbguard/Audit.hpp ++++ b/src/Library/public/usbguard/Audit.hpp +@@ -27,6 +27,8 @@ + + #include + #include ++#include ++#include + + #include + #include +@@ -39,16 +41,24 @@ namespace usbguard + AuditIdentity(); + AuditIdentity(uid_t uid, pid_t pid); + ++ uid_t uid() const; ++ pid_t pid() const; ++ + std::string toString() const; ++ + private: + uid_t _uid; + pid_t _pid; + }; + ++ class AuditBackend; ++ + class DLL_PUBLIC AuditEvent + { +- AuditEvent(const AuditIdentity& identity); ++ AuditEvent(const AuditIdentity& identity, std::shared_ptr& backend); + public: ++ using Keys = std::unordered_map; ++ + AuditEvent(AuditEvent&& event); + AuditEvent(const AuditEvent& event) = delete; + ~AuditEvent(); +@@ -56,23 +66,43 @@ namespace usbguard + void success(); + void failure(); + ++ const AuditIdentity& identity() const; ++ const Keys& keys() const; ++ + private: +- void confirm(const std::string& result); +- void setConfirmed(bool state); +- std::string& refMessage(); ++ void commit(const std::string& result); ++ void setCommited(bool state); ++ void setKey(const std::string& key, const std::string& value); + +- bool _confirmed; ++ bool _commited; ++ + AuditIdentity _identity; +- std::string _message; ++ std::shared_ptr _backend; ++ Keys _keys; + + friend class Audit; + }; + ++ class DLL_PUBLIC AuditBackend ++ { ++ public: ++ AuditBackend(); ++ virtual ~AuditBackend(); ++ ++ virtual void write(const AuditEvent& event) = 0; ++ void commit(const AuditEvent& event); ++ ++ private: ++ std::mutex _mutex; ++ }; ++ + class DLL_PUBLIC Audit + { + public: + Audit(const AuditIdentity& identity); + ++ void setBackend(std::unique_ptr backend); ++ + AuditEvent policyEvent(std::shared_ptr rule, Policy::EventType event); + AuditEvent policyEvent(std::shared_ptr new_rule, std::shared_ptr old_rule); + AuditEvent policyEvent(std::shared_ptr device, Policy::EventType event); +@@ -94,10 +124,10 @@ namespace usbguard + * - what: append, remove, update + * - update: old, new + */ +- static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event); +- static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr new_rule, std::shared_ptr old_rule); +- static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event); +- static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Rule::Target old_target, Rule::Target new_target); ++ AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event); ++ AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr new_rule, std::shared_ptr old_rule); ++ AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event); ++ AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Rule::Target old_target, Rule::Target new_target); + + /* + * Audit device changes: +@@ -111,10 +141,11 @@ namespace usbguard + * - what: insert, remove, authorization target + * - change: old, new + */ +- static AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event); +- static AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr new_device, std::shared_ptr old_device); ++ AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event); ++ AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr new_device, std::shared_ptr old_device); + + private: + AuditIdentity _identity; ++ std::shared_ptr _backend; + }; + } /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Device.hpp b/src/Library/public/usbguard/Device.hpp +index d5a8130..f8dbb8d 100644 +--- a/src/Library/public/usbguard/Device.hpp ++++ b/src/Library/public/usbguard/Device.hpp +@@ -78,6 +78,7 @@ namespace usbguard { + const std::vector& getInterfaceTypes() const; + + virtual bool isController() const = 0; ++ virtual std::string getSystemName() const = 0; + + void loadDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); + void loadConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +diff --git a/usbguard-daemon.conf.in b/usbguard-daemon.conf.in +index 5e39e7b..bb98276 100644 +--- a/usbguard-daemon.conf.in ++++ b/usbguard-daemon.conf.in +@@ -155,6 +155,18 @@ IPCAccessControlFiles=%sysconfdir%/usbguard/IPCAccessControl.d/ + DeviceRulesWithPort=false + + # ++# USBGuard Audit events log backend ++# ++# One of: ++# ++# * FileAudit - Log audit events into a file specified by ++# AuditFilePath setting (see below) ++# * LinuxAudit - Log audit events using the Linux Audit ++# subsystem (using audit_log_user_message) ++# ++AuditBackend=FileAudit ++ ++# + # USBGuard audit events log file path. + # +-AuditFilePath=%localstatedir%/log/usbguard/usbguard-audit.log ++AuditFilePath=%localstatedir%/log/usbguard/usbguard-audit.log +\ No newline at end of file diff --git a/SOURCES/usbguard-0.7.0-make-full-testsuite-conditional.patch b/SOURCES/usbguard-0.7.0-make-full-testsuite-conditional.patch new file mode 100644 index 00000000..cbac6408 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-make-full-testsuite-conditional.patch @@ -0,0 +1,99 @@ +diff --git a/Makefile.am b/Makefile.am +index b7aa1a3..37273fb 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -670,15 +670,3 @@ analyze-clang: + --status-bugs -maxloop 8 -disable-checker deadcode.DeadStores -o "$(abs_top_builddir)" \ + make -j$(JOBS) + rm -rf "$(ANALYSIS_ROOT)" +- +-if MAINTAINER_MODE +-check-local: check-copyright +- +-check-copyright: +- $(eval GIT_CLONE_ROOT:=$(shell mktemp -d -t usbguard-git-clone.XXXXXX)) +- git clone "$(abs_top_srcdir)" "$(GIT_CLONE_ROOT)" && \ +- $(top_srcdir)/src/Tests/Packaging/files-without-copyright.sh "$(GIT_CLONE_ROOT)" +- rm -rf "$(GIT_CLONE_ROOT)" +-else +-check-local: +-endif +diff --git a/configure.ac b/configure.ac +index 287abf2..6ab0d9b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -597,13 +597,15 @@ if test -z "$ASPELL"; then + fi + + # +-# Maintainer mode. ++# Full test suite mode. + # +-# Runs several additional taks for certain make targets (e.g. tests) ++# Runs all available test when enabled. Some tests make assumption about ++# the environment they run in, so they might fail when these assumptions ++# are not met. + # +-AC_ARG_ENABLE([maintainer-mode], +- [AS_HELP_STRING([--enable-maintainer-mode], [Enable maintainer mode (default=no)])], +- [maintainer_mode=$enableval], [maintainer_mode=no]) ++AC_ARG_ENABLE([full-test-suite], ++ [AS_HELP_STRING([--enable-full-test-suite], [Run the full test suite (default=no)])], ++ [full_test_suite=$enableval], [full_test_suite=no]) + + # Checks for header files. + AC_LANG_PUSH([C++]) +@@ -713,8 +715,8 @@ AM_CONDITIONAL([SYSTEMD_SUPPORT_ENABLED], [test "x$systemd" = xyes ]) + AM_CONDITIONAL([GUI_QT_ENABLED], [test "x$build_gui_qt" = xyes ]) + AM_CONDITIONAL([DBUS_ENABLED], [test "x$with_dbus" = xyes ]) + AM_CONDITIONAL([POLICYKIT_ENABLED], [test "x$with_polkit" = xyes]) +-AM_CONDITIONAL([MAINTAINER_MODE], [test "x$maintainer_mode" = xyes]) +-AM_CONDITIONAL([BASH_COMPLETION_ENABLED],[test "x$bash_completion" != "xno"]) ++AM_CONDITIONAL([FULL_TEST_SUITE_ENABLED], [test "x$full_test_suite" = xyes]) ++AM_CONDITIONAL([BASH_COMPLETION_ENABLED], [test "x$bash_completion" != xno]) + + CXXFLAGS="$CXXFLAGS -fvisibility=hidden $COMMON_WARNING_FLAGS $WARNING_CXXFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden $COMMON_WARNING_FLAGS $WARNING_CFLAGS" +@@ -744,7 +746,7 @@ echo + echo " Build Configuration Summary " + echo "===================================" + echo +-echo " Maintainer mode: $maintainer_mode" ++echo " Run full test suite: $full_test_suite" + echo + echo "## Libraries" + echo +@@ -768,7 +770,8 @@ echo " Bash completion dir: $BASH_COMPLETION_DIR" + echo + echo "## Compilation Flags" + echo +-echo " Debug Mode: $debug" ++echo "Debug Build: $debug" ++echo " DEFS: $DEFS" + echo " CXXFLAGS: $CXXFLAGS" + echo " CFLAGS: $CFLAGS" + echo " CPPFLAGS: $CPPFLAGS" +diff --git a/src/Tests/Makefile.am b/src/Tests/Makefile.am +index a952d18..da7a35b 100644 +--- a/src/Tests/Makefile.am ++++ b/src/Tests/Makefile.am +@@ -58,13 +58,17 @@ TESTS=\ + test-unit \ + test-regression \ + USB/test-descriptor-parser.sh \ +- Packaging/spell-check.sh \ +- Rules/test-rules.sh \ ++ Rules/test-rules.sh ++ ++if FULL_TEST_SUITE_ENABLED ++TESTS+=\ ++ Packaging/spell-check.sh \ + UseCase/000_executable.sh \ + UseCase/001_cli_policy.sh \ + UseCase/002_cli_devices.sh \ + UseCase/003_cli_devices_dummy.sh \ + UseCase/004_daemonize.sh ++endif + + check_PROGRAMS=\ + test-unit \ diff --git a/SOURCES/usbguard-0.7.0-strict-configuration-parsing.patch b/SOURCES/usbguard-0.7.0-strict-configuration-parsing.patch new file mode 100644 index 00000000..359cdbc3 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-strict-configuration-parsing.patch @@ -0,0 +1,59 @@ +diff -up usbguard-0.7.0/src/Library/ConfigFilePrivate.cpp.strict-config usbguard-0.7.0/src/Library/ConfigFilePrivate.cpp +--- usbguard-0.7.0/src/Library/ConfigFilePrivate.cpp.strict-config 2017-11-03 10:43:09.528657179 +0100 ++++ usbguard-0.7.0/src/Library/ConfigFilePrivate.cpp 2017-11-03 11:03:51.338013408 +0100 +@@ -23,6 +23,7 @@ + #include "ConfigFilePrivate.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Exception.hpp" + #include "usbguard/Logger.hpp" + + #include +@@ -53,7 +54,7 @@ namespace usbguard + { + _stream.open(path, std::ios::in|std::ios::out); + if (!_stream.is_open()) { +- throw std::runtime_error("Can't open " + path); ++ throw Exception("Configuration", path, "unable to open the configuration file"); + } + _dirty = false; + parse(); +@@ -62,7 +63,7 @@ namespace usbguard + void ConfigFilePrivate::write() + { + if (!_stream.is_open()) { +- throw std::runtime_error("BUG: ConfigFilePrivate::write: write() before open()"); ++ throw USBGUARD_BUG("ConfigFilePrivate::write: write() before open()"); + } + + if (_dirty) { +@@ -116,21 +117,22 @@ namespace usbguard + while(std::getline(_stream, config_line)) { + ++config_line_number; + _lines.push_back(config_line); ++ config_line = trim(config_line); ++ ++ if (config_line.size() < 1 || config_line[0] == '#') { ++ continue; ++ } + + const size_t nv_separator = config_line.find_first_of("="); + if (nv_separator == std::string::npos) { +- continue; ++ throw Exception("Configuration", "line " + std::to_string(config_line_number), "syntax error"); + } + + std::string name = trim(config_line.substr(0, nv_separator)); +- std::string value = config_line.substr(nv_separator + 1); +- +- if (name[0] == '#') { +- continue; +- } ++ std::string value = trim(config_line.substr(nv_separator + 1)); + + if (!checkNVPair(name, value)) { +- continue; ++ throw Exception("Configuration", name, "unknown configuration directive"); + } + + NVPair& setting = _settings[name]; diff --git a/SOURCES/usbguard-0.7.0-upstream-compat.patch b/SOURCES/usbguard-0.7.0-upstream-compat.patch new file mode 100644 index 00000000..bd1eb303 --- /dev/null +++ b/SOURCES/usbguard-0.7.0-upstream-compat.patch @@ -0,0 +1,16939 @@ +diff --git a/Makefile.am b/Makefile.am +index 090e69c..1852983 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -138,7 +138,7 @@ man1_MANS=\ + + AM_CPPFLAGS=\ + -I$(top_srcdir)/src \ +- -I$(top_srcdir)/src/Library ++ -I$(top_srcdir)/src/Library/public + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = libusbguard.pc +@@ -150,6 +150,7 @@ libusbguard_la_CPPFLAGS=\ + -fPIC \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/Library \ ++ -I$(top_srcdir)/src/Library/public \ + -I$(top_builddir)/src/Library/IPC \ + @qb_CFLAGS@ \ + @protobuf_CFLAGS@ \ +@@ -196,94 +197,94 @@ CLEANFILES+=\ + $(nodist_libusbguard_la_SOURCES) + + libusbguard_la_SOURCES=\ +- src/Common/Thread.hpp \ + src/Common/ByteOrder.hpp \ +- src/Common/Utility.hpp \ +- src/Common/Utility.cpp \ + src/Common/FDInputStream.hpp \ +- src/Library/ConfigFile.cpp \ ++ src/Common/Thread.hpp \ ++ src/Common/Utility.cpp \ ++ src/Common/Utility.hpp \ ++ src/Library/AllowedMatchesCondition.cpp \ ++ src/Library/AllowedMatchesCondition.hpp \ ++ src/Library/Base64.cpp \ ++ src/Library/Base64.hpp \ + src/Library/ConfigFilePrivate.cpp \ + src/Library/ConfigFilePrivate.hpp \ +- src/Library/IPCPrivate.hpp \ +- src/Library/IPCPrivate.cpp \ +- src/Library/IPCClient.cpp \ +- src/Library/IPCClientPrivate.hpp \ ++ src/Library/DeviceManagerPrivate.cpp \ ++ src/Library/DeviceManagerPrivate.hpp \ ++ src/Library/DevicePrivate.cpp \ ++ src/Library/DevicePrivate.hpp \ ++ src/Library/FixedStateCondition.cpp \ ++ src/Library/FixedStateCondition.hpp \ ++ src/Library/Hash.cpp \ ++ src/Library/Hash.hpp \ + src/Library/IPCClientPrivate.cpp \ +- src/Library/IPCServer.cpp \ +- src/Library/IPCServerPrivate.hpp \ ++ src/Library/IPCClientPrivate.hpp \ ++ src/Library/IPCPrivate.cpp \ ++ src/Library/IPCPrivate.hpp \ + src/Library/IPCServerPrivate.cpp \ +- src/Library/USB.cpp \ +- src/Library/Rule.cpp \ +- src/Library/RuleParser.cpp \ +- src/Library/RuleParser.hpp \ +- src/Library/RuleParser/Grammar.hpp \ +- src/Library/RuleParser/Actions.hpp \ +- src/Library/RulePrivate.cpp \ +- src/Library/RulePrivate.hpp \ +- src/Library/RuleSet.cpp \ +- src/Library/RuleSetPrivate.cpp \ +- src/Library/RuleSetPrivate.hpp \ +- src/Library/Typedefs.cpp \ +- src/Library/DeviceManagerHooks.cpp \ +- src/Library/Device.cpp \ +- src/Library/DevicePrivate.hpp \ +- src/Library/DevicePrivate.cpp \ +- src/Library/DeviceManager.cpp \ +- src/Library/DeviceManagerPrivate.hpp \ +- src/Library/DeviceManagerPrivate.cpp \ +- src/Library/Logger.cpp \ ++ src/Library/IPCServerPrivate.hpp \ + src/Library/Init.cpp \ +- src/Library/RuleCondition.hpp \ +- src/Library/RuleCondition.cpp \ +- src/Library/AllowedMatchesCondition.hpp \ +- src/Library/AllowedMatchesCondition.cpp \ +- src/Library/FixedStateCondition.hpp \ +- src/Library/FixedStateCondition.cpp \ +- src/Library/RandomStateCondition.hpp \ +- src/Library/RandomStateCondition.cpp \ +- src/Library/LocaltimeCondition.hpp \ + src/Library/LocaltimeCondition.cpp \ ++ src/Library/LocaltimeCondition.hpp \ ++ src/Library/RandomStateCondition.cpp \ ++ src/Library/RandomStateCondition.hpp \ + src/Library/RuleAppliedCondition.cpp \ + src/Library/RuleAppliedCondition.hpp \ + src/Library/RuleEvaluatedCondition.cpp \ + src/Library/RuleEvaluatedCondition.hpp \ +- src/Library/Utility.cpp \ +- src/Library/Base64.cpp \ +- src/Library/Base64.hpp \ +- src/Library/Hash.cpp \ +- src/Library/Hash.hpp \ +- src/Library/UEvent.hpp \ ++ src/Library/RuleParser/Actions.hpp \ ++ src/Library/RuleParser/Grammar.hpp \ ++ src/Library/RulePrivate.cpp \ ++ src/Library/RulePrivate.hpp \ ++ src/Library/RuleSetPrivate.cpp \ ++ src/Library/RuleSetPrivate.hpp \ ++ src/Library/SysFSDevice.cpp \ ++ src/Library/SysFSDevice.hpp \ + src/Library/UEvent.cpp \ +- src/Library/UEventParser.hpp \ +- src/Library/UEventParser.cpp \ +- src/Library/UEventDeviceManager.hpp \ ++ src/Library/UEvent.hpp \ + src/Library/UEventDeviceManager.cpp \ +- src/Library/SysFSDevice.hpp \ +- src/Library/SysFSDevice.cpp \ +- src/Library/USBGuard.cpp \ +- src/Library/Policy.cpp \ +- src/Library/Audit.cpp \ +- src/Library/Audit.hpp ++ src/Library/UEventDeviceManager.hpp \ ++ src/Library/UEventParser.cpp \ ++ src/Library/UEventParser.hpp \ ++ src/Library/Utility.cpp \ ++ src/Library/Utility.hpp \ ++ src/Library/public/usbguard/Audit.cpp \ ++ src/Library/public/usbguard/Audit.hpp \ ++ src/Library/public/usbguard/ConfigFile.cpp \ ++ src/Library/public/usbguard/Device.cpp \ ++ src/Library/public/usbguard/DeviceManager.cpp \ ++ src/Library/public/usbguard/DeviceManagerHooks.cpp \ ++ src/Library/public/usbguard/IPCClient.cpp \ ++ src/Library/public/usbguard/IPCServer.cpp \ ++ src/Library/public/usbguard/Logger.cpp \ ++ src/Library/public/usbguard/Policy.cpp \ ++ src/Library/public/usbguard/Rule.cpp \ ++ src/Library/public/usbguard/RuleCondition.cpp \ ++ src/Library/public/usbguard/RuleParser.cpp \ ++ src/Library/public/usbguard/RuleParser.hpp \ ++ src/Library/public/usbguard/RuleSet.cpp \ ++ src/Library/public/usbguard/Typedefs.cpp \ ++ src/Library/public/usbguard/USB.cpp \ ++ src/Library/public/usbguard/USBGuard.cpp + + pkginclude_HEADERS=\ +- src/Library/ConfigFile.hpp \ +- src/Library/Interface.hpp \ +- src/Library/IPCClient.hpp \ +- src/Library/IPCServer.hpp \ +- src/Library/USB.hpp \ +- src/Library/Rule.hpp \ +- src/Library/RuleSet.hpp \ +- src/Library/Typedefs.hpp \ +- src/Library/DeviceManagerHooks.hpp \ +- src/Library/Device.hpp \ +- src/Library/DeviceManager.hpp \ +- src/Library/Logger.hpp \ +- src/Library/Predicates.hpp \ +- src/Library/Utility.hpp \ +- src/Library/Exception.hpp \ +- src/Library/USBGuard.hpp \ +- src/Library/Policy.hpp \ +- src/Library/Audit.hpp ++ src/Library/public/usbguard/Audit.hpp \ ++ src/Library/public/usbguard/ConfigFile.hpp \ ++ src/Library/public/usbguard/Device.hpp \ ++ src/Library/public/usbguard/DeviceManager.hpp \ ++ src/Library/public/usbguard/DeviceManagerHooks.hpp \ ++ src/Library/public/usbguard/Exception.hpp \ ++ src/Library/public/usbguard/IPCClient.hpp \ ++ src/Library/public/usbguard/IPCServer.hpp \ ++ src/Library/public/usbguard/Interface.hpp \ ++ src/Library/public/usbguard/Logger.hpp \ ++ src/Library/public/usbguard/Policy.hpp \ ++ src/Library/public/usbguard/Predicates.hpp \ ++ src/Library/public/usbguard/Rule.hpp \ ++ src/Library/public/usbguard/RuleCondition.hpp \ ++ src/Library/public/usbguard/RuleSet.hpp \ ++ src/Library/public/usbguard/Typedefs.hpp \ ++ src/Library/public/usbguard/USB.hpp \ ++ src/Library/public/usbguard/USBGuard.hpp + + # Workaround for generated protobuf code mishaps + #``` +@@ -304,11 +305,9 @@ sbin_PROGRAMS=\ + usbguard_daemon_SOURCES=\ + src/Daemon/Daemon.cpp \ + src/Daemon/Daemon.hpp \ +- src/Daemon/Exceptions.hpp \ + src/Daemon/main.cpp \ + src/Daemon/Seccomp.c \ + src/Daemon/Seccomp.h \ +- src/Common/CCBQueue.hpp \ + src/Common/Utility.hpp \ + src/Common/Utility.cpp + +diff --git a/configure.ac b/configure.ac +index 0c9a525..287abf2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -17,6 +17,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])]) + # + EXTERNAL_CXXFLAGS="$CXXFLAGS" + EXTERNAL_CFLAGS="$CFLAGS" ++EXTERNAL_CPPFLAGS="$CPPFLAGS" + + COMMON_WARNING_FLAGS=" -pedantic" + COMMON_WARNING_FLAGS+=" -Wno-unknown-pragmas" +@@ -54,6 +55,7 @@ AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], + # + CXXFLAGS="-std=c++11 $EXTERNAL_CXXFLAGS" + CFLAGS="-std=c99 $EXTERNAL_CFLAGS" ++CPPFLAGS="-DHAVE_BUILD_CONFIG_H $EXTERNAL_CPPFLAGS" + + # + # Additional CXXFLAGS used when --enable-debug-build is used +diff --git a/src/CLI/IPCSignalWatcher.cpp b/src/CLI/IPCSignalWatcher.cpp +index 3dbb616..d4e9e1a 100644 +--- a/src/CLI/IPCSignalWatcher.cpp ++++ b/src/CLI/IPCSignalWatcher.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include + #include "IPCSignalWatcher.hpp" + +diff --git a/src/CLI/IPCSignalWatcher.hpp b/src/CLI/IPCSignalWatcher.hpp +index 36e979e..2101def 100644 +--- a/src/CLI/IPCSignalWatcher.hpp ++++ b/src/CLI/IPCSignalWatcher.hpp +@@ -17,7 +17,11 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/IPCClient.hpp" + + namespace usbguard + { +diff --git a/src/CLI/PolicyGenerator.cpp b/src/CLI/PolicyGenerator.cpp +index 277019f..1035e40 100644 +--- a/src/CLI/PolicyGenerator.cpp ++++ b/src/CLI/PolicyGenerator.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "PolicyGenerator.hpp" + + namespace usbguard +@@ -77,7 +81,7 @@ namespace usbguard + _catchall_target = target; + } + +- void PolicyGenerator::dmHookDeviceEvent(DeviceManager::EventType event, Pointer device) ++ void PolicyGenerator::dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) + { + if (event != DeviceManager::EventType::Present) { + /* +@@ -96,11 +100,11 @@ namespace usbguard + port_specific = device->getSerial().empty(); + } + +- Pointer rule = device->getDeviceRule(/*include_port=*/port_specific); ++ std::shared_ptr rule = device->getDeviceRule(/*include_port=*/port_specific); + + /* Remove everything but the hash value for hash-only rules */ + if (_hash_only) { +- Pointer rule_hashonly(new Rule()); ++ std::shared_ptr rule_hashonly(new Rule()); + rule_hashonly->setRuleID(rule->getRuleID()); + rule_hashonly->setHash(rule->getHash()); + rule_hashonly->setParentHash(rule->getParentHash()); +@@ -127,7 +131,7 @@ namespace usbguard + return _ruleset.assignID(); + } + +- void PolicyGenerator::dmHookDeviceException(const String& message) ++ void PolicyGenerator::dmHookDeviceException(const std::string& message) + { + USBGUARD_LOG(Error) << message; + } +diff --git a/src/CLI/PolicyGenerator.hpp b/src/CLI/PolicyGenerator.hpp +index bbb872a..5de5429 100644 +--- a/src/CLI/PolicyGenerator.hpp ++++ b/src/CLI/PolicyGenerator.hpp +@@ -16,10 +16,14 @@ + // + // Authors: Daniel Kopecek + // +-#include +-#include +-#include +-#include ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Rule.hpp" ++#include "usbguard/RuleSet.hpp" ++#include "usbguard/DeviceManager.hpp" ++#include "usbguard/DeviceManagerHooks.hpp" + + namespace usbguard + { +@@ -37,13 +41,13 @@ namespace usbguard + void generate(); + const RuleSet& refRuleSet() const; + +- void dmHookDeviceEvent(DeviceManager::EventType event, Pointer device) override; ++ void dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) override; + uint32_t dmHookAssignID() override; +- void dmHookDeviceException(const String& message) override; ++ void dmHookDeviceException(const std::string& message) override; + + private: + RuleSet _ruleset; +- Pointer _dm; ++ std::shared_ptr _dm; + + bool _with_hash; + bool _hash_only; +diff --git a/src/CLI/usbguard-add-user.cpp b/src/CLI/usbguard-add-user.cpp +index 228c08d..e8307ea 100644 +--- a/src/CLI/usbguard-add-user.cpp ++++ b/src/CLI/usbguard-add-user.cpp +@@ -16,11 +16,18 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-add-user.hpp" +-#include +-#include ++ ++#include "usbguard/USBGuard.hpp" ++#include "usbguard/IPCServer.hpp" ++ + #include ++ + #include + #include + +diff --git a/src/CLI/usbguard-add-user.hpp b/src/CLI/usbguard-add-user.hpp +index 9bd8b12..73d74f4 100644 +--- a/src/CLI/usbguard-add-user.hpp ++++ b/src/CLI/usbguard-add-user.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_add_user(int argc, char **argv); +diff --git a/src/CLI/usbguard-allow-device.cpp b/src/CLI/usbguard-allow-device.cpp +index 7a3cf07..449218c 100644 +--- a/src/CLI/usbguard-allow-device.cpp ++++ b/src/CLI/usbguard-allow-device.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-allow-device.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-allow-device.hpp b/src/CLI/usbguard-allow-device.hpp +index 80cdd34..d236a69 100644 +--- a/src/CLI/usbguard-allow-device.hpp ++++ b/src/CLI/usbguard-allow-device.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_allow_device(int argc, char **argv); +diff --git a/src/CLI/usbguard-append-rule.cpp b/src/CLI/usbguard-append-rule.cpp +index c455905..ab1adbb 100644 +--- a/src/CLI/usbguard-append-rule.cpp ++++ b/src/CLI/usbguard-append-rule.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-append-rule.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-append-rule.hpp b/src/CLI/usbguard-append-rule.hpp +index 1a1b229..049a40d 100644 +--- a/src/CLI/usbguard-append-rule.hpp ++++ b/src/CLI/usbguard-append-rule.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_append_rule(int argc, char **argv); +diff --git a/src/CLI/usbguard-block-device.cpp b/src/CLI/usbguard-block-device.cpp +index 71bd011..b4100bc 100644 +--- a/src/CLI/usbguard-block-device.cpp ++++ b/src/CLI/usbguard-block-device.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-block-device.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-block-device.hpp b/src/CLI/usbguard-block-device.hpp +index b0e1812..8962e7b 100644 +--- a/src/CLI/usbguard-block-device.hpp ++++ b/src/CLI/usbguard-block-device.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_block_device(int argc, char **argv); +diff --git a/src/CLI/usbguard-generate-policy.cpp b/src/CLI/usbguard-generate-policy.cpp +index 47bbbc0..207aa5d 100644 +--- a/src/CLI/usbguard-generate-policy.cpp ++++ b/src/CLI/usbguard-generate-policy.cpp +@@ -16,15 +16,20 @@ + // + // Authors: Daniel Kopecek + // +-#include +-#include +-#include ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "usbguard.hpp" + #include "usbguard-generate-policy.hpp" + #include "PolicyGenerator.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/DeviceManager.hpp" ++ ++#include ++#include ++ + namespace usbguard + { + static const char *options_short = "hpPt:HX"; +diff --git a/src/CLI/usbguard-generate-policy.hpp b/src/CLI/usbguard-generate-policy.hpp +index 464edfa..3d3d975 100644 +--- a/src/CLI/usbguard-generate-policy.hpp ++++ b/src/CLI/usbguard-generate-policy.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_generate_policy(int argc, char **argv); +diff --git a/src/CLI/usbguard-get-parameter.cpp b/src/CLI/usbguard-get-parameter.cpp +index 2a1ce08..b81f416 100644 +--- a/src/CLI/usbguard-get-parameter.cpp ++++ b/src/CLI/usbguard-get-parameter.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-get-parameter.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-get-parameter.hpp b/src/CLI/usbguard-get-parameter.hpp +index fdd74fe..147cd15 100644 +--- a/src/CLI/usbguard-get-parameter.hpp ++++ b/src/CLI/usbguard-get-parameter.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_get_parameter(int argc, char **argv); +diff --git a/src/CLI/usbguard-list-devices.cpp b/src/CLI/usbguard-list-devices.cpp +index 01389df..94112d6 100644 +--- a/src/CLI/usbguard-list-devices.cpp ++++ b/src/CLI/usbguard-list-devices.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-list-devices.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-list-devices.hpp b/src/CLI/usbguard-list-devices.hpp +index 0b99454..563f754 100644 +--- a/src/CLI/usbguard-list-devices.hpp ++++ b/src/CLI/usbguard-list-devices.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_list_devices(int argc, char **argv); +diff --git a/src/CLI/usbguard-list-rules.cpp b/src/CLI/usbguard-list-rules.cpp +index 396c3c8..2508d5a 100644 +--- a/src/CLI/usbguard-list-rules.cpp ++++ b/src/CLI/usbguard-list-rules.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-list-rules.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-list-rules.hpp b/src/CLI/usbguard-list-rules.hpp +index 9508e1b..60ccccc 100644 +--- a/src/CLI/usbguard-list-rules.hpp ++++ b/src/CLI/usbguard-list-rules.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_list_rules(int argc, char **argv); +diff --git a/src/CLI/usbguard-read-descriptor.cpp b/src/CLI/usbguard-read-descriptor.cpp +index deb3364..451fb8f 100644 +--- a/src/CLI/usbguard-read-descriptor.cpp ++++ b/src/CLI/usbguard-read-descriptor.cpp +@@ -16,10 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-read-descriptor.hpp" +-#include +-#include ++ ++#include "usbguard/USB.hpp" ++#include "usbguard/Exception.hpp" ++ + #include + #include + #include +diff --git a/src/CLI/usbguard-read-descriptor.hpp b/src/CLI/usbguard-read-descriptor.hpp +index ca505a4..8310dae 100644 +--- a/src/CLI/usbguard-read-descriptor.hpp ++++ b/src/CLI/usbguard-read-descriptor.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_read_descriptor(int argc, char **argv); +diff --git a/src/CLI/usbguard-reject-device.cpp b/src/CLI/usbguard-reject-device.cpp +index adaaa18..08649a3 100644 +--- a/src/CLI/usbguard-reject-device.cpp ++++ b/src/CLI/usbguard-reject-device.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-reject-device.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-reject-device.hpp b/src/CLI/usbguard-reject-device.hpp +index 2d54a37..8d42276 100644 +--- a/src/CLI/usbguard-reject-device.hpp ++++ b/src/CLI/usbguard-reject-device.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_reject_device(int argc, char **argv); +diff --git a/src/CLI/usbguard-remove-rule.cpp b/src/CLI/usbguard-remove-rule.cpp +index b99dc0f..05acd0a 100644 +--- a/src/CLI/usbguard-remove-rule.cpp ++++ b/src/CLI/usbguard-remove-rule.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-remove-rule.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-remove-rule.hpp b/src/CLI/usbguard-remove-rule.hpp +index e31a11f..0c0f9e0 100644 +--- a/src/CLI/usbguard-remove-rule.hpp ++++ b/src/CLI/usbguard-remove-rule.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_remove_rule(int argc, char **argv); +diff --git a/src/CLI/usbguard-remove-user.cpp b/src/CLI/usbguard-remove-user.cpp +index 89cc5ba..23fe05e 100644 +--- a/src/CLI/usbguard-remove-user.cpp ++++ b/src/CLI/usbguard-remove-user.cpp +@@ -16,11 +16,18 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-remove-user.hpp" +-#include +-#include ++ ++#include "usbguard/USBGuard.hpp" ++#include "usbguard/IPCServer.hpp" ++ + #include ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-remove-user.hpp b/src/CLI/usbguard-remove-user.hpp +index d32a0a6..ce2b4db 100644 +--- a/src/CLI/usbguard-remove-user.hpp ++++ b/src/CLI/usbguard-remove-user.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_remove_user(int argc, char **argv); +diff --git a/src/CLI/usbguard-rule-parser.cpp b/src/CLI/usbguard-rule-parser.cpp +index 6a85b15..cdb880a 100644 +--- a/src/CLI/usbguard-rule-parser.cpp ++++ b/src/CLI/usbguard-rule-parser.cpp +@@ -16,15 +16,21 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Rule.hpp" ++#include "usbguard/RuleParser.hpp" ++ + #include + #ifndef _GNU_SOURCE + # define _GNU_SOURCE + #endif + #include + #include ++ + #include +-#include "Rule.hpp" +-#include "RuleParser.hpp" + + static const char *options_short = "hft"; + +diff --git a/src/CLI/usbguard-set-parameter.cpp b/src/CLI/usbguard-set-parameter.cpp +index c3a141c..9df5ce6 100644 +--- a/src/CLI/usbguard-set-parameter.cpp ++++ b/src/CLI/usbguard-set-parameter.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-set-parameter.hpp" + +-#include ++#include "usbguard/IPCClient.hpp" ++ + #include + + namespace usbguard +diff --git a/src/CLI/usbguard-set-parameter.hpp b/src/CLI/usbguard-set-parameter.hpp +index d3c238c..116f400 100644 +--- a/src/CLI/usbguard-set-parameter.hpp ++++ b/src/CLI/usbguard-set-parameter.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_set_parameter(int argc, char **argv); +diff --git a/src/CLI/usbguard-watch.cpp b/src/CLI/usbguard-watch.cpp +index bd1cb0d..da333f3 100644 +--- a/src/CLI/usbguard-watch.cpp ++++ b/src/CLI/usbguard-watch.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "usbguard.hpp" + #include "usbguard-watch.hpp" + +diff --git a/src/CLI/usbguard-watch.hpp b/src/CLI/usbguard-watch.hpp +index 1be98ef..f538715 100644 +--- a/src/CLI/usbguard-watch.hpp ++++ b/src/CLI/usbguard-watch.hpp +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + namespace usbguard + { + int usbguard_watch(int argc, char **argv); +diff --git a/src/CLI/usbguard.cpp b/src/CLI/usbguard.cpp +index faf1a5d..77c5497 100644 +--- a/src/CLI/usbguard.cpp ++++ b/src/CLI/usbguard.cpp +@@ -16,11 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif ++ ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ + #include + #include +-#include +-#include + + #ifndef _GNU_SOURCE + # define _GNU_SOURCE +diff --git a/src/CLI/usbguard.hpp b/src/CLI/usbguard.hpp +index 9688c3d..dace3e4 100644 +--- a/src/CLI/usbguard.hpp ++++ b/src/CLI/usbguard.hpp +@@ -16,12 +16,17 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Logger.hpp" ++ + #include + #include + #include + +-#include "Logger.hpp" +- + namespace usbguard + { + extern const char *usbguard_arg0; +diff --git a/src/Common/ByteOrder.hpp b/src/Common/ByteOrder.hpp +index c7a4650..7f2e88d 100644 +--- a/src/Common/ByteOrder.hpp ++++ b/src/Common/ByteOrder.hpp +@@ -17,6 +17,10 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include + #include + +diff --git a/src/Common/CCBQueue.hpp b/src/Common/CCBQueue.hpp +deleted file mode 100644 +index 1686991..0000000 +--- a/src/Common/CCBQueue.hpp ++++ /dev/null +@@ -1,256 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#ifndef CCBQUEUE_HPP +-#define CCBQUEUE_HPP +- +-#include +-#include +-#include +- +-#ifndef CCBQUEUE_STATE_BITS +-# define CCBQUEUE_STATE_BITS 32 +-#endif +- +-namespace CCBQueueOpt +-{ +- enum BlockingMethod { +- NoBlocking, +- Spinlock, +- Yield, +- ConstSleep, +- AdaptiveSleep +- }; +-} +- +-template(nullptr)> +-class CCBQueue +-{ +-public: +-#if CCBQUEUE_STATE_BITS == 64 +- typedef uint32_t index_type; +- typedef uint32_t count_type; +- typedef uint64_t state_type; +- const index_type invalid_index = UINT32_MAX; +- const count_type count_type_max = UINT32_MAX; +-#elif CCBQUEUE_STATE_BITS == 32 +- typedef uint16_t index_type; +- typedef uint16_t count_type; +- typedef uint32_t state_type; +- const index_type invalid_index = UINT16_MAX; +- const count_type count_type_max = UINT16_MAX; +-#elif CCBQUEUE_STATE_BITS == 16 +- typedef uint8_t index_type; +- typedef uint8_t count_type; +- typedef uint16_t state_type; +- const index_type invalid_index = UINT8_MAX; +- const count_type count_type_max = UINT8_MAX; +-#else +-# error "Invalid CCBQUEUE_STATE_BITS value. Must be one of: 64, 32, 16." +-#endif +-private: +- union State { +- struct { +- index_type begin; +- count_type count; +- }; +- state_type unified; +- }; +- +- uint8_t* _queue_mem; +- const size_t _item_size; +- const count_type _capacity; +- +- State _r_state; // readability state +- State _w_state; // writability state +- +-protected: +- T* indexToPointer(index_type index) const __attribute__((/*returns_nonnull,*/ nothrow, hot)) +- { +- return (T *)(((uintptr_t)_queue_mem) + (_item_size * index)); +- } +- +- index_type pointerToIndex(const T* pointer) const __attribute__((nonnull, nothrow, hot)) +- { +- return (index_type)((((uintptr_t)pointer) - ((uintptr_t)_queue_mem)) / _item_size); +- } +- +- // Modifies write state (++count) +- index_type acquireFreeIndex() __attribute__((nothrow)) +- { +- State w_state_old, w_state_new; +- do { +- // Read the current state +- w_state_old.unified = _w_state.unified; +- // Check whether there's scape for a new item +- if (w_state_old.count >= _capacity) { +- // No free index +- return invalid_index; +- } +- // Create a new state +- w_state_new.unified = w_state_old.unified; +- ++w_state_new.count; +- // +- // Try to atomically update the state, repeat the +- // whole process if it fails +- // +- } while(!__sync_bool_compare_and_swap(&_w_state.unified, +- w_state_old.unified, +- w_state_new.unified)); +- +- return ((w_state_old.begin + w_state_old.count) % _capacity); +- } +- +- // Modifies read state (++begin, --count) +- index_type acquireReadIndex() __attribute__((nothrow)) +- { +- State r_state_old, r_state_new; +- do { +- // Read the current state +- r_state_old.unified = _r_state.unified; +- // Check whether there's something to read +- if (r_state_old.count == 0) { +- return invalid_index; +- } +- // Create a new state +- r_state_new.unified = r_state_old.unified; +- --r_state_new.count; +- // Wrap the .begin index if needed +- if (++r_state_new.begin == _capacity) { +- r_state_new.begin = 0; +- } +- // +- // Try to atomically update the state, repeat the +- // while process if it fails +- // +- } while(!__sync_bool_compare_and_swap(&_r_state.unified, +- r_state_old.unified, +- r_state_new.unified)); +- return r_state_old.begin; +- } +- +- index_type nextEnqueueIndex() __attribute__((nothrow)) +- { +- State r_state; +- r_state.unified = __sync_add_and_fetch(&_r_state.unified, 0); +- return ((r_state.begin + r_state.count) % _capacity); +- } +- +- index_type nextReleaseIndex() __attribute__((nothrow)) +- { +- State w_state; +- w_state.unified = __sync_add_and_fetch(&_w_state.unified, 0); +- return w_state.begin; +- } +- +-public: +- CCBQueue(uint32_t max_memory_MiB) +- : _item_size(sizeof(T)), +- _capacity(((max_memory_MiB*1<<20)/sizeof(T))>count_type_max? +- count_type_max:(max_memory_MiB*1<<20)/sizeof(T)) +- { +- _queue_mem = new uint8_t[_capacity * _item_size]; +- _w_state.unified = 0; +- _r_state.unified = 0; +- } +- +- ~CCBQueue() +- { +- delete [] _queue_mem; +- } +- +- T* acquire() __attribute__((nothrow)) +- { +- const index_type free_index = acquireFreeIndex(); +- if (free_index == invalid_index) { +- /* No free space */ +- return nullptr; +- } +- else { +- return indexToPointer(free_index); +- } +- } +- +- // Modifies read state (++count) +- bool enqueue(const T* item) __attribute__((nonnull, nothrow)) +- { +- // Check that we can enqueue the item +- if (pointerToIndex(item) != nextEnqueueIndex()) { +- return false; +- } +- // Enqueue the item / Update readability state +- State r_state_old, r_state_new; +- +- do { +- r_state_old.unified = _r_state.unified; +- r_state_new.unified = r_state_old.unified; +- ++r_state_new.count; +- } while(!__sync_bool_compare_and_swap(&_r_state.unified, +- r_state_old.unified, +- r_state_new.unified)); +- return true; +- } +- +- const T* dequeue() __attribute__((nothrow)) +- { +- const index_type index = acquireReadIndex(); +- if (index == invalid_index) { +- return nullptr; +- } +- else { +- return indexToPointer(index); +- } +- } +- +- // Modifies write state (++begin, --count) +- bool release(const T* item) __attribute__((nonnull, nothrow)) +- { +- // Check that we can release the item +- if (pointerToIndex(item) != nextReleaseIndex()) { +- return false; +- } +- +- State w_state_old, w_state_new; +- +- do { +- // Read the current state +- w_state_old.unified = _w_state.unified; +- // Create an updated state +- w_state_new.unified = w_state_old.unified; +- --w_state_new.count; +- if (++w_state_new.begin == _capacity) { +- w_state_new.begin = 0; +- } +- // Atomically update the state +- } while(!__sync_bool_compare_and_swap(&_w_state.unified, +- w_state_old.unified, +- w_state_new.unified)); +- return true; +- } +- +- // Returns number of queued items +- count_type count() const +- { +- return _r_state.count; +- } +- +-}; +- +-#endif /* CCBQUEUE_HPP */ +diff --git a/src/Common/FDInputStream.hpp b/src/Common/FDInputStream.hpp +index 5ab319b..4d6a92c 100644 +--- a/src/Common/FDInputStream.hpp ++++ b/src/Common/FDInputStream.hpp +@@ -17,8 +17,10 @@ + // Authors: Daniel Kopecek + // + #pragma once +- ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif ++ + #include + #include + #include +diff --git a/src/Common/Thread.hpp b/src/Common/Thread.hpp +index b413b4a..04730b8 100644 +--- a/src/Common/Thread.hpp ++++ b/src/Common/Thread.hpp +@@ -17,8 +17,11 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + +-#include "Logger.hpp" ++#include "usbguard/Logger.hpp" + + #include + #include +diff --git a/src/Common/Utility.cpp b/src/Common/Utility.cpp +index 2867ccf..f84d2a8 100644 +--- a/src/Common/Utility.cpp ++++ b/src/Common/Utility.cpp +@@ -16,23 +16,28 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include ++#endif ++ ++#include "usbguard/Logger.hpp" ++ + #include "Common/Utility.hpp" + ++#include ++#include ++ ++#include ++#include ++#include + #include +-#include +-#include +-#include + #include +-#include ++#include + #include ++#include ++#include + #include +-#include +-#include +-#include +-#include +-#include ++#include + + namespace usbguard + { +@@ -77,7 +82,7 @@ namespace usbguard + return; + } + +- bool writePID(const String& filepath) ++ bool writePID(const std::string& filepath) + { + std::ofstream pidstream(filepath, std::ios_base::trunc); + if (!pidstream) { +@@ -87,7 +92,7 @@ namespace usbguard + return true; + } + +- static void runCommandExecChild(const String& path, const std::vector& args) ++ static void runCommandExecChild(const std::string& path, const std::vector& args) + { + struct rlimit rlim; + +@@ -147,20 +152,20 @@ namespace usbguard + + int runCommand(const char * const path, const char * const arg1, const int timeout_secs) + { +- std::vector args; ++ std::vector args; + args.push_back(arg1); + return runCommand(path, args, timeout_secs); + } + + int runCommand(const char * const path, const char * const arg1, const char * const arg2, const int timeout_secs) + { +- std::vector args; ++ std::vector args; + args.push_back(arg1); + args.push_back(arg2); + return runCommand(path, args, timeout_secs); + } + +- int runCommand(const String& path, const std::vector& args, const int timeout_secs) ++ int runCommand(const std::string& path, const std::vector& args, const int timeout_secs) + { + int retval = 0, status = 0; + bool timedout = false; +@@ -218,18 +223,18 @@ namespace usbguard + return retval; + } + +- String filenameFromPath(const String& filepath, const bool include_extension) ++ std::string filenameFromPath(const std::string& filepath, const bool include_extension) + { +- const String directory_separator = "/"; +- StringVector path_tokens; ++ const std::string directory_separator = "/"; ++ std::vector path_tokens; + + tokenizeString(filepath, path_tokens, directory_separator); + + if (path_tokens.size() == 0) { +- return String(); ++ return std::string(); + } + +- const String& filename = path_tokens.back(); ++ const std::string& filename = path_tokens.back(); + + if (include_extension) { + return filename; +@@ -240,10 +245,10 @@ namespace usbguard + return filename.substr(0, substr_to); + } + +- String parentPath(const String& path) ++ std::string parentPath(const std::string& path) + { +- const String directory_separator = "/"; +- String parent_path(path); ++ const std::string directory_separator = "/"; ++ std::string parent_path(path); + + // find first not '/' (from end) + // find first '/' (from end) +@@ -256,7 +261,7 @@ namespace usbguard + * Whole path consists only of '/'. + */ + if (reverse_start_pos == std::string::npos) { +- return String(); ++ return std::string(); + } + + reverse_start_pos = \ +@@ -266,7 +271,7 @@ namespace usbguard + * No directory separator in the rest of the path. + */ + if (reverse_start_pos == std::string::npos) { +- return String(); ++ return std::string(); + } + + reverse_start_pos = \ +@@ -277,41 +282,41 @@ namespace usbguard + * /foo/bar => /foo + * /foo/bar/ => /foo + * /foo/bar// => /foo +- * /foo => String() +- * /foo/ => String() +- * / => String() +- * //foo => String() ++ * /foo => std::string() ++ * /foo/ => std::string() ++ * / => std::string() ++ * //foo => std::string() + * + */ + if (reverse_start_pos == std::string::npos) { +- return String(); ++ return std::string(); + } + + return path.substr(0, reverse_start_pos + 1); + } + +- String trimRight(const String& s, const String& delimiters) ++ std::string trimRight(const std::string& s, const std::string& delimiters) + { + const size_t substr_to = s.find_last_not_of(delimiters); + if (substr_to != std::string::npos) { + return s.substr(0, substr_to + 1); + } + else { +- return String(); ++ return std::string(); + } + } + +- String trimLeft(const String& s, const String& delimiters) ++ std::string trimLeft(const std::string& s, const std::string& delimiters) + { + const size_t substr_from = s.find_first_not_of(delimiters); +- if (substr_from == String::npos) { ++ if (substr_from == std::string::npos) { + return s; + } else { + return s.substr(substr_from); + } + } + +- String trim(const String& s, const String& delimiters) ++ std::string trim(const std::string& s, const std::string& delimiters) + { + return trimRight(trimLeft(s, delimiters), delimiters); + } +@@ -323,20 +328,20 @@ namespace usbguard + * an unsigned int. + */ + template<> +- String numberToString(const uint8_t number, const String& prefix, const int base, const int align, const char align_char) ++ std::string numberToString(const uint8_t number, const std::string& prefix, const int base, const int align, const char align_char) + { + const uint16_t n = static_cast(number); + return numberToString(n, prefix, base, align, align_char); + } + + template<> +- uint8_t stringToNumber(const String& s, const int base) ++ uint8_t stringToNumber(const std::string& s, const int base) + { + const unsigned int num = stringToNumber(s, base); + return (uint8_t)num; + } + +- bool isNumericString(const String& s) ++ bool isNumericString(const std::string& s) + { + for (int c : s) { + if (!isdigit(c)) { +@@ -346,10 +351,10 @@ namespace usbguard + return true; + } + +- int loadFiles(const String& directory, +- std::function filter, +- std::function loader, +- std::function&, const std::pair&)> sorter) ++ int loadFiles(const std::string& directory, ++ std::function filter, ++ std::function loader, ++ std::function&, const std::pair&)> sorter) + { + DIR* dirobj = opendir(directory.c_str()); + int retval = 0; +@@ -358,7 +363,7 @@ namespace usbguard + throw ErrnoException("loadFiles", directory, errno); + } + try { +- std::vector> loadpaths; ++ std::vector> loadpaths; + struct dirent *entry_ptr = nullptr; + /* + * readdir usage note: We rely on the fact that readdir should be thread-safe +@@ -367,14 +372,14 @@ namespace usbguard + * readdir_r, is deprecated in newer versions of glibc. + */ + while((entry_ptr = readdir(dirobj)) != nullptr) { +- const String filename(entry_ptr->d_name); ++ const std::string filename(entry_ptr->d_name); + + if (filename == "." || filename == "..") { + continue; + } + +- String fullpath = directory + "/" + filename; +- String loadpath = filter(fullpath, entry_ptr); ++ std::string fullpath = directory + "/" + filename; ++ std::string loadpath = filter(fullpath, entry_ptr); + + if (!loadpath.empty()) { + loadpaths.emplace_back(std::make_pair(std::move(loadpath),std::move(fullpath))); +@@ -400,7 +405,7 @@ namespace usbguard + return retval; + } + +- String removePrefix(const String& prefix, const String& value) ++ std::string removePrefix(const std::string& prefix, const std::string& value) + { + if (value.compare(0, prefix.size(), prefix) == 0) { + return value.substr(prefix.size()); +@@ -410,7 +415,7 @@ namespace usbguard + } + } + +- String symlinkPath(const String& linkpath, struct stat *st_user) ++ std::string symlinkPath(const std::string& linkpath, struct stat *st_user) + { + struct stat st = { }; + struct stat *st_ptr = nullptr; +@@ -440,7 +445,7 @@ namespace usbguard + throw Exception("symlinkPath", linkpath, "symlink value size out of range"); + } + +- String buffer(st_ptr->st_size, 0); ++ std::string buffer(st_ptr->st_size, 0); + const ssize_t link_size = readlink(linkpath.c_str(), &buffer[0], buffer.capacity()); + + if (link_size <= 0 || link_size > st_ptr->st_size) { +diff --git a/src/Common/Utility.hpp b/src/Common/Utility.hpp +index 1ca922b..f722b22 100644 +--- a/src/Common/Utility.hpp ++++ b/src/Common/Utility.hpp +@@ -17,20 +17,26 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "Exception.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Exception.hpp" ++#include "usbguard/Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++#include + #include ++#include + #include +-#include +-#include +-#include +-#include ++ + #include +-#include +-#include +-#include + #include +-#include ++#include ++#include + + namespace usbguard + { +@@ -51,7 +57,7 @@ namespace usbguard + * Writes the current PID to a file at filepath. + * Returns true on success, otherwise returns false. + */ +- bool writePID(const String& filepath); ++ bool writePID(const std::string& filepath); + + /** + * Wrappers for the __builtin_expect function. +@@ -66,7 +72,7 @@ namespace usbguard + + int runCommand(const char *path, const char *arg1, int timeout_secs = 10); + int runCommand(const char *path, const char *arg1, const char *arg2, int timeout_secs = 10); +- int runCommand(const String& path, const std::vector& args = std::vector(), int timeout_secs = 10); ++ int runCommand(const std::string& path, const std::vector& args = std::vector(), int timeout_secs = 10); + + /** + * Tokenize a std::string compatible type using delimiters specified in a string. +@@ -105,15 +111,15 @@ namespace usbguard + * representation. + */ + template +- String numberToString(const T number, const String& prefix = String(), const int base = 10, const int align = -1, const char align_char = ' ') ++ std::string numberToString(const T number, const std::string& prefix = std::string(), const int base = 10, const int align = -1, const char align_char = ' ') + { + std::ostringstream ss; + + ss << std::setbase(base); + ss << number; + +- const String number_string = ss.str(); +- String result; ++ const std::string number_string = ss.str(); ++ std::string result; + result.append(prefix); + + if (align > 0 && number_string.size() < (size_t)align) { +@@ -128,14 +134,14 @@ namespace usbguard + } + + template<> +- String numberToString(const uint8_t number, const String& prefix, const int base, const int align, const char align_char); ++ std::string numberToString(const uint8_t number, const std::string& prefix, const int base, const int align, const char align_char); + + /** + * Convert a string representation of a number + * to a number of type T. + */ + template +- T stringToNumber(const String& s, const int base = 10) ++ T stringToNumber(const std::string& s, const int base = 10) + { + std::istringstream ss(s); + T num; +@@ -144,9 +150,9 @@ namespace usbguard + } + + template<> +- uint8_t stringToNumber(const String& s, const int base); ++ uint8_t stringToNumber(const std::string& s, const int base); + +- bool isNumericString(const String& s); ++ bool isNumericString(const std::string& s); + + /** + * Return the filename part of a path. If include_extension is set to +@@ -159,48 +165,48 @@ namespace usbguard + * "/foo/bar/baz.woo.txt" (include_extension=false) => "baz.woo" + * "foo.txt" (include_extension=true) => "foo.txt" + */ +- String filenameFromPath(const String& filepath, bool include_extension = false); ++ std::string filenameFromPath(const std::string& filepath, bool include_extension = false); + + /** + * Return the parent path part of a path. + */ +- String parentPath(const String& path); ++ std::string parentPath(const std::string& path); + + /** + * Remove whitespace characters from the right side of a string. + */ +- String trimRight(const String& s, const String& delimiters = " \f\n\r\t\v"); ++ std::string trimRight(const std::string& s, const std::string& delimiters = " \f\n\r\t\v"); + + /** + * Remove whitespace characters from the left side of a string. + */ +- String trimLeft(const String& s, const String& delimiters = " \f\n\r\t\v"); ++ std::string trimLeft(const std::string& s, const std::string& delimiters = " \f\n\r\t\v"); + + /** + * Remove whitespace characters from the left & right side of a string. + */ +- String trim(const String& s, const String& delimiters = " \f\n\r\t\v"); ++ std::string trim(const std::string& s, const std::string& delimiters = " \f\n\r\t\v"); + + /** +- * Call a void(*)(const String&) compatible method for every file in a directory ++ * Call a void(*)(const std::string&) compatible method for every file in a directory + * matching a regular expression. The function does not recursively descent into + * subdirectories. + */ +- int loadFiles(const String& directory, +- std::function filter, +- std::function loader, +- std::function&, const std::pair&)> sorter = \ +- [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); ++ int loadFiles(const std::string& directory, ++ std::function filter, ++ std::function loader, ++ std::function&, const std::pair&)> sorter = \ ++ [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + + /** + * Remove prefix from string. + */ +- String removePrefix(const String& prefix, const String& value); ++ std::string removePrefix(const std::string& prefix, const std::string& value); + + /** + * Read symlink destination. + */ +- String symlinkPath(const String& linkpath, struct stat *st_user = nullptr); ++ std::string symlinkPath(const std::string& linkpath, struct stat *st_user = nullptr); + + /* + * Restorer class +diff --git a/src/DBus/DBusBridge.cpp b/src/DBus/DBusBridge.cpp +index 7985304..02c6bbc 100644 +--- a/src/DBus/DBusBridge.cpp ++++ b/src/DBus/DBusBridge.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "DBusBridge.hpp" + + namespace usbguard +diff --git a/src/DBus/DBusBridge.hpp b/src/DBus/DBusBridge.hpp +index 2c15945..fe8a5ac 100644 +--- a/src/DBus/DBusBridge.hpp ++++ b/src/DBus/DBusBridge.hpp +@@ -17,14 +17,17 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/IPCClient.hpp" + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-register" + #include + #pragma clang diagnostic pop + +-#include "IPCClient.hpp" +- + namespace usbguard + { + class DBusBridge : public IPCClient +diff --git a/src/DBus/gdbus-server.cpp b/src/DBus/gdbus-server.cpp +index fee0329..8f596b8 100644 +--- a/src/DBus/gdbus-server.cpp ++++ b/src/DBus/gdbus-server.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp +index 4e93f91..b317c85 100644 +--- a/src/Daemon/Daemon.cpp ++++ b/src/Daemon/Daemon.cpp +@@ -16,15 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #include "Daemon.hpp" +-#include "Logger.hpp" + #include "Common/Utility.hpp" +-#include "IPCPrivate.hpp" +-#include "RulePrivate.hpp" +-#include "RuleParser.hpp" +-#include "Audit.hpp" ++ ++#include "usbguard/Logger.hpp" ++#include "usbguard/RuleParser.hpp" ++#include "usbguard/Audit.hpp" + + #include + #include +@@ -36,7 +37,6 @@ + #include + #include + #include +- + #include + #include + +@@ -47,7 +47,7 @@ namespace usbguard + * unknown setting is found in the config file, + * a warning message will be displayed. + */ +- static const StringVector G_config_known_names = { ++ static const std::vector G_config_known_names = { + "RuleFile", + "ImplicitPolicyTarget", + "PresentDevicePolicy", +@@ -62,7 +62,7 @@ namespace usbguard + "AuditFilePath" + }; + +- static const std::vector > device_policy_method_strings = { ++ static const std::vector > device_policy_method_strings = { + { "allow", Daemon::DevicePolicyMethod::Allow }, + { "block", Daemon::DevicePolicyMethod::Block }, + { "reject", Daemon::DevicePolicyMethod::Reject }, +@@ -70,7 +70,7 @@ namespace usbguard + { "apply-policy", Daemon::DevicePolicyMethod::ApplyPolicy } + }; + +- Daemon::DevicePolicyMethod Daemon::devicePolicyMethodFromString(const String& policy_string) ++ Daemon::DevicePolicyMethod Daemon::devicePolicyMethodFromString(const std::string& policy_string) + { + for (auto device_policy_method_string : device_policy_method_strings) { + if (device_policy_method_string.first == policy_string) { +@@ -119,14 +119,14 @@ namespace usbguard + _config.close(); + } + +- void Daemon::loadConfiguration(const String& path) ++ void Daemon::loadConfiguration(const std::string& path) + { + USBGUARD_LOG(Info) << "Loading configuration from " << path; + _config.open(path); + + /* RuleFile */ + if (_config.hasSettingValue("RuleFile")) { +- const String& rule_file = _config.getSettingValue("RuleFile"); ++ const std::string& rule_file = _config.getSettingValue("RuleFile"); + try { + loadRules(rule_file); + } +@@ -145,36 +145,36 @@ namespace usbguard + + /* ImplicitPolicyTarget */ + if (_config.hasSettingValue("ImplicitPolicyTarget")) { +- const String& target_string = _config.getSettingValue("ImplicitPolicyTarget"); ++ const std::string& target_string = _config.getSettingValue("ImplicitPolicyTarget"); + Rule::Target target = Rule::targetFromString(target_string); + setImplicitPolicyTarget(target); + } + + /* PresentDevicePolicy */ + if (_config.hasSettingValue("PresentDevicePolicy")) { +- const String& policy_string = _config.getSettingValue("PresentDevicePolicy"); ++ const std::string& policy_string = _config.getSettingValue("PresentDevicePolicy"); + DevicePolicyMethod policy = Daemon::devicePolicyMethodFromString(policy_string); + setPresentDevicePolicyMethod(policy); + } + + /* PresentControllerPolicy */ + if (_config.hasSettingValue("PresentControllerPolicy")) { +- const String& policy_string = _config.getSettingValue("PresentControllerPolicy"); ++ const std::string& policy_string = _config.getSettingValue("PresentControllerPolicy"); + DevicePolicyMethod policy = Daemon::devicePolicyMethodFromString(policy_string); + setPresentControllerPolicyMethod(policy); + } + + /* InsertedDevicePolicy */ + if (_config.hasSettingValue("InsertedDevicePolicy")) { +- const String& policy_string = _config.getSettingValue("InsertedDevicePolicy"); ++ const std::string& policy_string = _config.getSettingValue("InsertedDevicePolicy"); + DevicePolicyMethod policy = Daemon::devicePolicyMethodFromString(policy_string); + setInsertedDevicePolicyMethod(policy); + } + + /* IPCAllowedUsers */ + if (_config.hasSettingValue("IPCAllowedUsers")) { +- const String users_value = _config.getSettingValue("IPCAllowedUsers"); +- StringVector users; ++ const std::string users_value = _config.getSettingValue("IPCAllowedUsers"); ++ std::vector users; + tokenizeString(users_value, users, " ", /*trim_empty=*/true); + USBGUARD_LOG(Debug) << "Setting IPCAllowedUsers to { " << users_value << " }"; + +@@ -185,8 +185,8 @@ namespace usbguard + + /* IPCAllowedGroups */ + if (_config.hasSettingValue("IPCAllowedGroups")) { +- const String groups_value =_config.getSettingValue("IPCAllowedGroups"); +- StringVector groups; ++ const std::string groups_value =_config.getSettingValue("IPCAllowedGroups"); ++ std::vector groups; + tokenizeString(groups_value, groups, " ", /*trim_empty=*/true); + USBGUARD_LOG(Debug) << "Setting IPCAllowedGroups to { " << groups_value << " }"; + +@@ -197,7 +197,7 @@ namespace usbguard + + /* DeviceRulesWithPort */ + if (_config.hasSettingValue("DeviceRulesWithPort")) { +- const String value = _config.getSettingValue("DeviceRulesWithPort"); ++ const std::string value = _config.getSettingValue("DeviceRulesWithPort"); + USBGUARD_LOG(Debug) << "Setting DeviceRulesWithPort to " << value; + if (value == "true") { + _device_rules_with_port = true; +@@ -219,7 +219,7 @@ namespace usbguard + + /* RestoreControllerDeviceState */ + if (_config.hasSettingValue("RestoreControllerDeviceState")) { +- const String value = _config.getSettingValue("RestoreControllerDeviceState"); ++ const std::string value = _config.getSettingValue("RestoreControllerDeviceState"); + + if (value == "true") { + _restore_controller_device_state = true; +@@ -236,13 +236,13 @@ namespace usbguard + + /* IPCAccessControlFiles */ + if (_config.hasSettingValue("IPCAccessControlFiles")) { +- const String value = _config.getSettingValue("IPCAccessControlFiles"); ++ const std::string value = _config.getSettingValue("IPCAccessControlFiles"); + loadIPCAccessControlFiles(value); + } + + /* AuditFilePath */ + if (_config.hasSettingValue("AuditFilePath")) { +- const String value = _config.getSettingValue("AuditFilePath"); ++ const std::string value = _config.getSettingValue("AuditFilePath"); + USBGUARD_LOG(Debug) << "Setting AuditFilePath to " << value; + USBGUARD_LOGGER.setAuditFile(true, value); + } +@@ -250,40 +250,40 @@ namespace usbguard + USBGUARD_LOG(Info) << "Configuration loaded successfully."; + } + +- void Daemon::loadRules(const String& path) ++ void Daemon::loadRules(const std::string& path) + { + USBGUARD_LOG(Info) << "Loading permanent policy file " << path; + _ruleset.load(path); + } + +- void Daemon::loadIPCAccessControlFiles(const String& path) ++ void Daemon::loadIPCAccessControlFiles(const std::string& path) + { + USBGUARD_LOG(Info) << "Loading IPC access control files at " << path; + loadFiles(path, +- [](const String& path, const struct dirent * dir_entry) ++ [](const std::string& path, const struct dirent * dir_entry) + { + (void)dir_entry; + return filenameFromPath(path, /*include_extension=*/true); + } + , +- [this](const String& basename, const String& fullpath) ++ [this](const std::string& basename, const std::string& fullpath) + { + return loadIPCAccessControlFile(basename, fullpath); + }); + } + +- void Daemon::checkIPCAccessControlName(const String& name) ++ void Daemon::checkIPCAccessControlName(const std::string& name) + { + IPCServer::checkAccessControlName(name); + } + +- void Daemon::parseIPCAccessControlFilename(const String& basename, String * const ptr_user, String * const ptr_group) ++ void Daemon::parseIPCAccessControlFilename(const std::string& basename, std::string * const ptr_user, std::string * const ptr_group) + { + const auto ug_separator = basename.find_first_of(":"); + const bool has_group = ug_separator != std::string::npos; + +- const String user = basename.substr(0, ug_separator); +- const String group = has_group ? basename.substr(ug_separator + 1) : String(); ++ const std::string user = basename.substr(0, ug_separator); ++ const std::string group = has_group ? basename.substr(ug_separator + 1) : std::string(); + + checkIPCAccessControlName(user); + checkIPCAccessControlName(group); +@@ -292,12 +292,12 @@ namespace usbguard + *ptr_group = group; + } + +- bool Daemon::loadIPCAccessControlFile(const String& basename, const String& fullpath) ++ bool Daemon::loadIPCAccessControlFile(const std::string& basename, const std::string& fullpath) + { + USBGUARD_LOG(Info) << "Loading IPC access control file " << fullpath; + +- String user; +- String group; ++ std::string user; ++ std::string group; + IPCServer::AccessControl ac; + + try { +@@ -506,14 +506,14 @@ namespace usbguard + << " target=" << Rule::targetToString(target) + << " permanent=" << permanent; + +- Pointer device = _dm->getDevice(id); +- Pointer rule; ++ std::shared_ptr device = _dm->getDevice(id); ++ std::shared_ptr rule; + + if (permanent) { + rule = upsertDeviceRule(id, target); + } + else { +- rule = makePointer(); ++ rule = std::make_shared(); + rule->setTarget(target); + } + +@@ -524,14 +524,14 @@ namespace usbguard + return rule->getRuleID(); + } + +- void Daemon::dmHookDeviceEvent(DeviceManager::EventType event, Pointer device) ++ void Daemon::dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) + { + USBGUARD_LOG(Trace) << "event=" << DeviceManager::eventTypeToString(event) + << " device_ptr=" << device.get(); + + auto audit_event = Audit::deviceEvent(_audit_identity, device, event); + +- Pointer device_rule = \ ++ std::shared_ptr device_rule = \ + device->getDeviceRule(/*with_port*/true, + /*with_parent_hash=*/true); + +@@ -542,7 +542,7 @@ namespace usbguard + + audit_event.success(); + +- Pointer policy_rule = nullptr; ++ std::shared_ptr policy_rule = nullptr; + + switch(event) { + case DeviceManager::EventType::Present: +@@ -562,12 +562,12 @@ namespace usbguard + dmApplyDevicePolicy(device, policy_rule); + } + +- void Daemon::dmHookDeviceException(const String& message) ++ void Daemon::dmHookDeviceException(const std::string& message) + { + USBGUARD_LOG(Warning) << message; + } + +- void Daemon::dmApplyDevicePolicy(Pointer device, Pointer matched_rule) ++ void Daemon::dmApplyDevicePolicy(std::shared_ptr device, std::shared_ptr matched_rule) + { + USBGUARD_LOG(Trace) << "device_ptr=" << device.get() + << " matched_rule_ptr=" << matched_rule.get(); +@@ -576,7 +576,7 @@ namespace usbguard + device, device->getTarget(), matched_rule->getTarget()); + + const Rule::Target target_old = device->getTarget(); +- Pointer device_post = \ ++ std::shared_ptr device_post = \ + _dm->applyDevicePolicy(device->getID(), + matched_rule->getTarget()); + +@@ -592,7 +592,7 @@ namespace usbguard + USBGUARD_LOG(Debug) << "Implicit rule matched"; + } + +- Pointer device_rule = \ ++ std::shared_ptr device_rule = \ + device_post->getDeviceRule(/*with_port=*/true, + /*with_parent_hash=*/true); + +@@ -607,17 +607,17 @@ namespace usbguard + audit_event.success(); + } + +- Pointer Daemon::getInsertedDevicePolicyRule(Pointer device) ++ std::shared_ptr Daemon::getInsertedDevicePolicyRule(std::shared_ptr device) + { + USBGUARD_LOG(Trace) << "device_ptr=" << device.get(); + +- Pointer device_rule = \ ++ std::shared_ptr device_rule = \ + device->getDeviceRule(/*with_port=*/true, + /*with_parent_hash=*/true, + /*match_rule=*/true); + + Rule::Target target = Rule::Target::Invalid; +- Pointer policy_rule; ++ std::shared_ptr policy_rule; + const DevicePolicyMethod policy_method = _inserted_device_policy_method; + + switch (policy_method) { +@@ -637,7 +637,7 @@ namespace usbguard + } + + if (policy_rule == nullptr) { +- policy_rule = makePointer(); ++ policy_rule = std::make_shared(); + policy_rule->setTarget(target); + policy_rule->setRuleID(Rule::RootID); + } +@@ -645,11 +645,11 @@ namespace usbguard + return policy_rule; + } + +- Pointer Daemon::getPresentDevicePolicyRule(Pointer device) ++ std::shared_ptr Daemon::getPresentDevicePolicyRule(std::shared_ptr device) + { + USBGUARD_LOG(Trace) << "entry: device_ptr=" << device.get(); + +- Pointer device_rule = \ ++ std::shared_ptr device_rule = \ + device->getDeviceRule(/*with_port=*/true, + /*with_parent_hash=*/true, + /*match_rule=*/true); +@@ -661,7 +661,7 @@ namespace usbguard + device->isController() ? _present_controller_policy_method : _present_device_policy_method; + + Rule::Target target = Rule::Target::Invalid; +- Pointer matched_rule = nullptr; ++ std::shared_ptr matched_rule = nullptr; + + switch (policy_method) { + case DevicePolicyMethod::Allow: +@@ -685,7 +685,7 @@ namespace usbguard + } + + if (matched_rule == nullptr) { +- matched_rule = makePointer(); ++ matched_rule = std::make_shared(); + matched_rule->setTarget(target); + matched_rule->setRuleID(Rule::ImplicitID); + } +@@ -719,13 +719,13 @@ namespace usbguard + return device_rules; + } + +- Pointer Daemon::upsertDeviceRule(uint32_t id, Rule::Target target) ++ std::shared_ptr Daemon::upsertDeviceRule(uint32_t id, Rule::Target target) + { + USBGUARD_LOG(Trace) << "entry:" + << "id=" << id + << "target=" << Rule::targetToString(target); + +- Pointer device = _dm->getDevice(id); ++ std::shared_ptr device = _dm->getDevice(id); + + bool with_port = true && _device_rules_with_port; + bool with_parent_hash = true; +@@ -766,15 +766,15 @@ namespace usbguard + } + + /* Generate a match rule for upsert */ +- Pointer match_rule = device->getDeviceRule(false, false, /*match_rule=*/true); +- const String match_spec = match_rule->toString(); ++ std::shared_ptr match_rule = device->getDeviceRule(false, false, /*match_rule=*/true); ++ const std::string match_spec = match_rule->toString(); + + USBGUARD_LOG(Debug) << "match_spec=" << match_spec; + + /* Generate new device rule */ +- Pointer device_rule = device->getDeviceRule(with_port, with_parent_hash); ++ std::shared_ptr device_rule = device->getDeviceRule(with_port, with_parent_hash); + device_rule->setTarget(target); +- const String rule_spec = device_rule->toString(); ++ const std::string rule_spec = device_rule->toString(); + + USBGUARD_LOG(Debug) << "rule_spec=" << rule_spec; + +@@ -794,7 +794,7 @@ namespace usbguard + IPCServer::addAllowedUID(uid, ac); + } + +- void Daemon::addIPCAllowedUID(const String& uid_string, const IPCServer::AccessControl& ac) ++ void Daemon::addIPCAllowedUID(const std::string& uid_string, const IPCServer::AccessControl& ac) + { + addIPCAllowedUID(stringToNumber(uid_string), ac); + } +@@ -805,12 +805,12 @@ namespace usbguard + IPCServer::addAllowedGID(gid, ac); + } + +- void Daemon::addIPCAllowedGID(const String& gid_string, const IPCServer::AccessControl& ac) ++ void Daemon::addIPCAllowedGID(const std::string& gid_string, const IPCServer::AccessControl& ac) + { + addIPCAllowedGID(stringToNumber(gid_string), ac); + } + +- void Daemon::addIPCAllowedUser(const String& user, const IPCServer::AccessControl& ac) ++ void Daemon::addIPCAllowedUser(const std::string& user, const IPCServer::AccessControl& ac) + { + USBGUARD_LOG(Trace) << "user=" << user; + +@@ -822,7 +822,7 @@ namespace usbguard + } + } + +- void Daemon::addIPCAllowedGroup(const String& group, const IPCServer::AccessControl& ac) ++ void Daemon::addIPCAllowedGroup(const std::string& group, const IPCServer::AccessControl& ac) + { + USBGUARD_LOG(Trace) << "group=" << group; + +diff --git a/src/Daemon/Daemon.hpp b/src/Daemon/Daemon.hpp +index d6081d3..cfd02d9 100644 +--- a/src/Daemon/Daemon.hpp ++++ b/src/Daemon/Daemon.hpp +@@ -17,19 +17,22 @@ + // Authors: Daniel Kopecek + // + #pragma once +- +-#include "Typedefs.hpp" +-#include "ConfigFile.hpp" +-#include "IPCServer.hpp" +-#include "RuleSet.hpp" +-#include "Rule.hpp" +-#include "Device.hpp" +-#include "DeviceManager.hpp" +-#include "DeviceManagerHooks.hpp" +-#include "Audit.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "Common/Thread.hpp" + ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/ConfigFile.hpp" ++#include "usbguard/IPCServer.hpp" ++#include "usbguard/RuleSet.hpp" ++#include "usbguard/Rule.hpp" ++#include "usbguard/Device.hpp" ++#include "usbguard/DeviceManager.hpp" ++#include "usbguard/DeviceManagerHooks.hpp" ++#include "usbguard/Audit.hpp" ++ + #include + #include + #include +@@ -47,18 +50,18 @@ namespace usbguard + ApplyPolicy + }; + +- static DevicePolicyMethod devicePolicyMethodFromString(const String& policy_string); ++ static DevicePolicyMethod devicePolicyMethodFromString(const std::string& policy_string); + static const std::string devicePolicyMethodToString(DevicePolicyMethod policy); + + Daemon(); + ~Daemon(); + +- void loadConfiguration(const String& path); +- void loadRules(const String& path); +- void loadIPCAccessControlFiles(const String& path); +- bool loadIPCAccessControlFile(const String& basename, const String& fullpath); +- void checkIPCAccessControlName(const String& basename); +- void parseIPCAccessControlFilename(const String& basename, String * const ptr_user, String * const ptr_group); ++ void loadConfiguration(const std::string& path); ++ void loadRules(const std::string& path); ++ void loadIPCAccessControlFiles(const std::string& path); ++ bool loadIPCAccessControlFile(const std::string& basename, const std::string& fullpath); ++ void checkIPCAccessControlName(const std::string& basename); ++ void parseIPCAccessControlFilename(const std::string& basename, std::string * const ptr_user, std::string * const ptr_group); + + void setImplicitPolicyTarget(Rule::Target target); + void setPresentDevicePolicyMethod(DevicePolicyMethod policy); +@@ -85,32 +88,32 @@ namespace usbguard + const std::vector listDevices(const std::string& query) override; + + /* Device manager hooks */ +- void dmHookDeviceEvent(DeviceManager::EventType event, Pointer device) override; ++ void dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) override; + uint32_t dmHookAssignID() override; +- void dmHookDeviceException(const String& message) override; ++ void dmHookDeviceException(const std::string& message) override; + + #define USBGUARD_IPCSERVER_DEFAULT_AC \ + IPCServer::AccessControl(IPCServer::AccessControl::Section::ALL, IPCServer::AccessControl::Privilege::ALL) + + void addIPCAllowedUID(uid_t uid, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); +- void addIPCAllowedUID(const String& uid_string, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); ++ void addIPCAllowedUID(const std::string& uid_string, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); + void addIPCAllowedGID(gid_t gid, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); +- void addIPCAllowedGID(const String& gid_string, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); +- void addIPCAllowedUser(const String& user, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); +- void addIPCAllowedGroup(const String& group, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); ++ void addIPCAllowedGID(const std::string& gid_string, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); ++ void addIPCAllowedUser(const std::string& user, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); ++ void addIPCAllowedGroup(const std::string& group, const IPCServer::AccessControl& ac = USBGUARD_IPCSERVER_DEFAULT_AC); + + private: +- void dmApplyDevicePolicy(Pointer device, Pointer matched_rule); +- Pointer getInsertedDevicePolicyRule(Pointer device); +- Pointer getPresentDevicePolicyRule(Pointer device); ++ void dmApplyDevicePolicy(std::shared_ptr device, std::shared_ptr matched_rule); ++ std::shared_ptr getInsertedDevicePolicyRule(std::shared_ptr device); ++ std::shared_ptr getPresentDevicePolicyRule(std::shared_ptr device); + +- Pointer upsertDeviceRule(uint32_t id, Rule::Target target); ++ std::shared_ptr upsertDeviceRule(uint32_t id, Rule::Target target); + + ConfigFile _config; + RuleSet _ruleset; + +- String _device_manager_backend; +- Pointer _dm; ++ std::string _device_manager_backend; ++ std::shared_ptr _dm; + + std::atomic _implicit_policy_target; + std::atomic _present_device_policy_method; +diff --git a/src/Daemon/Exceptions.hpp b/src/Daemon/Exceptions.hpp +deleted file mode 100644 +index 79fa499..0000000 +--- a/src/Daemon/Exceptions.hpp ++++ /dev/null +@@ -1,77 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#ifndef USBFW_EXCEPTIONS_HPP +-#define USBFW_EXCEPTIONS_HPP +-#include +- +-#include +- +-namespace usbguard +-{ +- /** +- * Exception class representing an error +- * in configuration. FirewallD has several +- * sources of configuration data. +- * 1) the main configuration file +- * 2) the XML definition files for zones, services, icmptypes +- */ +- class ConfigurationError : public std::runtime_error +- { +- public: +- ConfigurationError(const std::string& source, const std::string& message, size_t line = 0) +- : std::runtime_error("Configuration error"), +- _source(source), +- _message(message), +- _line(line) +- {} +- +- const std::string source() const { return _source; } +- size_t line() const { return _line; } +- const std::string message() const { return _message; } +- +- private: +- const std::string _source; // configuration file specifier +- const std::string _message; +- size_t _line; // error line or 0 if unknown/unavailable +- }; +- +- /** +- * Exception class representin an error +- * in the firewall abstraction layer. +- */ +- class FirewallError : public std::runtime_error +- { +- public: +- FirewallError(const String& name, const String& message = String()) +- : std::runtime_error("Firewall error"), +- _name(name), +- _message(message) +- {} +- +- const String& name() const { return _name; } +- const String& message() const { return _message; } +- +- private: +- const String _name; +- const String _message; +- }; +- +-} /* namespace usbguard */ +- +-#endif /* USBFW_EXCEPTIONS_HPP */ +diff --git a/src/Daemon/Seccomp.c b/src/Daemon/Seccomp.c +index 29eab3a..9d727a8 100644 +--- a/src/Daemon/Seccomp.c ++++ b/src/Daemon/Seccomp.c +@@ -16,7 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #include "Seccomp.h" + +@@ -169,3 +171,5 @@ bool setupSeccompWhitelist(void) + return false; + } + #endif ++ ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/Daemon/Seccomp.h b/src/Daemon/Seccomp.h +index 09b9f35..2e9389f 100644 +--- a/src/Daemon/Seccomp.h ++++ b/src/Daemon/Seccomp.h +@@ -16,6 +16,11 @@ + // + // Authors: Daniel Kopecek + // ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include + + #ifdef __cplusplus +@@ -27,3 +32,5 @@ bool setupSeccompWhitelist(void); + #ifdef __cplusplus + } + #endif ++ ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/Daemon/main.cpp b/src/Daemon/main.cpp +index 73c49b3..869c2e2 100644 +--- a/src/Daemon/main.cpp ++++ b/src/Daemon/main.cpp +@@ -16,17 +16,20 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + +-#include +- +-#include "Logger.hpp" + #include "Daemon.hpp" +-#include "Exception.hpp" + #include "Common/Utility.hpp" + #include "Seccomp.h" + ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ + #include ++ + #include + + #if defined(HAVE_LIBCAPNG) +@@ -41,7 +44,7 @@ const char * const G_optstring = "dskl:p:c:hWC"; + static void printUsage(std::ostream& stream, const char *arg0) + { + stream << std::endl; +- stream << "Usage: " << filenameFromPath(String(arg0), true) << " [OPTIONS]" << std::endl; ++ stream << "Usage: " << filenameFromPath(std::string(arg0), true) << " [OPTIONS]" << std::endl; + stream << std::endl; + stream << " -d Enable debugging messages in the log." << std::endl; + stream << " -s Log to syslog." << std::endl; +@@ -65,9 +68,9 @@ int main(int argc, char *argv[]) + bool log_file = false; + bool use_seccomp_whitelist = false; + bool drop_capabilities = false; +- String log_file_path; +- String pid_file; +- String conf_file = "/etc/usbguard/usbguard-daemon.conf"; ++ std::string log_file_path; ++ std::string pid_file; ++ std::string conf_file = "/etc/usbguard/usbguard-daemon.conf"; + int opt; + + while ((opt = getopt(argc, argv, G_optstring)) != -1) { +@@ -84,13 +87,13 @@ int main(int argc, char *argv[]) + break; + case 'l': + log_file = true; +- log_file_path = String(optarg); ++ log_file_path = std::string(optarg); + break; + case 'p': +- pid_file = String(optarg); ++ pid_file = std::string(optarg); + break; + case 'c': +- conf_file = String(optarg); ++ conf_file = std::string(optarg); + break; + case 'W': + use_seccomp_whitelist = true; +diff --git a/src/GUI.Qt/DeviceDialog.cpp b/src/GUI.Qt/DeviceDialog.cpp +index c9fb172..28407b1 100644 +--- a/src/GUI.Qt/DeviceDialog.cpp ++++ b/src/GUI.Qt/DeviceDialog.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "DeviceDialog.h" + #include "DeviceDialog.ui.h" + +-#include ++#include "usbguard/Logger.hpp" ++ + #include + #include + +diff --git a/src/GUI.Qt/DeviceDialog.h b/src/GUI.Qt/DeviceDialog.h +index 23f7a74..3461179 100644 +--- a/src/GUI.Qt/DeviceDialog.h ++++ b/src/GUI.Qt/DeviceDialog.h +@@ -17,11 +17,15 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/USB.hpp" ++#include "usbguard/Rule.hpp" + + #include + #include +-#include +-#include + + namespace Ui { + class DeviceDialog; +@@ -92,3 +96,5 @@ private: + QString _device_id; + QStringList _interface_types; + }; ++ ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/GUI.Qt/DeviceModel.cpp b/src/GUI.Qt/DeviceModel.cpp +index 265eba0..51b203b 100644 +--- a/src/GUI.Qt/DeviceModel.cpp ++++ b/src/GUI.Qt/DeviceModel.cpp +@@ -16,9 +16,14 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif ++ + #include "DeviceModel.h" +-#include ++ ++#include "usbguard/Logger.hpp" ++ + #include + #include + #include +diff --git a/src/GUI.Qt/DeviceModel.h b/src/GUI.Qt/DeviceModel.h +index 51238e3..c64d5e0 100644 +--- a/src/GUI.Qt/DeviceModel.h ++++ b/src/GUI.Qt/DeviceModel.h +@@ -16,14 +16,17 @@ + // + // Authors: Daniel Kopecek + // +-#ifndef DEVICEMODEL_H +-#define DEVICEMODEL_H ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Rule.hpp" + + #include + #include + #include + #include +-#include + + class DeviceModelItem + { +@@ -98,4 +101,4 @@ private: + DeviceModelItem *_root_item; + }; + +-#endif // DEVICEMODEL_H ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/GUI.Qt/MainWindow.cpp b/src/GUI.Qt/MainWindow.cpp +index 12751e6..31d4ad7 100644 +--- a/src/GUI.Qt/MainWindow.cpp ++++ b/src/GUI.Qt/MainWindow.cpp +@@ -15,13 +15,18 @@ + // along with this program. If not, see . + // + // Authors: Daniel Kopecek ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "MainWindow.h" + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wswitch-default" + #include "MainWindow.ui.h" + #include "DeviceDialog.h" +-#include ++ ++#include "usbguard/Logger.hpp" ++ + #include + #include + #include +diff --git a/src/GUI.Qt/MainWindow.h b/src/GUI.Qt/MainWindow.h +index 4b9f5a0..efb6a3e 100644 +--- a/src/GUI.Qt/MainWindow.h ++++ b/src/GUI.Qt/MainWindow.h +@@ -17,15 +17,19 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "DeviceModel.h" + #include "TargetDelegate.h" + ++#include "usbguard/IPCClient.hpp" ++ + #include + #include + #include + #include +-#include + + namespace Ui { + class MainWindow; +@@ -132,3 +136,4 @@ private: + TargetDelegate _target_delegate; + }; + ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/GUI.Qt/TargetDelegate.cpp b/src/GUI.Qt/TargetDelegate.cpp +index 18a3db2..415e1b3 100644 +--- a/src/GUI.Qt/TargetDelegate.cpp ++++ b/src/GUI.Qt/TargetDelegate.cpp +@@ -16,10 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "TargetDelegate.h" + #include "DeviceModel.h" ++ ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + TargetDelegate::TargetDelegate(QObject *parent) + : QStyledItemDelegate(parent) +diff --git a/src/GUI.Qt/TargetDelegate.h b/src/GUI.Qt/TargetDelegate.h +index c4b3218..2661b39 100644 +--- a/src/GUI.Qt/TargetDelegate.h ++++ b/src/GUI.Qt/TargetDelegate.h +@@ -16,8 +16,10 @@ + // + // Authors: Daniel Kopecek + // +-#ifndef TARGETDELEGATE_H +-#define TARGETDELEGATE_H ++#pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include + +@@ -34,4 +36,4 @@ public: + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + }; + +-#endif // TARGETDELEGATE_H ++/* vim: set ts=2 sw=2 et */ +diff --git a/src/GUI.Qt/main.cpp b/src/GUI.Qt/main.cpp +index 458217f..c9e86e2 100644 +--- a/src/GUI.Qt/main.cpp ++++ b/src/GUI.Qt/main.cpp +@@ -16,6 +16,10 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "MainWindow.h" + #include + #include +diff --git a/src/Library/AllowedMatchesCondition.cpp b/src/Library/AllowedMatchesCondition.cpp +index f871a9c..b60c63c 100644 +--- a/src/Library/AllowedMatchesCondition.cpp ++++ b/src/Library/AllowedMatchesCondition.cpp +@@ -16,14 +16,19 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "AllowedMatchesCondition.hpp" +-#include "RuleParser.hpp" +-#include "Logger.hpp" +-#include ++ ++#include "usbguard/Interface.hpp" ++#include "usbguard/Logger.hpp" ++#include "usbguard/RuleParser.hpp" + + namespace usbguard + { +- AllowedMatchesCondition::AllowedMatchesCondition(const String& device_spec, bool negated) ++ AllowedMatchesCondition::AllowedMatchesCondition(const std::string& device_spec, bool negated) + : RuleConditionBase("allowed-matches", device_spec, negated) + { + _device_match_rule = parseRuleFromString(std::string("allow ") + device_spec); +diff --git a/src/Library/AllowedMatchesCondition.hpp b/src/Library/AllowedMatchesCondition.hpp +index f0c8451..3fb4788 100644 +--- a/src/Library/AllowedMatchesCondition.hpp ++++ b/src/Library/AllowedMatchesCondition.hpp +@@ -17,16 +17,23 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Rule.hpp" ++#include "usbguard/Typedefs.hpp" ++ ++#include + + namespace usbguard + { + class AllowedMatchesCondition : public RuleConditionBase + { + public: +- AllowedMatchesCondition(const String& device_spec, bool negated = false); ++ AllowedMatchesCondition(const std::string& device_spec, bool negated = false); + AllowedMatchesCondition(const AllowedMatchesCondition& rhs); + void init(Interface * const interface_ptr); + bool update(const Rule& rule); +diff --git a/src/Library/Audit.cpp b/src/Library/Audit.cpp +deleted file mode 100644 +index ad7a744..0000000 +--- a/src/Library/Audit.cpp ++++ /dev/null +@@ -1,252 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +- +-#include "Audit.hpp" +- +-#include +-#include +-#include +- +-namespace usbguard +-{ +- +- AuditIdentity::AuditIdentity() +- { +- _uid = getuid(); +- _pid = getpid(); +- } +- +- AuditIdentity::AuditIdentity(uid_t uid, pid_t pid) +- { +- _uid = uid; +- _pid = pid; +- } +- +- std::string AuditIdentity::toString() const +- { +- std::string identity_string; +- +- identity_string.append("{ uid="); +- identity_string.append(numberToString(_uid)); +- identity_string.append(" pid="); +- identity_string.append(numberToString(_pid)); +- identity_string.append(" }"); +- +- return identity_string; +- } +- +- AuditEvent::AuditEvent(const AuditIdentity& identity) +- : _confirmed(false), +- _identity(identity) +- { +- +- } +- +- AuditEvent::AuditEvent(AuditEvent&& event) +- : _confirmed(event._confirmed), +- _identity(std::move(event._identity)), +- _message(std::move(event._message)) +- { +- event.setConfirmed(true); +- } +- +- AuditEvent::~AuditEvent() +- { +- if (!_confirmed) { +- failure(); +- } +- } +- +- void AuditEvent::confirm(const std::string& result) +- { +- USBGUARD_LOG(Audit) << "result=" << result \ +- << " identity=" << _identity.toString() \ +- << " " << _message; +- setConfirmed(true); +- } +- +- void AuditEvent::success() +- { +- confirm("SUCCESS"); +- } +- +- void AuditEvent::failure() +- { +- confirm("FAILURE"); +- } +- +- void AuditEvent::setConfirmed(bool state) +- { +- _confirmed = state; +- } +- +- std::string& AuditEvent::refMessage() +- { +- return _message; +- } +- +- Audit::Audit(const AuditIdentity& identity) +- : _identity(identity) +- { +- +- } +- +- AuditEvent Audit::policyEvent(Pointer rule, Policy::EventType event) +- { +- return policyEvent(_identity, rule, event); +- } +- +- AuditEvent Audit::policyEvent(Pointer new_rule, Pointer old_rule) +- { +- return policyEvent(_identity, new_rule, old_rule); +- } +- +- AuditEvent Audit::policyEvent(Pointer device, Policy::EventType event) +- { +- return policyEvent(_identity, device, event); +- } +- +- AuditEvent Audit::policyEvent(Pointer device, Rule::Target old_target, Rule::Target new_target) +- { +- return policyEvent(_identity, device, old_target, new_target); +- } +- +- AuditEvent Audit::deviceEvent(Pointer device, DeviceManager::EventType event) +- { +- return deviceEvent(_identity, device, event); +- } +- +- AuditEvent Audit::deviceEvent(Pointer new_device, Pointer old_device) +- { +- return deviceEvent(_identity, new_device, old_device); +- } +- +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, Pointer rule, Policy::EventType event) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy."; +- message += Policy::eventTypeToString(event); +- +- message += " rule.id="; +- message += numberToString(rule->getRuleID()); +- +- message += " rule='"; +- message += rule->toString(); +- message += "'"; +- +- return audit_event; +- } +- +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, Pointer new_rule, Pointer old_rule) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy."; +- message += Policy::eventTypeToString(Policy::EventType::Update); +- +- message += " rule.id="; +- message += numberToString(old_rule->getRuleID()); +- +- message += " rule.old='"; +- message += old_rule->toString(); +- message += "'"; +- +- message += " rule.new='"; +- message += new_rule->toString(); +- message += "'"; +- +- return audit_event; +- } +- +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, Pointer device, Policy::EventType event) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy.Device."; +- message += Policy::eventTypeToString(event); +- +- message += " target="; +- message += Rule::targetToString(device->getTarget()); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; +- } +- +- AuditEvent Audit::policyEvent(const AuditIdentity& identity, Pointer device, Rule::Target old_target, Rule::Target new_target) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Policy.Device."; +- message += Policy::eventTypeToString(Policy::EventType::Update); +- +- message += " target.old="; +- message += Rule::targetToString(old_target); +- +- message += " target.new="; +- message += Rule::targetToString(new_target); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; +- } +- +- AuditEvent Audit::deviceEvent(const AuditIdentity& identity, Pointer device, DeviceManager::EventType event) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Device."; +- message += DeviceManager::eventTypeToString(event); +- +- message += " device='"; +- message += device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; +- } +- +- AuditEvent Audit::deviceEvent(const AuditIdentity& identity, Pointer new_device, Pointer old_device) +- { +- AuditEvent audit_event(identity); +- auto& message = audit_event.refMessage(); +- +- message += "type=Device."; +- message += DeviceManager::eventTypeToString(DeviceManager::EventType::Update); +- +- message += " device.old='"; +- message += old_device->getDeviceRule()->toString(); +- message += "'"; +- +- message += " device.new='"; +- message += new_device->getDeviceRule()->toString(); +- message += "'"; +- +- return audit_event; +- } +-} /* namespace usbguard */ +diff --git a/src/Library/Audit.hpp b/src/Library/Audit.hpp +deleted file mode 100644 +index 8ef5020..0000000 +--- a/src/Library/Audit.hpp ++++ /dev/null +@@ -1,120 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-namespace usbguard +-{ +- class DLL_PUBLIC AuditIdentity +- { +- public: +- AuditIdentity(); +- AuditIdentity(uid_t uid, pid_t pid); +- +- std::string toString() const; +- private: +- uid_t _uid; +- pid_t _pid; +- }; +- +- class DLL_PUBLIC AuditEvent +- { +- AuditEvent(const AuditIdentity& identity); +- public: +- AuditEvent(AuditEvent&& event); +- AuditEvent(const AuditEvent& event) = delete; +- ~AuditEvent(); +- +- void success(); +- void failure(); +- +- private: +- void confirm(const std::string& result); +- void setConfirmed(bool state); +- std::string& refMessage(); +- +- bool _confirmed; +- AuditIdentity _identity; +- std::string _message; +- +- friend class Audit; +- }; +- +- class DLL_PUBLIC Audit +- { +- public: +- Audit(const AuditIdentity& identity); +- +- AuditEvent policyEvent(Pointer rule, Policy::EventType event); +- AuditEvent policyEvent(Pointer new_rule, Pointer old_rule); +- AuditEvent policyEvent(Pointer device, Policy::EventType event); +- AuditEvent policyEvent(Pointer device, Rule::Target old_target, Rule::Target new_target); +- +- AuditEvent deviceEvent(Pointer device, DeviceManager::EventType event); +- AuditEvent deviceEvent(Pointer new_device, Pointer old_device); +- +- /* +- * Audit policy changes: +- * - rule append +- * - rule remove +- * - rule update +- * - policy parameter change +- * +- * Audit data: +- * - who: uid + pid +- * - when: time +- * - what: append, remove, update +- * - update: old, new +- */ +- static AuditEvent policyEvent(const AuditIdentity& identity, Pointer rule, Policy::EventType event); +- static AuditEvent policyEvent(const AuditIdentity& identity, Pointer new_rule, Pointer old_rule); +- static AuditEvent policyEvent(const AuditIdentity& identity, Pointer device, Policy::EventType event); +- static AuditEvent policyEvent(const AuditIdentity& identity, Pointer device, Rule::Target old_target, Rule::Target new_target); +- +- /* +- * Audit device changes: +- * - device insertion +- * - device removal +- * - device authorization target change +- * +- * Audit data: +- * - who: uid + pid +- * - when: time +- * - what: insert, remove, authorization target +- * - change: old, new +- */ +- static AuditEvent deviceEvent(const AuditIdentity& identity, Pointer device, DeviceManager::EventType event); +- static AuditEvent deviceEvent(const AuditIdentity& identity, Pointer new_device, Pointer old_device); +- +- private: +- AuditIdentity _identity; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/Base64.cpp b/src/Library/Base64.cpp +index 6471c31..6f8cc4d 100644 +--- a/src/Library/Base64.cpp ++++ b/src/Library/Base64.cpp +@@ -16,7 +16,12 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "Base64.hpp" ++#include + #include + + namespace usbguard +@@ -180,7 +185,7 @@ namespace usbguard + } + #undef B + +- String base64Encode (const uint8_t * const data, const size_t size) { ++ std::string base64Encode (const uint8_t * const data, const size_t size) { + if (size == 0 || data == nullptr) { + throw std::runtime_error("base64encode: invalid input"); + } +@@ -189,7 +194,7 @@ namespace usbguard + const uint8_t remainder = size % 3; + const size_t enc3_count = (size - remainder) / 3; + +- String result(encoded_size, 0); ++ std::string result(encoded_size, 0); + char * const buffer = &result[0]; + size_t i = 0; + +@@ -213,7 +218,7 @@ namespace usbguard + return result; + } + +- String base64Decode(const char * const data, const size_t size) { ++ std::string base64Decode(const char * const data, const size_t size) { + if (size == 0 || (size % 4) != 0) { + throw std::runtime_error("base64Decode: invalid input"); + } +@@ -231,7 +236,7 @@ namespace usbguard + --dec4_count; + } + +- String result(decoded_size, 0); ++ std::string result(decoded_size, 0); + uint8_t * const buffer = reinterpret_cast(&result[0]); + size_t i = 0; + +@@ -268,12 +273,12 @@ namespace usbguard + return (encoded_size / 4 * 3) + (encoded_size % 4); + } + +- String base64Encode(const String& value) ++ std::string base64Encode(const std::string& value) + { + return base64Encode(reinterpret_cast(value.c_str()), value.size()); + } + +- String base64Decode(const String& value) ++ std::string base64Decode(const std::string& value) + { + return base64Decode(value.c_str(), value.size()); + } +diff --git a/src/Library/Base64.hpp b/src/Library/Base64.hpp +index d297735..d8d733b 100644 +--- a/src/Library/Base64.hpp ++++ b/src/Library/Base64.hpp +@@ -16,7 +16,11 @@ + // + // Authors: Daniel Kopecek + // +-#include "Typedefs.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include + #include + + namespace usbguard +@@ -24,11 +28,11 @@ namespace usbguard + size_t base64EncodedSize(size_t decoded_size); + size_t base64DecodedSize(size_t encoded_size); + +- String base64Encode(const String& value); +- String base64Encode(const uint8_t *buffer, size_t buflen); ++ std::string base64Encode(const std::string& value); ++ std::string base64Encode(const uint8_t *buffer, size_t buflen); + +- String base64Decode(const String& value); +- size_t base64Decode(const String& value, void *buffer, size_t buflen); +- String base64Decode(const char * const data, const size_t size); ++ std::string base64Decode(const std::string& value); ++ size_t base64Decode(const std::string& value, void *buffer, size_t buflen); ++ std::string base64Decode(const char * const data, const size_t size); + } /* namespace usbguard */ + +diff --git a/src/Library/ConfigFile.cpp b/src/Library/ConfigFile.cpp +deleted file mode 100644 +index b55faaa..0000000 +--- a/src/Library/ConfigFile.cpp ++++ /dev/null +@@ -1,62 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "ConfigFilePrivate.hpp" +- +-namespace usbguard +-{ +- ConfigFile::ConfigFile(const StringVector& known_names) +- { +- d_pointer = new ConfigFilePrivate(*this, known_names); +- } +- +- ConfigFile::~ConfigFile() +- { +- delete d_pointer; +- } +- +- void ConfigFile::open(const String& path) +- { +- d_pointer->open(path); +- } +- +- void ConfigFile::write() +- { +- d_pointer->write(); +- } +- +- void ConfigFile::close() +- { +- d_pointer->close(); +- } +- +- const String& ConfigFile::getSettingValue(const String& name) const +- { +- return d_pointer->getSettingValue(name); +- } +- +- void ConfigFile::setSettingValue(const String& name, String& value) +- { +- d_pointer->setSettingValue(name, value); +- } +- +- bool ConfigFile::hasSettingValue(const String& name) const +- { +- return d_pointer->hasSettingValue(name); +- } +-} /* namespace usbguard */ +diff --git a/src/Library/ConfigFile.hpp b/src/Library/ConfigFile.hpp +deleted file mode 100644 +index f987640..0000000 +--- a/src/Library/ConfigFile.hpp ++++ /dev/null +@@ -1,41 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include +- +-namespace usbguard { +- class ConfigFilePrivate; +- class DLL_PUBLIC ConfigFile +- { +- public: +- ConfigFile(const StringVector& known_names = StringVector()); +- ~ConfigFile(); +- +- void open(const String& path); +- void write(); +- void close(); +- +- void setSettingValue(const String& name, String& value); +- bool hasSettingValue(const String& name) const; +- const String& getSettingValue(const String& name) const; +- +- private: +- ConfigFilePrivate* d_pointer; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/ConfigFilePrivate.cpp b/src/Library/ConfigFilePrivate.cpp +index eb15ca4..63a455a 100644 +--- a/src/Library/ConfigFilePrivate.cpp ++++ b/src/Library/ConfigFilePrivate.cpp +@@ -16,15 +16,24 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "ConfigFilePrivate.hpp" + #include "Common/Utility.hpp" +-#include "Logger.hpp" ++ ++#include "usbguard/Logger.hpp" ++ + #include ++#include ++#include ++ ++#include + + namespace usbguard + { +- ConfigFilePrivate::ConfigFilePrivate(ConfigFile& p_instance, const StringVector& known_names) ++ ConfigFilePrivate::ConfigFilePrivate(ConfigFile& p_instance, const std::vector& known_names) + : _p_instance(p_instance), + _known_names(known_names) + { +@@ -40,7 +49,7 @@ namespace usbguard + } + } + +- void ConfigFilePrivate::open(const String& path) ++ void ConfigFilePrivate::open(const std::string& path) + { + _stream.open(path, std::ios::in|std::ios::out); + if (!_stream.is_open()) { +@@ -81,27 +90,27 @@ namespace usbguard + _stream.close(); + } + +- const String& ConfigFilePrivate::getSettingValue(const String& name) const ++ const std::string& ConfigFilePrivate::getSettingValue(const std::string& name) const + { + const NVPair& setting = _settings.at(name); + return setting.value; + } + +- void ConfigFilePrivate::setSettingValue(const String& name, String& value) ++ void ConfigFilePrivate::setSettingValue(const std::string& name, std::string& value) + { + NVPair& setting = _settings.at(name); + setting.value = value; + _dirty = true; + } + +- bool ConfigFilePrivate::hasSettingValue(const String& name) const ++ bool ConfigFilePrivate::hasSettingValue(const std::string& name) const + { + return (_settings.count(name) != 0); + } + + void ConfigFilePrivate::parse() + { +- String config_line; ++ std::string config_line; + size_t config_line_number = 0; + + while(std::getline(_stream, config_line)) { +@@ -109,12 +118,12 @@ namespace usbguard + _lines.push_back(config_line); + + const size_t nv_separator = config_line.find_first_of("="); +- if (nv_separator == String::npos) { ++ if (nv_separator == std::string::npos) { + continue; + } + +- String name = trim(config_line.substr(0, nv_separator)); +- String value = config_line.substr(nv_separator + 1); ++ std::string name = trim(config_line.substr(0, nv_separator)); ++ std::string value = config_line.substr(nv_separator + 1); + + if (name[0] == '#') { + continue; +@@ -132,7 +141,7 @@ namespace usbguard + } + } + +- bool ConfigFilePrivate::checkNVPair(const String& name, const String& value) const ++ bool ConfigFilePrivate::checkNVPair(const std::string& name, const std::string& value) const + { + (void)value; /* TODO */ + +diff --git a/src/Library/ConfigFilePrivate.hpp b/src/Library/ConfigFilePrivate.hpp +index 39788a7..3d57a11 100644 +--- a/src/Library/ConfigFilePrivate.hpp ++++ b/src/Library/ConfigFilePrivate.hpp +@@ -17,43 +17,50 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include "ConfigFile.hpp" ++#endif ++ ++#include "usbguard/ConfigFile.hpp" ++ + #include ++#include ++#include ++#include + + namespace usbguard { + class ConfigFilePrivate + { + public: +- ConfigFilePrivate(ConfigFile& p_instance, const StringVector& known_names); ++ ConfigFilePrivate(ConfigFile& p_instance, const std::vector& known_names); + ~ConfigFilePrivate(); + +- void open(const String& path); ++ void open(const std::string& path); + void write(); + void close(); + +- void setSettingValue(const String& name, String& value); +- bool hasSettingValue(const String& name) const; +- const String& getSettingValue(const String& name) const; ++ void setSettingValue(const std::string& name, std::string& value); ++ bool hasSettingValue(const std::string& name) const; ++ const std::string& getSettingValue(const std::string& name) const; + + protected: + void parse(); +- bool checkNVPair(const String& name, const String& value) const; ++ bool checkNVPair(const std::string& name, const std::string& value) const; + + private: + struct NVPair + { +- String name; +- String value; ++ std::string name; ++ std::string value; + size_t line_number; + }; + + ConfigFile& _p_instance; +- String _path; ++ std::string _path; + std::fstream _stream; +- StringVector _lines; +- StringKeyMap _settings; ++ std::vector _lines; ++ std::map _settings; + bool _dirty; +- StringVector _known_names; ++ std::vector _known_names; + }; + } +diff --git a/src/Library/Device.cpp b/src/Library/Device.cpp +deleted file mode 100644 +index 636349e..0000000 +--- a/src/Library/Device.cpp ++++ /dev/null +@@ -1,196 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include +-#include "DevicePrivate.hpp" +- +-namespace usbguard { +- Device::Device(DeviceManager& manager) +- { +- d_pointer = new DevicePrivate(*this, manager); +- } +- +- Device::~Device() +- { +- delete d_pointer; +- d_pointer = nullptr; +- } +- +- Device::Device(const Device& rhs) +- { +- d_pointer = new DevicePrivate(*this, *rhs.d_pointer); +- } +- +- const Device& Device::operator=(const Device &rhs) +- { +- DevicePrivate* n_pointer = new DevicePrivate(*this, *rhs.d_pointer); +- delete d_pointer; +- d_pointer = n_pointer; +- return *this; +- } +- +- DeviceManager& Device::manager() const +- { +- return d_pointer->manager(); +- } +- +- std::mutex& Device::refDeviceMutex() +- { +- return d_pointer->refDeviceMutex(); +- } +- +- Pointer Device::getDeviceRule(const bool with_port, const bool with_parent_hash, const bool match_rule) +- { +- return d_pointer->getDeviceRule(with_port, with_parent_hash, match_rule); +- } +- +- String Device::hashString(const String& value) const +- { +- return d_pointer->hashString(value); +- } +- +- void Device::initializeHash() +- { +- d_pointer->initializeHash(); +- } +- +- void Device::updateHash(const void * const ptr, const size_t size) +- { +- d_pointer->updateHash(ptr, size); +- } +- +- void Device::updateHash(std::istream& descriptor_stream, const size_t expected_size) +- { +- d_pointer->updateHash(descriptor_stream, expected_size); +- } +- +- String Device::finalizeHash() +- { +- return d_pointer->finalizeHash(); +- } +- +- const String& Device::getHash() const +- { +- return d_pointer->getHash(); +- } +- +- void Device::setParentHash(const String& hash) +- { +- d_pointer->setParentHash(hash); +- } +- +- void Device::setID(uint32_t id) +- { +- d_pointer->setID(id); +- } +- +- uint32_t Device::getID() const +- { +- return d_pointer->getID(); +- } +- +- void Device::setParentID(uint32_t id) +- { +- d_pointer->setParentID(id); +- } +- +- uint32_t Device::getParentID() const +- { +- return d_pointer->getParentID(); +- } +- +- void Device::setTarget(Rule::Target target) +- { +- d_pointer->setTarget(target); +- } +- +- Rule::Target Device::getTarget() const +- { +- return d_pointer->getTarget(); +- } +- +- void Device::setName(const String& name) +- { +- d_pointer->setName(name); +- } +- +- const String& Device::getName() const +- { +- return d_pointer->getName(); +- } +- +- void Device::setDeviceID(const USBDeviceID& device_id) +- { +- d_pointer->setDeviceID(device_id); +- } +- +- const USBDeviceID& Device::getDeviceID() const +- { +- return d_pointer->getDeviceID(); +- } +- +- void Device::setPort(const String& port) +- { +- d_pointer->setPort(port); +- } +- +- const String& Device::getPort() const +- { +- return d_pointer->getPort(); +- } +- +- void Device::setSerial(const String& serial_number) +- { +- d_pointer->setSerial(serial_number); +- } +- +- const String& Device::getSerial() const +- { +- return d_pointer->getSerial(); +- } +- +- std::vector& Device::refMutableInterfaceTypes() +- { +- return d_pointer->refMutableInterfaceTypes(); +- } +- +- const std::vector& Device::getInterfaceTypes() const +- { +- return d_pointer->getInterfaceTypes(); +- } +- +- void Device::loadDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) +- { +- d_pointer->loadDeviceDescriptor(parser, descriptor); +- } +- +- void Device::loadConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) +- { +- d_pointer->loadConfigurationDescriptor(parser, descriptor); +- } +- +- void Device::loadInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) +- { +- d_pointer->loadInterfaceDescriptor(parser, descriptor); +- } +- +- void Device::loadEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) +- { +- d_pointer->loadEndpointDescriptor(parser, descriptor); +- } +-} /* namespace usbguard */ +diff --git a/src/Library/Device.hpp b/src/Library/Device.hpp +deleted file mode 100644 +index e90580e..0000000 +--- a/src/Library/Device.hpp ++++ /dev/null +@@ -1,84 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +-#include +-#include +- +-namespace usbguard { +- class DeviceManager; +- class DevicePrivate; +- class DLL_PUBLIC Device +- { +- public: +- Device(DeviceManager& manager); +- ~Device(); +- Device(const Device& rhs); +- const Device& operator=(const Device& rhs); +- +- DeviceManager& manager() const; +- +- std::mutex& refDeviceMutex(); +- Pointer getDeviceRule(bool with_port = true, bool with_parent_hash = true, bool match_rule = false); +- String hashString(const String& value) const; +- void initializeHash(); +- void updateHash(const void * ptr, size_t size); +- void updateHash(std::istream& descriptor_stream, size_t expected_size); +- String finalizeHash(); +- const String& getHash() const; +- +- void setParentHash(const String& hash); +- +- void setID(uint32_t id); +- uint32_t getID() const; +- +- void setParentID(uint32_t id); +- uint32_t getParentID() const; +- +- void setTarget(Rule::Target target); +- Rule::Target getTarget() const; +- +- void setName(const String& name); +- const String& getName() const; +- +- void setDeviceID(const USBDeviceID& device_id); +- const USBDeviceID& getDeviceID() const; +- +- void setPort(const String& port); +- const String& getPort() const; +- +- void setSerial(const String& serial_number); +- const String& getSerial() const; +- +- std::vector& refMutableInterfaceTypes(); +- const std::vector& getInterfaceTypes() const; +- +- virtual bool isController() const = 0; +- +- void loadDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +- void loadConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +- void loadInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +- void loadEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +- +- private: +- DevicePrivate *d_pointer; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/DeviceManager.cpp b/src/Library/DeviceManager.cpp +deleted file mode 100644 +index 8a2bbdd..0000000 +--- a/src/Library/DeviceManager.cpp ++++ /dev/null +@@ -1,177 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include +-#include +-#include +-#include +-#include "DeviceManagerPrivate.hpp" +- +-namespace usbguard { +- uint32_t DeviceManager::eventTypeToInteger(DeviceManager::EventType event) +- { +- return static_cast(event); +- } +- +- DeviceManager::EventType DeviceManager::eventTypeFromInteger(uint32_t event_integer) +- { +- switch(event_integer) { +- case static_cast(EventType::Insert): +- case static_cast(EventType::Update): +- case static_cast(EventType::Remove): +- break; +- default: +- throw std::runtime_error("Invalid event type integer value"); +- } +- return static_cast(event_integer); +- } +- +- std::string DeviceManager::eventTypeToString(DeviceManager::EventType event) +- { +- switch(event) { +- case DeviceManager::EventType::Present: +- return "Present"; +- case DeviceManager::EventType::Insert: +- return "Insert"; +- case DeviceManager::EventType::Remove: +- return "Remove"; +- case DeviceManager::EventType::Update: +- return "Update"; +- default: +- throw USBGUARD_BUG("unknown event type"); +- } +- } +- +- DeviceManager::DeviceManager(DeviceManagerHooks& hooks) +- { +- d_pointer = new DeviceManagerPrivate(*this, hooks); +- } +- +- DeviceManager::DeviceManager(const DeviceManager& rhs) +- { +- d_pointer = new DeviceManagerPrivate(*this, *rhs.d_pointer); +- } +- +- const DeviceManager& DeviceManager::operator=(const DeviceManager& rhs) +- { +- DeviceManagerPrivate* n_pointer = new DeviceManagerPrivate(*this, *rhs.d_pointer); +- delete d_pointer; +- d_pointer = n_pointer; +- return *this; +- } +- +- DeviceManager::~DeviceManager() +- { +- delete d_pointer; +- d_pointer = nullptr; +- } +- +- void DeviceManager::setRestoreControllerDeviceState(bool enabled) +- { +- d_pointer->setRestoreControllerDeviceState(enabled); +- } +- +- bool DeviceManager::getRestoreControllerDeviceState() const +- { +- return d_pointer->getRestoreControllerDeviceState(); +- } +- +- void DeviceManager::insertDevice(Pointer device) +- { +- d_pointer->insertDevice(device); +- } +- +- Pointer DeviceManager::removeDevice(uint32_t id) +- { +- return d_pointer->removeDevice(id); +- } +- +- PointerVector DeviceManager::getDeviceList() +- { +- return d_pointer->getDeviceList(); +- } +- +- PointerVector DeviceManager::getDeviceList(const Rule& query) +- { +- PointerVector matching_devices; +- +- for (auto const& device : getDeviceList()) { +- if (query.appliesTo(device->getDeviceRule())) { +- switch(query.getTarget()) { +- case Rule::Target::Allow: +- case Rule::Target::Block: +- if (device->getTarget() == query.getTarget()) { +- matching_devices.push_back(device); +- } +- break; +- case Rule::Target::Device: +- case Rule::Target::Match: +- matching_devices.push_back(device); +- break; +- case Rule::Target::Reject: +- case Rule::Target::Unknown: +- case Rule::Target::Invalid: +- default: +- throw std::runtime_error("Invalid device query target"); +- } +- } +- } +- +- return matching_devices; +- } +- +- Pointer DeviceManager::getDevice(uint32_t id) +- { +- return d_pointer->getDevice(id); +- } +- +- void DeviceManager::DeviceEvent(DeviceManager::EventType event, Pointer device) +- { +- d_pointer->DeviceEvent(event, device); +- } +- +- void DeviceManager::DeviceException(const String& message) +- { +- d_pointer->DeviceException(message); +- } +-} /* namespace usbguard */ +- +-#if defined(HAVE_UEVENT) +-# include "UEventDeviceManager.hpp" +-#endif +- +-usbguard::Pointer usbguard::DeviceManager::create(DeviceManagerHooks& hooks, const String& backend) +-{ +-#if defined(HAVE_UEVENT) +- if (backend == "udev") { +- USBGUARD_LOG(Warning) << "udev backend is OBSOLETE. Falling back to new default: uevent"; +- } +- if (backend == "uevent" || /* transition udev => uevent */backend == "udev") { +- return usbguard::makePointer(hooks); +- } +- if (backend == "dummy") { +- const char * const device_root_cstr = getenv("USBGUARD_DUMMY_DEVICE_ROOT"); +- if (device_root_cstr == nullptr) { +- throw Exception("DeviceManager", "dummy", "USBGUARD_DUMMY_DEVICE_ROOT environment variable not defined"); +- } +- const String device_root(device_root_cstr); +- return usbguard::makePointer(hooks, device_root, /*dummy_mode=*/true); +- } +-#endif +- throw Exception("DeviceManager", "backend", "requested backend is not available"); +-} +diff --git a/src/Library/DeviceManager.hpp b/src/Library/DeviceManager.hpp +deleted file mode 100644 +index 4edeb13..0000000 +--- a/src/Library/DeviceManager.hpp ++++ /dev/null +@@ -1,79 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include +-#include +-#include +-#include +- +-namespace usbguard { +- class DeviceManagerHooks; +- class DeviceManagerPrivate; +- class DLL_PUBLIC DeviceManager +- { +- public: +- enum class EventType { +- Present = 0, +- Insert = 1, +- Update = 2, /* use case: writable attribute changed externally */ +- Remove = 3, +- }; +- +- static uint32_t eventTypeToInteger(EventType event); +- static EventType eventTypeFromInteger(uint32_t event_integer); +- static std::string eventTypeToString(EventType event); +- +- DeviceManager(DeviceManagerHooks& hooks); +- DeviceManager(const DeviceManager& rhs); +- const DeviceManager& operator=(const DeviceManager& rhs); +- +- virtual ~DeviceManager(); +- +- virtual void setDefaultBlockedState(bool state) = 0; +- virtual void setEnumerationOnlyMode(bool state) = 0; +- virtual void start() = 0; +- virtual void stop() = 0; +- virtual void scan() = 0; +- +- void setRestoreControllerDeviceState(bool enabled); +- bool getRestoreControllerDeviceState() const; +- +- virtual Pointer applyDevicePolicy(uint32_t id, Rule::Target target) = 0; +- +- virtual void insertDevice(Pointer device); +- Pointer removeDevice(uint32_t id); +- +- /* Returns a copy of the list of active USB devices */ +- PointerVector getDeviceList(); +- PointerVector getDeviceList(const Rule& query); +- +- Pointer getDevice(uint32_t id); +- std::mutex& refDeviceMapMutex(); +- +- /* Call Daemon instance hooks */ +- void DeviceEvent(EventType event, Pointer device); +- void DeviceException(const String& message); +- +- static Pointer create(DeviceManagerHooks& hooks, const String& backend); +- +- private: +- DeviceManagerPrivate *d_pointer; +- }; +- +-} /* namespace usbguard */ +diff --git a/src/Library/DeviceManagerHooks.cpp b/src/Library/DeviceManagerHooks.cpp +deleted file mode 100644 +index f039389..0000000 +--- a/src/Library/DeviceManagerHooks.cpp ++++ /dev/null +@@ -1,29 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include +- +-namespace usbguard +-{ +- void DeviceManagerHooks::dmHookDeviceEvent(DeviceManager::EventType event, Pointer device) +- { +- (void)event; +- (void)device; +- /* NOOP */ +- } +-} /* namespace usbguard */ +diff --git a/src/Library/DeviceManagerHooks.hpp b/src/Library/DeviceManagerHooks.hpp +deleted file mode 100644 +index 7a4d20a..0000000 +--- a/src/Library/DeviceManagerHooks.hpp ++++ /dev/null +@@ -1,35 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +-#include +-#include +- +-namespace usbguard +-{ +- class DLL_PUBLIC DeviceManagerHooks +- { +- public: +- virtual void dmHookDeviceEvent(DeviceManager::EventType event, Pointer device); +- virtual uint32_t dmHookAssignID() = 0; +- virtual void dmHookDeviceException(const String& message) = 0; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/DeviceManagerPrivate.cpp b/src/Library/DeviceManagerPrivate.cpp +index 579b3c7..990641d 100644 +--- a/src/Library/DeviceManagerPrivate.cpp ++++ b/src/Library/DeviceManagerPrivate.cpp +@@ -16,10 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "DeviceManagerPrivate.hpp" +-#include +-#include "Exception.hpp" +-#include "Logger.hpp" ++ ++#include "usbguard/DeviceManagerHooks.hpp" ++#include "usbguard/Exception.hpp" ++#include "usbguard/Logger.hpp" + + namespace usbguard { + DeviceManagerPrivate::DeviceManagerPrivate(DeviceManager& p_instance, DeviceManagerHooks& hooks) +@@ -55,7 +60,7 @@ namespace usbguard { + return _restore_controller_device_state; + } + +- void DeviceManagerPrivate::insertDevice(Pointer device) ++ void DeviceManagerPrivate::insertDevice(std::shared_ptr device) + { + USBGUARD_LOG(Trace) << "device_ptr=" << device.get(); + std::unique_lock device_map_lock(_device_map_mutex); +@@ -65,7 +70,7 @@ namespace usbguard { + _device_map[id] = device; + } + +- Pointer DeviceManagerPrivate::removeDevice(uint32_t id) ++ std::shared_ptr DeviceManagerPrivate::removeDevice(uint32_t id) + { + USBGUARD_LOG(Trace) << "entry: id=" << id; + std::unique_lock device_map_lock(_device_map_mutex); +@@ -73,16 +78,16 @@ namespace usbguard { + if (it == _device_map.end()) { + throw Exception("Device remove", "device id", "id doesn't exist"); + } +- Pointer device = it->second; ++ std::shared_ptr device = it->second; + _device_map.erase(it); + USBGUARD_LOG(Trace) << "return: device_ptr=" << device.get(); + return device; + } + +- PointerVector DeviceManagerPrivate::getDeviceList() ++ std::vector> DeviceManagerPrivate::getDeviceList() + { + std::unique_lock device_map_lock(_device_map_mutex); +- PointerVector devices; ++ std::vector> devices; + + for (auto& map_entry : _device_map) { + devices.push_back(map_entry.second); +@@ -91,7 +96,7 @@ namespace usbguard { + return devices; + } + +- Pointer DeviceManagerPrivate::getDevice(uint32_t id) ++ std::shared_ptr DeviceManagerPrivate::getDevice(uint32_t id) + { + USBGUARD_LOG(Trace) << "id=" << id; + std::unique_lock device_map_lock(_device_map_mutex); +@@ -103,14 +108,14 @@ namespace usbguard { + } + } + +- void DeviceManagerPrivate::DeviceEvent(DeviceManager::EventType event, Pointer device) ++ void DeviceManagerPrivate::DeviceEvent(DeviceManager::EventType event, std::shared_ptr device) + { + USBGUARD_LOG(Trace) << "event=" << DeviceManager::eventTypeToString(event) + << "device_ptr=" << device.get(); + _hooks.dmHookDeviceEvent(event, device); + } + +- void DeviceManagerPrivate::DeviceException(const String& message) ++ void DeviceManagerPrivate::DeviceException(const std::string& message) + { + USBGUARD_LOG(Trace) << "message=" << message; + _hooks.dmHookDeviceException(message); +diff --git a/src/Library/DeviceManagerPrivate.hpp b/src/Library/DeviceManagerPrivate.hpp +index b98443b..7ccf39a 100644 +--- a/src/Library/DeviceManagerPrivate.hpp ++++ b/src/Library/DeviceManagerPrivate.hpp +@@ -17,10 +17,17 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include +-#include +-#include +-#include ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Device.hpp" ++#include "usbguard/DeviceManager.hpp" ++#include "usbguard/RuleSet.hpp" ++#include "usbguard/Typedefs.hpp" ++ ++#include ++#include + #include + + namespace usbguard { +@@ -35,23 +42,23 @@ namespace usbguard { + void setRestoreControllerDeviceState(bool enabled); + bool getRestoreControllerDeviceState() const; + +- void insertDevice(Pointer device); +- Pointer removeDevice(uint32_t id); ++ void insertDevice(std::shared_ptr device); ++ std::shared_ptr removeDevice(uint32_t id); + + /* Returns a copy of the list of active USB devices */ +- PointerVector getDeviceList(); +- Pointer getDevice(uint32_t id); ++ std::vector> getDeviceList(); ++ std::shared_ptr getDevice(uint32_t id); + std::mutex& refDeviceMapMutex(); + + /* Call Daemon instance hooks */ +- void DeviceEvent(DeviceManager::EventType event, Pointer device); +- void DeviceException(const String& message); ++ void DeviceEvent(DeviceManager::EventType event, std::shared_ptr device); ++ void DeviceException(const std::string& message); + + private: + DeviceManager& _p_instance; + DeviceManagerHooks& _hooks; + mutable std::mutex _device_map_mutex; +- PointerMap _device_map; ++ std::map> _device_map; + bool _restore_controller_device_state; + }; + +diff --git a/src/Library/DevicePrivate.cpp b/src/Library/DevicePrivate.cpp +index da91c27..fa422ac 100644 +--- a/src/Library/DevicePrivate.cpp ++++ b/src/Library/DevicePrivate.cpp +@@ -16,12 +16,18 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "DevicePrivate.hpp" +-#include "DeviceManager.hpp" +-#include "Logger.hpp" + #include "Hash.hpp" +-#include "Exception.hpp" + #include "Common/Utility.hpp" ++ ++#include "usbguard/DeviceManager.hpp" ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ + #include + + namespace usbguard { +@@ -68,14 +74,14 @@ namespace usbguard { + return _mutex; + } + +- Pointer DevicePrivate::getDeviceRule(const bool with_port, const bool with_parent_hash, const bool match_rule) ++ std::shared_ptr DevicePrivate::getDeviceRule(const bool with_port, const bool with_parent_hash, const bool match_rule) + { + USBGUARD_LOG(Trace) << "entry: " + << " with_port=" << with_port + << " with_parent_hash=" << with_parent_hash + << " match_rule=" << match_rule; + +- Pointer device_rule = makePointer(); ++ std::shared_ptr device_rule = std::make_shared(); + std::unique_lock device_lock(refDeviceMutex()); + + device_rule->setRuleID(_id); +@@ -117,7 +123,7 @@ namespace usbguard { + return device_rule; + } + +- String DevicePrivate::hashString(const String& value) const ++ std::string DevicePrivate::hashString(const std::string& value) const + { + Hash hash; + hash.update(value); +@@ -128,8 +134,8 @@ namespace usbguard { + { + Hash hash; + +- const String vendor_id = _device_id.getVendorID(); +- const String product_id = _device_id.getProductID(); ++ const std::string vendor_id = _device_id.getVendorID(); ++ const std::string product_id = _device_id.getProductID(); + + if (vendor_id.empty() || product_id.empty()) { + throw Exception("Device hash initialization", numberToString(getID()), "vendor and/or product id values not available"); +@@ -138,7 +144,7 @@ namespace usbguard { + /* + * Hash name, device id and serial number fields. + */ +- for (const String& field : { _name, vendor_id, product_id, _serial_number }) { ++ for (const std::string& field : { _name, vendor_id, product_id, _serial_number }) { + hash.update(field); + } + +@@ -167,13 +173,13 @@ namespace usbguard { + _hash = std::move(hash); + } + +- String DevicePrivate::finalizeHash() ++ std::string DevicePrivate::finalizeHash() + { + _hash_base64 = _hash.getBase64(); + return _hash_base64; + } + +- const String& DevicePrivate::getHash() const ++ const std::string& DevicePrivate::getHash() const + { + if (_hash_base64.empty()) { + throw USBGUARD_BUG("Accessing unfinalized device hash value"); +@@ -181,7 +187,7 @@ namespace usbguard { + return _hash_base64; + } + +- void DevicePrivate::setParentHash(const String& hash) ++ void DevicePrivate::setParentHash(const std::string& hash) + { + _parent_hash = hash; + } +@@ -216,7 +222,7 @@ namespace usbguard { + return _target; + } + +- void DevicePrivate::setName(const String& name) ++ void DevicePrivate::setName(const std::string& name) + { + if (name.size() > USB_GENERIC_STRING_MAX_LENGTH) { + throw Exception("DevicePrivate::setName", numberToString(getID()), "name string size out-of-range"); +@@ -224,7 +230,7 @@ namespace usbguard { + _name = name; + } + +- const String& DevicePrivate::getName() const ++ const std::string& DevicePrivate::getName() const + { + return _name; + } +@@ -239,7 +245,7 @@ namespace usbguard { + return _device_id; + } + +- void DevicePrivate::setPort(const String& port) ++ void DevicePrivate::setPort(const std::string& port) + { + if (port.size() > USB_PORT_STRING_MAX_LENGTH) { + throw std::runtime_error("device port string size out of range"); +@@ -247,12 +253,12 @@ namespace usbguard { + _port = port; + } + +- const String& DevicePrivate::getPort() const ++ const std::string& DevicePrivate::getPort() const + { + return _port; + } + +- void DevicePrivate::setSerial(const String& serial_number) ++ void DevicePrivate::setSerial(const std::string& serial_number) + { + if (serial_number.size() > USB_GENERIC_STRING_MAX_LENGTH) { + throw std::runtime_error("device serial number string size out of range"); +@@ -260,7 +266,7 @@ namespace usbguard { + _serial_number = serial_number; + } + +- const String& DevicePrivate::getSerial() const ++ const std::string& DevicePrivate::getSerial() const + { + return _serial_number; + } +diff --git a/src/Library/DevicePrivate.hpp b/src/Library/DevicePrivate.hpp +index 940653d..ef1d801 100644 +--- a/src/Library/DevicePrivate.hpp ++++ b/src/Library/DevicePrivate.hpp +@@ -17,14 +17,23 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Hash.hpp" ++ ++#include "usbguard/Device.hpp" ++#include "usbguard/Rule.hpp" ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/USB.hpp" + +-#include +-#include +-#include +-#include +-#include +-#include + #include ++#include ++#include ++#include ++ ++#include + + namespace usbguard { + class DevicePrivate +@@ -37,16 +46,16 @@ namespace usbguard { + DeviceManager& manager() const; + + std::mutex& refDeviceMutex(); +- Pointer getDeviceRule(bool with_port = true, bool with_parent_hash = true, bool match_rule = false); +- String hashString(const String& value) const; ++ std::shared_ptr getDeviceRule(bool with_port = true, bool with_parent_hash = true, bool match_rule = false); ++ std::string hashString(const std::string& value) const; + + void initializeHash(); + void updateHash(const void * const ptr, size_t size); + void updateHash(std::istream& descriptor_stream, size_t expected_size); +- String finalizeHash(); +- const String& getHash() const; ++ std::string finalizeHash(); ++ const std::string& getHash() const; + +- void setParentHash(const String& hash); ++ void setParentHash(const std::string& hash); + + void setID(uint32_t id); + uint32_t getID() const; +@@ -57,17 +66,17 @@ namespace usbguard { + void setTarget(Rule::Target target); + Rule::Target getTarget() const; + +- void setName(const String& name); +- const String& getName() const; ++ void setName(const std::string& name); ++ const std::string& getName() const; + + void setDeviceID(const USBDeviceID& device_id); + const USBDeviceID& getDeviceID() const; + +- void setPort(const String& port); +- const String& getPort() const; ++ void setPort(const std::string& port); ++ const std::string& getPort() const; + +- void setSerial(const String& serial_number); +- const String& getSerial() const; ++ void setSerial(const std::string& serial_number); ++ const std::string& getSerial() const; + + std::vector& refMutableInterfaceTypes(); + const std::vector& getInterfaceTypes() const; +@@ -83,14 +92,14 @@ namespace usbguard { + std::mutex _mutex; + uint32_t _id; + uint32_t _parent_id; +- String _parent_hash; ++ std::string _parent_hash; + Rule::Target _target; +- String _name; ++ std::string _name; + USBDeviceID _device_id; +- String _serial_number; +- String _port; ++ std::string _serial_number; ++ std::string _port; + std::vector _interface_types; +- String _hash_base64; ++ std::string _hash_base64; + Hash _hash; + }; + } /* namespace usbguard */ +diff --git a/src/Library/Exception.hpp b/src/Library/Exception.hpp +deleted file mode 100644 +index c985704..0000000 +--- a/src/Library/Exception.hpp ++++ /dev/null +@@ -1,176 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +- +-#include +-#ifndef _GNU_SOURCE +-# define _GNU_SOURCE +-#endif +-#include +-#include +- +-namespace usbguard +-{ +- class DLL_PUBLIC Exception : public std::exception +- { +- public: +- Exception(const String& context, +- const String& object, +- const String& reason_val) +- : _context(context), +- _object(object), +- _reason(reason_val) +- { +- } +- +- Exception(const Exception& rhs) +- : _context(rhs._context), +- _object(rhs._object), +- _reason(rhs._reason) +- { +- } +- +- const String& context() const noexcept +- { +- return _context; +- } +- +- const String& object() const noexcept +- { +- return _object; +- } +- +- const String& reason() const noexcept +- { +- return _reason; +- } +- +- void setContext(const String& context) +- { +- _context = context; +- } +- +- void setObject(const String& object) +- { +- _object = object; +- } +- +- void setReason(const String& reason_val) +- { +- _reason = reason_val; +- } +- +- virtual String message() const noexcept +- { +- try { +- return _context + ": " + (!_object.empty() ? _object + ": " : "") + _reason; +- } +- catch(...) { +- return "usbguard::Exception: exception^2"; +- } +- } +- +- virtual const char * what() const noexcept +- { +- return "usbguard::Exception"; +- } +- +- private: +- String _context; +- String _object; +- String _reason; +- }; +- +-#define USBGUARD_BUG(m) \ +- ::usbguard::Exception(__PRETTY_FUNCTION__, "BUG", m) +- +- class ErrnoException : public Exception +- { +- public: +- ErrnoException(const String& context, const String& object, const int errno_value) +- : Exception(context, object, ErrnoException::reasonFromErrno(errno_value)) +- { +- } +- private: +- static String reasonFromErrno(const int errno_value) +- { +- char buffer[1024]; +- return String(strerror_r(errno_value, buffer, sizeof buffer)); +- } +- }; +- +-#define USBGUARD_SYSCALL_THROW(context, syscall_bool_expression) \ +- do { \ +- if (syscall_bool_expression) { \ +- throw usbguard::ErrnoException(context, #syscall_bool_expression, errno); \ +- } \ +- } while(0) +- +- class IPCException : public Exception +- { +- public: +- IPCException() +- : Exception("", "", ""), +- _message_id(0) +- { +- } +- +- IPCException(const Exception& exception, +- uint64_t message_id = 0) +- : Exception(exception), +- _message_id(message_id) +- { +- } +- +- IPCException(const String& context, +- const String& object, +- const String& reason, +- uint64_t message_id = 0) +- : Exception(context, object, reason), +- _message_id(message_id) +- { +- } +- +- IPCException(const IPCException& rhs) +- : Exception(rhs), +- _message_id(rhs._message_id) +- { +- } +- +- bool hasMessageID() const noexcept +- { +- return _message_id != 0; +- } +- +- uint64_t messageID() const noexcept +- { +- return _message_id; +- } +- +- void setMessageID(uint64_t message_id) +- { +- _message_id = message_id; +- } +- +- private: +- uint64_t _message_id; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/FixedStateCondition.cpp b/src/Library/FixedStateCondition.cpp +index e201f64..b53de2f 100644 +--- a/src/Library/FixedStateCondition.cpp ++++ b/src/Library/FixedStateCondition.cpp +@@ -16,8 +16,13 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "FixedStateCondition.hpp" +-#include "RuleParser.hpp" ++ ++#include "usbguard/RuleParser.hpp" + + namespace usbguard + { +diff --git a/src/Library/FixedStateCondition.hpp b/src/Library/FixedStateCondition.hpp +index 9a23376..250f74e 100644 +--- a/src/Library/FixedStateCondition.hpp ++++ b/src/Library/FixedStateCondition.hpp +@@ -17,9 +17,14 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Rule.hpp" ++ ++#include "usbguard/RuleCondition.hpp" + + namespace usbguard + { +diff --git a/src/Library/Hash.cpp b/src/Library/Hash.cpp +index 455f773..0bad18b 100644 +--- a/src/Library/Hash.cpp ++++ b/src/Library/Hash.cpp +@@ -16,13 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #include "Hash.hpp" + #include "Base64.hpp" +-#include "Exception.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Exception.hpp" ++ + namespace usbguard + { + Hash::Hash() +@@ -87,7 +90,7 @@ namespace usbguard + #endif + } + +- size_t Hash::update(const String& value) ++ size_t Hash::update(const std::string& value) + { + return update(value.c_str(), value.size()); + } +@@ -127,7 +130,7 @@ namespace usbguard + return size_hashed; + } + +- String Hash::getBase64() ++ std::string Hash::getBase64() + { + #if defined(USBGUARD_USE_LIBSODIUM) + uint8_t hash_binary[crypto_hash_sha256_BYTES]; +diff --git a/src/Library/Hash.hpp b/src/Library/Hash.hpp +index 23623ec..5c2fa5f 100644 +--- a/src/Library/Hash.hpp ++++ b/src/Library/Hash.hpp +@@ -17,12 +17,16 @@ + // Authors: Daniel Kopecek + // + #pragma once +- ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif ++ ++#include "usbguard/Typedefs.hpp" + +-#include "Typedefs.hpp" +-#include + #include ++#include ++ ++#include + + #if defined(USBGUARD_USE_LIBSODIUM) + #include +@@ -42,10 +46,10 @@ namespace usbguard + Hash(Hash&& rhs); + Hash& operator=(Hash&& rhs); + ~Hash(); +- size_t update(const String& value); ++ size_t update(const std::string& value); + size_t update(const void *ptr, size_t size); + size_t update(std::istream& stream); +- String getBase64(); ++ std::string getBase64(); + private: + #if defined(USBGUARD_USE_LIBSODIUM) + crypto_hash_sha256_state _state; +diff --git a/src/Library/IPCClient.cpp b/src/Library/IPCClient.cpp +deleted file mode 100644 +index 03b2fa5..0000000 +--- a/src/Library/IPCClient.cpp ++++ /dev/null +@@ -1,87 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "IPCClientPrivate.hpp" +- +-namespace usbguard +-{ +- IPCClient::IPCClient(bool connected) +- { +- d_pointer = new IPCClientPrivate(*this, connected); +- } +- +- IPCClient::~IPCClient() +- { +- delete d_pointer; +- } +- +- void IPCClient::connect() +- { +- d_pointer->connect(); +- } +- +- void IPCClient::disconnect() +- { +- d_pointer->disconnect(/*do_wait*/true); +- } +- +- bool IPCClient::isConnected() const +- { +- return d_pointer->isConnected(); +- } +- +- void IPCClient::wait() +- { +- d_pointer->wait(); +- } +- +- std::string IPCClient::setParameter(const std::string& name, const std::string& value) +- { +- return d_pointer->setParameter(name, value); +- } +- +- std::string IPCClient::getParameter(const std::string& name) +- { +- return d_pointer->getParameter(name); +- } +- +- uint32_t IPCClient::appendRule(const std::string& rule_spec, uint32_t parent_id) +- { +- return d_pointer->appendRule(rule_spec, parent_id); +- } +- +- void IPCClient::removeRule(uint32_t id) +- { +- d_pointer->removeRule(id); +- } +- +- const RuleSet IPCClient::listRules(const std::string& query) +- { +- return d_pointer->listRules(query); +- } +- +- uint32_t IPCClient::applyDevicePolicy(uint32_t id, Rule::Target target, bool permanent) +- { +- return d_pointer->applyDevicePolicy(id, target, permanent); +- } +- +- const std::vector IPCClient::listDevices(const std::string& query) +- { +- return d_pointer->listDevices(query); +- } +-} /* namespace usbguard */ +diff --git a/src/Library/IPCClient.hpp b/src/Library/IPCClient.hpp +deleted file mode 100644 +index d72c043..0000000 +--- a/src/Library/IPCClient.hpp ++++ /dev/null +@@ -1,102 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include +-#include +-#include +-#include +- +-namespace usbguard +-{ +- class IPCClientPrivate; +- class DLL_PUBLIC IPCClient : public Interface +- { +- public: +- IPCClient(bool connected = false); +- virtual ~IPCClient(); +- +- void connect(); +- void disconnect(); +- bool isConnected() const; +- void wait(); +- +- std::string setParameter(const std::string& name, const std::string& value) override; +- std::string getParameter(const std::string& name) override; +- +- uint32_t appendRule(const std::string& rule_spec, uint32_t parent_id) override; +- void removeRule(uint32_t id) override; +- const RuleSet listRules(const std::string& query) override; +- const RuleSet listRules() +- { +- return listRules("match"); +- } +- +- uint32_t applyDevicePolicy(uint32_t id, Rule::Target target, bool permanent) override; +- const std::vector listDevices(const std::string& query) override; +- const std::vector listDevices() /* NOTE: left for compatibility */ +- { +- return listDevices("match"); +- } +- +- virtual void IPCConnected() {} +- +- virtual void IPCDisconnected(bool exception_initiated, const IPCException& exception) +- { +- (void)exception_initiated; +- (void)exception; +- } +- +- virtual void DevicePresenceChanged(uint32_t id, +- DeviceManager::EventType event, +- Rule::Target target, +- const std::string& device_rule) override +- { +- (void)id; +- (void)event; +- (void)target; +- (void)device_rule; +- } +- +- virtual void DevicePolicyChanged(uint32_t id, +- Rule::Target target_old, +- Rule::Target target_new, +- const std::string& device_rule, +- uint32_t rule_id) override +- { +- (void)id; +- (void)target_old; +- (void)target_new; +- (void)device_rule; +- (void)rule_id; +- } +- +- virtual void ExceptionMessage(const std::string& context, +- const std::string& object, +- const std::string& reason) override +- { +- (void)context; +- (void)object; +- (void)reason; +- } +- +- private: +- IPCClientPrivate* d_pointer; +- }; +- +-} /* namespace usbguard */ +diff --git a/src/Library/IPCClientPrivate.cpp b/src/Library/IPCClientPrivate.cpp +index 5e24a09..fc9e044 100644 +--- a/src/Library/IPCClientPrivate.cpp ++++ b/src/Library/IPCClientPrivate.cpp +@@ -16,9 +16,14 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "IPCClientPrivate.hpp" + #include "IPCPrivate.hpp" +-#include "Logger.hpp" ++ ++#include "usbguard/Logger.hpp" + + #include + #include +diff --git a/src/Library/IPCClientPrivate.hpp b/src/Library/IPCClientPrivate.hpp +index 71ad73e..3905d9a 100644 +--- a/src/Library/IPCClientPrivate.hpp ++++ b/src/Library/IPCClientPrivate.hpp +@@ -17,9 +17,10 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include "Typedefs.hpp" +-#include "IPCClient.hpp" ++#endif ++ + #include "IPCPrivate.hpp" + #include "Common/Thread.hpp" + +@@ -28,6 +29,9 @@ + #include "Exception.pb.h" + #include "Parameter.pb.h" + ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/IPCClient.hpp" ++ + #include + #include + #include +diff --git a/src/Library/IPCPrivate.cpp b/src/Library/IPCPrivate.cpp +index 14f3015..1fdc6c0 100644 +--- a/src/Library/IPCPrivate.cpp ++++ b/src/Library/IPCPrivate.cpp +@@ -16,12 +16,17 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "IPCPrivate.hpp" +-#include "Logger.hpp" + +-#include +-#include +-#include ++#include "Devices.pb.h" ++#include "Exception.pb.h" ++#include "Policy.pb.h" ++ ++#include "usbguard/Logger.hpp" + + #include + #include +diff --git a/src/Library/IPCPrivate.hpp b/src/Library/IPCPrivate.hpp +index badf450..1723649 100644 +--- a/src/Library/IPCPrivate.hpp ++++ b/src/Library/IPCPrivate.hpp +@@ -17,10 +17,13 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + +-#include "Exception.hpp" +-#include "Typedefs.hpp" +-#include "IPCServer.hpp" ++#include "usbguard/Exception.hpp" ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/IPCServer.hpp" + + #include + #include +diff --git a/src/Library/IPCServer.cpp b/src/Library/IPCServer.cpp +deleted file mode 100644 +index 69db0d2..0000000 +--- a/src/Library/IPCServer.cpp ++++ /dev/null +@@ -1,303 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "IPCServerPrivate.hpp" +-#include "Common/Utility.hpp" +- +-#include +- +-namespace usbguard +-{ +- void IPCServer::checkAccessControlName(const std::string& name) +- { +- if (name.size() > 32) { +- throw Exception("IPC access control", "name too long", name); +- } +- +- const String valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; +- +- if (name.find_first_not_of(valid_chars) != std::string::npos) { +- throw Exception("IPC access control", "name contains invalid character(s)", name); +- } +- +- } +- +- static const std::vector> section_ttable = { +- { "ALL", IPCServer::AccessControl::Section::ALL }, +- { "Policy", IPCServer::AccessControl::Section::POLICY }, +- { "Parameters", IPCServer::AccessControl::Section::PARAMETERS }, +- { "Devices", IPCServer::AccessControl::Section::DEVICES }, +- { "Exceptions", IPCServer::AccessControl::Section::EXCEPTIONS }, +- { "None", IPCServer::AccessControl::Section::NONE } +- }; +- +- IPCServer::AccessControl::Section IPCServer::AccessControl::sectionFromString(const std::string& section_string) +- { +- for (auto ttable_entry : section_ttable) { +- if (ttable_entry.first == section_string) { +- return ttable_entry.second; +- } +- } +- throw std::runtime_error("Invalid AccessControl::Section string"); +- } +- +- std::string IPCServer::AccessControl::sectionToString(const IPCServer::AccessControl::Section section) +- { +- for (auto ttable_entry : section_ttable) { +- if (ttable_entry.second == section) { +- return ttable_entry.first; +- } +- } +- throw std::runtime_error("Invalid AccessControl::Section value"); +- } +- +- static const std::vector> privilege_ttable = { +- { "ALL", IPCServer::AccessControl::Privilege::ALL }, +- { "modify", IPCServer::AccessControl::Privilege::MODIFY }, +- { "list", IPCServer::AccessControl::Privilege::LIST }, +- { "listen", IPCServer::AccessControl::Privilege::LISTEN }, +- { "none", IPCServer::AccessControl::Privilege::NONE } +- }; +- +- IPCServer::AccessControl::Privilege IPCServer::AccessControl::privilegeFromString(const std::string& privilege_string) +- { +- for (auto ttable_entry : privilege_ttable) { +- if (ttable_entry.first == privilege_string) { +- return ttable_entry.second; +- } +- } +- throw std::runtime_error("Invalid AccessControl::Section string"); +- } +- +- std::string IPCServer::AccessControl::privilegeToString(const IPCServer::AccessControl::Privilege privilege) +- { +- for (auto ttable_entry : privilege_ttable) { +- if (ttable_entry.second == privilege) { +- return ttable_entry.first; +- } +- } +- throw std::runtime_error("Invalid AccessControl::Privilege value"); +- } +- +- IPCServer::AccessControl::AccessControl() +- { +- /* Empty: no privileges */ +- } +- +- IPCServer::AccessControl::AccessControl(const std::string& access_control_string) +- { +- std::stringstream ss(access_control_string); +- load(ss); +- } +- +- IPCServer::AccessControl::AccessControl(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) +- { +- setPrivilege(section, privilege); +- } +- +- IPCServer::AccessControl::AccessControl(const IPCServer::AccessControl& rhs) +- : _access_control(rhs._access_control) +- { +- } +- +- IPCServer::AccessControl& IPCServer::AccessControl::operator=(const IPCServer::AccessControl& rhs) +- { +- _access_control = rhs._access_control; +- return *this; +- } +- +- bool IPCServer::AccessControl::hasPrivilege(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) const +- { +- if (section == Section::ALL || section == Section::NONE) { +- throw USBGUARD_BUG("Cannot test against ALL, NONE sections"); +- } +- +- const auto it = _access_control.find(section); +- +- if (it == _access_control.cend()) { +- return false; +- } +- +- return (it->second & static_cast(privilege)) == static_cast(privilege); +- } +- +- void IPCServer::AccessControl::setPrivilege(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) +- { +- if (section == Section::NONE) { +- throw USBGUARD_BUG("Cannot set privileges for NONE section"); +- } +- if (section == Section::ALL) { +- for (const auto& value : { +- Section::POLICY, +- Section::PARAMETERS, +- Section::EXCEPTIONS, +- Section::DEVICES }) { +- _access_control[value] |= static_cast(privilege); +- } +- } +- else { +- _access_control[section] |= static_cast(privilege); +- } +- } +- +- void IPCServer::AccessControl::clear() +- { +- _access_control.clear(); +- } +- +- void IPCServer::AccessControl::load(std::istream& stream) +- { +- std::string line; +- size_t line_number = 0; +- +- while (std::getline(stream, line)) { +- ++line_number; +- const size_t nv_separator = line.find_first_of("="); +- +- if (nv_separator == String::npos) { +- continue; +- } +- +- const String section_string = trim(line.substr(0, nv_separator)); +- const Section section = sectionFromString(section_string); +- +- const String privileges_string = line.substr(nv_separator + 1); +- StringVector privilege_strings; +- tokenizeString(privileges_string, privilege_strings, " ,", /*trim_empty=*/true); +- +- for (const String& privilege_string : privilege_strings) { +- const Privilege privilege = privilegeFromString(privilege_string); +- setPrivilege(section, privilege); +- } +- } +- } +- +- void IPCServer::AccessControl::save(std::ostream& stream) const +- { +- std::string access_control_string; +- +- for (auto const& section : { +- Section::DEVICES, +- Section::POLICY, +- Section::PARAMETERS, +- Section::EXCEPTIONS +- }) { +- bool section_is_empty = true; +- std::string section_string = sectionToString(section); +- section_string.append("="); +- +- for (auto const& privilege : { +- Privilege::LIST, +- Privilege::MODIFY, +- Privilege::LISTEN +- }) { +- if (hasPrivilege(section, privilege)) { +- const std::string privilege_string = privilegeToString(privilege); +- section_string.append(privilege_string); +- section_string.append(","); +- section_is_empty = false; +- } +- } +- +- if (!section_is_empty) { +- section_string.pop_back(); +- access_control_string.append(section_string); +- access_control_string.append("\n"); +- } +- } +- +- stream << access_control_string; +- } +- +- void IPCServer::AccessControl::merge(const IPCServer::AccessControl& rhs) +- { +- for (auto const& ac_entry : rhs._access_control) { +- _access_control[ac_entry.first] |= ac_entry.second; +- } +- } +- +- void IPCServer::AccessControl::merge(const std::string& access_control_string) +- { +- const AccessControl access_control(access_control_string); +- merge(access_control); +- } +- +- IPCServer::IPCServer() +- { +- d_pointer = new IPCServerPrivate(*this); +- } +- +- IPCServer::~IPCServer() +- { +- delete d_pointer; +- } +- +- void IPCServer::start() +- { +- d_pointer->start(); +- } +- +- void IPCServer::stop() +- { +- d_pointer->stop(); +- } +- +- void IPCServer::DevicePresenceChanged(uint32_t id, +- DeviceManager::EventType event, +- Rule::Target target, +- const std::string& device_rule) +- { +- d_pointer->DevicePresenceChanged(id, event, target, device_rule); +- } +- +- void IPCServer::DevicePolicyChanged(uint32_t id, +- Rule::Target target_old, +- Rule::Target target_new, +- const std::string& device_rule, +- uint32_t rule_id) +- { +- d_pointer->DevicePolicyChanged(id, target_old, target_new, device_rule, rule_id); +- } +- +- void IPCServer::ExceptionMessage(const std::string& context, +- const std::string& object, +- const std::string& reason) +- { +- d_pointer->ExceptionMessage(context, object, reason); +- } +- +- void IPCServer::addAllowedUID(uid_t uid, const IPCServer::AccessControl& ac) +- { +- d_pointer->addAllowedUID(uid, ac); +- } +- +- void IPCServer::addAllowedGID(gid_t gid, const IPCServer::AccessControl& ac) +- { +- d_pointer->addAllowedGID(gid, ac); +- } +- +- void IPCServer::addAllowedUsername(const std::string& username, const IPCServer::AccessControl& ac) +- { +- d_pointer->addAllowedUsername(username, ac); +- } +- +- void IPCServer::addAllowedGroupname(const std::string& groupname, const IPCServer::AccessControl& ac) +- { +- d_pointer->addAllowedGroupname(groupname, ac); +- } +-} /* namespace usbguard */ +diff --git a/src/Library/IPCServer.hpp b/src/Library/IPCServer.hpp +deleted file mode 100644 +index 954be0c..0000000 +--- a/src/Library/IPCServer.hpp ++++ /dev/null +@@ -1,117 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-namespace usbguard +-{ +- class IPCServerPrivate; +- class DLL_PUBLIC IPCServer : public Interface +- { +- public: +- static void checkAccessControlName(const std::string& name); +- +- class AccessControl +- { +- public: +- enum class Section : uint8_t { +- NONE = 0, +- DEVICES = 1, +- POLICY = 2, +- PARAMETERS = 3, +- EXCEPTIONS = 4, +- ALL = 255 +- }; +- +- static Section sectionFromString(const std::string& section_string); +- static std::string sectionToString(const Section section); +- +- enum class Privilege : uint8_t { +- NONE = 0x00, +- LIST = 0x01, +- MODIFY = 0x02, +- LISTEN = 0x08, +- ALL = 0xff +- }; +- +- static Privilege privilegeFromString(const std::string& privilege_string); +- static std::string privilegeToString(const Privilege privilege); +- +- AccessControl(); +- AccessControl(const std::string& access_control_string); +- AccessControl(Section section, Privilege privilege); +- AccessControl(const AccessControl& rhs); +- AccessControl& operator=(const AccessControl& rhs); +- +- bool hasPrivilege(Section section, Privilege privilege) const; +- void setPrivilege(Section section, Privilege privilege); +- void clear(); +- void load(std::istream& stream); +- void save(std::ostream& stream) const; +- void merge(const AccessControl& rhs); +- void merge(const std::string& access_control_string); +- +- private: +- struct SectionHash { +- std::size_t operator()(Section value) const +- { +- return static_cast(value); +- } +- }; +- +- std::unordered_map _access_control; +- }; +- +- IPCServer(); +- virtual ~IPCServer(); +- +- void start(); +- void stop(); +- +- void DevicePresenceChanged(uint32_t id, +- DeviceManager::EventType event, +- Rule::Target target, +- const std::string& device_rule); +- +- void DevicePolicyChanged(uint32_t id, +- Rule::Target target_old, +- Rule::Target target_new, +- const std::string& device_rule, +- uint32_t rule_id); +- +- void ExceptionMessage(const std::string& context, +- const std::string& object, +- const std::string& reason); +- +- void addAllowedUID(uid_t uid, const IPCServer::AccessControl& ac); +- void addAllowedGID(gid_t gid, const IPCServer::AccessControl& ac); +- void addAllowedUsername(const std::string& username, const IPCServer::AccessControl& ac); +- void addAllowedGroupname(const std::string& groupname, const IPCServer::AccessControl& ac); +- +- private: +- IPCServerPrivate* d_pointer; +- }; +-} /* namespace usbguard */ +- +diff --git a/src/Library/IPCServerPrivate.cpp b/src/Library/IPCServerPrivate.cpp +index 56f8890..a83fc0e 100644 +--- a/src/Library/IPCServerPrivate.cpp ++++ b/src/Library/IPCServerPrivate.cpp +@@ -16,12 +16,17 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "IPCServerPrivate.hpp" + #include "IPCPrivate.hpp" +-#include "Logger.hpp" +-#include "Exception.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ + #include + #include + #include +@@ -237,7 +242,7 @@ namespace usbguard + IPCServerPrivate* server = \ + static_cast(qb_ipcs_connection_service_context_get(conn)); + +- UniquePointer access_control(new IPCServer::AccessControl()); ++ std::unique_ptr access_control(new IPCServer::AccessControl()); + const bool auth = server->qbIPCConnectionAllowed(uid, gid, access_control.get()); + qb_ipcs_context_set(conn, access_control.release()); + +@@ -587,7 +592,7 @@ namespace usbguard + USBGUARD_LOG(Trace) << "uid=" << uid << " gid=" << gid << " ac_ptr=" << ac_ptr; + + bool matched = false; +- const String uid_name = getNameFromUID(uid); ++ const std::string uid_name = getNameFromUID(uid); + const bool check_uid_group_membership = !uid_name.empty(); + + if (!uid_name.empty()) { +@@ -602,7 +607,7 @@ namespace usbguard + } + } + +- const String gid_name = getNameFromGID(gid); ++ const std::string gid_name = getNameFromGID(gid); + + if (!gid_name.empty()) { + const auto& it = _allowed_groupnames.find(gid_name); +@@ -623,7 +628,7 @@ namespace usbguard + */ + for (auto const& allowed_gid_entry : _allowed_gids) { + const auto& allowed_gid = allowed_gid_entry.first; +- const std::vector group_members = getGroupMemberNames(allowed_gid); ++ const std::vector group_members = getGroupMemberNames(allowed_gid); + + for (const auto& group_member : group_members) { + if (group_member == uid_name) { +@@ -641,7 +646,7 @@ namespace usbguard + */ + for (auto const& allowed_groupnames_entry : _allowed_groupnames) { + const auto& allowed_groupname = allowed_groupnames_entry.first; +- const std::vector group_members = getGroupMemberNames(allowed_groupname); ++ const std::vector group_members = getGroupMemberNames(allowed_groupname); + + for (const auto& group_member : group_members) { + if (group_member == uid_name) { +@@ -665,87 +670,87 @@ namespace usbguard + return matched; + } + +- String IPCServerPrivate::getNameFromUID(uid_t uid) ++ std::string IPCServerPrivate::getNameFromUID(uid_t uid) + { +- String buffer(1024, 0); ++ std::string buffer(1024, 0); + struct passwd pw = { }; + struct passwd *pwptr = nullptr; + + if (getpwuid_r(uid, &pw, &buffer[0], buffer.capacity(), &pwptr) != 0) { + USBGUARD_LOG(Warning) << "Unable to lookup username for uid=" << uid << ": errno=" << errno; +- return String(); ++ return std::string(); + } + + if (pwptr == nullptr || pw.pw_name == nullptr) { + USBGUARD_LOG(Info) << "No username associated with uid=" << uid; +- return String(); ++ return std::string(); + } + +- return String(pw.pw_name); ++ return std::string(pw.pw_name); + } + +- String IPCServerPrivate::getNameFromGID(gid_t gid) ++ std::string IPCServerPrivate::getNameFromGID(gid_t gid) + { +- String buffer(4096, 0); ++ std::string buffer(4096, 0); + struct group gr = { }; + struct group *grptr = nullptr; + + if (getgrgid_r(gid, &gr, &buffer[0], buffer.capacity(), &grptr) != 0) { + USBGUARD_LOG(Warning) << "Unable to lookup groupname for gid=" << gid << ": errno=" << errno; +- return String(); ++ return std::string(); + } + + if (grptr == nullptr || gr.gr_name == nullptr) { + USBGUARD_LOG(Info) << "No groupname associated with gid=" << gid; +- return String(); ++ return std::string(); + } + +- return String(gr.gr_name); ++ return std::string(gr.gr_name); + } + +- std::vector IPCServerPrivate::getGroupMemberNames(gid_t gid) ++ std::vector IPCServerPrivate::getGroupMemberNames(gid_t gid) + { +- std::vector names; +- String buffer(4096, 0); ++ std::vector names; ++ std::string buffer(4096, 0); + struct group gr = { }; + struct group *grptr = nullptr; + + if (getgrgid_r(gid, &gr, &buffer[0], buffer.capacity(), &grptr) != 0) { + USBGUARD_LOG(Warning) << "Unable to fetch group members for gid=" << gid << ": errno=" << errno; +- return std::vector(); ++ return std::vector(); + } + + if (grptr == nullptr || gr.gr_name == nullptr) { + USBGUARD_LOG(Info) << "No group associated with gid=" << gid; +- return std::vector(); ++ return std::vector(); + } + + for (size_t i = 0; gr.gr_mem[i] != nullptr; ++i) { +- names.emplace_back(String(gr.gr_mem[i])); ++ names.emplace_back(std::string(gr.gr_mem[i])); + } + + return names; + } + +- std::vector IPCServerPrivate::getGroupMemberNames(const std::string& groupname) ++ std::vector IPCServerPrivate::getGroupMemberNames(const std::string& groupname) + { +- std::vector names; +- String buffer(4096, 0); ++ std::vector names; ++ std::string buffer(4096, 0); + struct group gr = { }; + struct group *grptr = nullptr; + + if (getgrnam_r(groupname.c_str(), &gr, &buffer[0], buffer.capacity(), &grptr) != 0) { + USBGUARD_LOG(Warning) << "Unable to fetch group member names for groupname=" << groupname << ": errno=" << errno; +- return std::vector(); ++ return std::vector(); + } + + if (grptr == nullptr || gr.gr_name == nullptr) { + USBGUARD_LOG(Info) << "Can't find group with name=" << groupname; +- return std::vector(); ++ return std::vector(); + } + + for (size_t i = 0; gr.gr_mem[i] != nullptr; ++i) { +- names.emplace_back(String(gr.gr_mem[i])); ++ names.emplace_back(std::string(gr.gr_mem[i])); + } + + return names; +diff --git a/src/Library/IPCServerPrivate.hpp b/src/Library/IPCServerPrivate.hpp +index 8c4629b..4ee1429 100644 +--- a/src/Library/IPCServerPrivate.hpp ++++ b/src/Library/IPCServerPrivate.hpp +@@ -17,12 +17,21 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include "Typedefs.hpp" +-#include "IPCServer.hpp" ++#endif ++ + #include "IPCPrivate.hpp" + #include "Common/Thread.hpp" + ++#include "Devices.pb.h" ++#include "Policy.pb.h" ++#include "Exception.pb.h" ++#include "Parameter.pb.h" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/IPCServer.hpp" ++ + #include + #include + #include +@@ -30,11 +39,6 @@ + #include + #include + +-#include "Devices.pb.h" +-#include "Policy.pb.h" +-#include "Exception.pb.h" +-#include "Parameter.pb.h" +- + namespace usbguard { + class IPCServerPrivate + { +@@ -97,10 +101,10 @@ namespace usbguard { + bool matchACLByGID(gid_t gid, IPCServer::AccessControl * const ac_ptr) const; + bool matchACLByName(uid_t uid, gid_t gid, IPCServer::AccessControl * const ac_ptr) const; + +- static String getNameFromUID(uid_t uid); +- static String getNameFromGID(gid_t gid); +- static std::vector getGroupMemberNames(gid_t gid); +- static std::vector getGroupMemberNames(const std::string& groupname); ++ static std::string getNameFromUID(uid_t uid); ++ static std::string getNameFromGID(gid_t gid); ++ static std::vector getGroupMemberNames(gid_t gid); ++ static std::vector getGroupMemberNames(const std::string& groupname); + + static void qbIPCSendMessage(qb_ipcs_connection_t *qb_conn, const IPC::MessagePointer& message); + static IPCServer::AccessControl::Section messageTypeNameToAccessControlSection(const std::string& name); +diff --git a/src/Library/Init.cpp b/src/Library/Init.cpp +index c4acbc5..23b81a5 100644 +--- a/src/Library/Init.cpp ++++ b/src/Library/Init.cpp +@@ -16,7 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #include "IPCServerPrivate.hpp" + #include "IPCClientPrivate.hpp" +diff --git a/src/Library/Interface.hpp b/src/Library/Interface.hpp +deleted file mode 100644 +index 5acc99a..0000000 +--- a/src/Library/Interface.hpp ++++ /dev/null +@@ -1,71 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-namespace usbguard +-{ +- class DLL_PUBLIC Interface +- { +- public: +- /* Parameters */ +- virtual std::string setParameter(const std::string& name, const std::string& value) = 0; +- virtual std::string getParameter(const std::string& name) = 0; +- +- /* Methods */ +- virtual uint32_t appendRule(const std::string& rule_spec, +- uint32_t parent_id) = 0; +- +- virtual void removeRule(uint32_t id) = 0; +- +- virtual const RuleSet listRules(const std::string& query) = 0; +- +- virtual uint32_t applyDevicePolicy(uint32_t id, +- Rule::Target target, +- bool permanent) = 0; +- +- virtual const std::vector listDevices(const std::string& query) = 0; +- +- /* Signals */ +- virtual void DevicePresenceChanged(uint32_t id, +- DeviceManager::EventType event, +- Rule::Target target, +- const std::string& device_rule) = 0; +- +- virtual void DevicePolicyChanged(uint32_t id, +- Rule::Target target_old, +- Rule::Target target_new, +- const std::string& device_rule, +- uint32_t rule_id) = 0; +- +- virtual void ExceptionMessage(const std::string& context, +- const std::string& object, +- const std::string& reason) = 0; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/LocaltimeCondition.cpp b/src/Library/LocaltimeCondition.cpp +index 0ed05e8..7299875 100644 +--- a/src/Library/LocaltimeCondition.cpp ++++ b/src/Library/LocaltimeCondition.cpp +@@ -16,9 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "LocaltimeCondition.hpp" +-#include "RuleParser.hpp" + #include "Common/Utility.hpp" ++ ++#include "usbguard/RuleParser.hpp" ++ + #ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE + #include +@@ -26,11 +32,11 @@ + + namespace usbguard + { +- LocaltimeCondition::LocaltimeCondition(const String& time_range, bool negated) ++ LocaltimeCondition::LocaltimeCondition(const std::string& time_range, bool negated) + : RuleConditionBase("localtime", time_range, negated) + { +- String time_begin; +- String time_end; ++ std::string time_begin; ++ std::string time_end; + const size_t dash_pos = time_range.find('-'); + + if (dash_pos == std::string::npos) { +@@ -106,7 +112,7 @@ namespace usbguard + return tm_string; + } + +- std::time_t LocaltimeCondition::stringToDaytime(const String& string) ++ std::time_t LocaltimeCondition::stringToDaytime(const std::string& string) + { + USBGUARD_LOG(Trace) << "string=" << string; + struct ::tm tm = { }; +diff --git a/src/Library/LocaltimeCondition.hpp b/src/Library/LocaltimeCondition.hpp +index c7672c6..8ff5663 100644 +--- a/src/Library/LocaltimeCondition.hpp ++++ b/src/Library/LocaltimeCondition.hpp +@@ -17,24 +17,31 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Rule.hpp" ++ + #include ++#include + + namespace usbguard + { + class LocaltimeCondition : public RuleConditionBase + { + public: +- LocaltimeCondition(const String& time_range, bool negated = false); ++ LocaltimeCondition(const std::string& time_range, bool negated = false); + LocaltimeCondition(const LocaltimeCondition& rhs); + bool update(const Rule& rule); + RuleConditionBase * clone() const; + + protected: +- static std::time_t stringToDaytime(const String& string); +- static String tmToString(const struct ::tm * const tm); ++ static std::time_t stringToDaytime(const std::string& string); ++ static std::string tmToString(const struct ::tm * const tm); + + private: + std::time_t _daytime_begin; +diff --git a/src/Library/Logger.cpp b/src/Library/Logger.cpp +deleted file mode 100644 +index a2c4d7a..0000000 +--- a/src/Library/Logger.cpp ++++ /dev/null +@@ -1,407 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +- +-#include "Logger.hpp" +-#include "Exception.hpp" +-#include "Common/Utility.hpp" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifndef __STDC_FORMAT_MACROS +-#define __STDC_FORMAT_MACROS +-#endif +-#include +- +-namespace usbguard +-{ +- /* Instantiate the logger */ +- Logger G_logger; +- +- const std::string LogStream::sourceToString(const Source& source) +- { +- return source.file + "@" + std::to_string(source.line) + "/" + source.function; +- } +- +- const std::string LogStream::levelToString(Level level) +- { +- switch (level) { +- case LogStream::Level::Audit: +- return "(A)"; +- case LogStream::Level::Error: +- return "(E)"; +- case LogStream::Level::Warning: +- return "(W)"; +- case LogStream::Level::Info: +- return "(i)"; +- case LogStream::Level::Debug: +- return "(D)"; +- case LogStream::Level::Trace: +- return "(T)"; +- default: +- throw std::runtime_error("BUG: unknown LogStream level value"); +- } +- } +- +- LogStream::LogStream(Logger& logger, const Source& source, const Level level) +- : _logger(logger), +- _source(source), +- _level(level) +- { +- } +- +- LogStream::LogStream(const LogStream& rhs) +- : std::basic_ios(), +- std::ostringstream(rhs.str()), +- _logger(rhs._logger), +- _source(rhs._source), +- _level(rhs._level) +- { +- } +- +- LogStream::~LogStream() +- { +- _logger.write(_source, _level, str()); +- } +- +- LogSink::LogSink(const std::string& name) +- : _name(name) +- { +- } +- +- LogSink::~LogSink() +- { +- } +- +- const std::string& LogSink::name() const +- { +- return _name; +- } +- +- /* +- * Internally required sinks +- */ +- class OStreamSink : public LogSink +- { +- public: +- OStreamSink(const std::string& name, std::ostream& stream) +- : LogSink(name), +- _ostream(stream) +- { +- } +- +- void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) +- { +- _ostream << '[' << Logger::timestamp() << "] "; +- _ostream << LogStream::levelToString(level) << " "; +- if (level >= LogStream::Level::Debug) { +- _ostream << LogStream::sourceToString(source) << ": "; +- } +- _ostream << message; +- _ostream << std::endl; +- } +- +- ~OStreamSink() +- { +- _ostream.flush(); +- } +- private: +- std::ostream& _ostream; +- }; +- +- class ConsoleSink : public OStreamSink +- { +- public: +- ConsoleSink() +- : OStreamSink("console", std::clog) +- { +- } +- }; +- +- class SyslogSink : public LogSink +- { +- public: +- SyslogSink(const std::string& ident) +- : LogSink("syslog"), +- _ident(ident) +- { +- openlog(_ident.c_str(), LOG_NDELAY|LOG_PID|LOG_CONS, LOG_DAEMON); +- } +- +- ~SyslogSink() +- { +- closelog(); +- } +- +- int levelToPriority(const LogStream::Level level) +- { +- switch (level) { +- case LogStream::Level::Audit: +- return LOG_NOTICE; +- case LogStream::Level::Error: +- return LOG_ERR; +- case LogStream::Level::Warning: +- return LOG_WARNING; +- case LogStream::Level::Info: +- return LOG_INFO; +- case LogStream::Level::Debug: +- case LogStream::Level::Trace: +- return LOG_DEBUG; +- default: +- throw USBGUARD_BUG("Invalid LogStream::Level value"); +- } +- } +- +- void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) +- { +- std::string log_message; +- +- if (level >= LogStream::Level::Debug) { +- log_message.append(LogStream::sourceToString(source)); +- log_message.append(": "); +- } +- log_message.append(message); +- +- syslog(levelToPriority(level), "%s", log_message.c_str()); +- } +- +- private: +- std::string _ident; +- }; +- +- class FileSink : public OStreamSink +- { +- public: +- FileSink(const std::string& filepath, bool append = true) +- : OStreamSink("file", _stream) +- { +- _filepath = filepath; +- _stream.open(filepath, append ? std::fstream::app : std::fstream::trunc); +- } +- +- ~FileSink() +- { +- _stream.close(); +- } +- private: +- std::string _filepath; +- std::ofstream _stream; +- }; +- +- class AuditFileSink : public OStreamSink +- { +- public: +- AuditFileSink(const std::string& filepath) +- : OStreamSink("auditfile", _stream) +- { +- _filepath = filepath; +- const auto saved_umask = umask(0177); +- try { +- _stream.open(filepath, std::fstream::app); +- } +- catch(...) { +- umask(saved_umask); +- throw; +- } +- umask(saved_umask); +- } +- +- void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) +- { +- /* +- * AuditFileSink logs only Audit level messages. +- */ +- if (level == LogStream::Level::Audit) { +- OStreamSink::write(source, level, message); +- } +- } +- +- ~AuditFileSink() +- { +- _stream.close(); +- } +- private: +- std::string _filepath; +- std::ofstream _stream; +- }; +- +- Logger::Logger() +- : _enabled(true), +- _level(LogStream::Level::Warning) +- { +- const char * const envval = getenv("USBGUARD_DEBUG"); +- /* +- * If USBGUARD_DEBUG=1 is set in the current environment, +- * set the debugging level to the highest level. +- */ +- if (envval != nullptr && strcmp(envval, "1") == 0) { +- _level = LogStream::Level::Trace; +- } +- setOutputConsole(true); +- } +- +- Logger::~Logger() +- { +- } +- +- std::unique_lock Logger::lock() const +- { +- return std::unique_lock(_mutex); +- } +- +- void Logger::setEnabled(bool state, LogStream::Level level) +- { +- auto L = lock(); +- _enabled = state; +- _level = level; +- } +- +- bool Logger::isEnabled(LogStream::Level level) const +- { +- auto L = lock(); +- return (_enabled && _level >= level); +- } +- +- void Logger::setOutputConsole(const bool state) +- { +- auto L = lock(); +- if (state == true) { +- std::unique_ptr sink(new ConsoleSink); +- addOutputSink_nolock(sink); +- } +- else { +- delOutputSink_nolock("console"); +- } +- } +- +- void Logger::setOutputFile(bool state, const std::string& filepath, bool append) +- { +- auto L = lock(); +- if (state == true) { +- std::unique_ptr sink(new FileSink(filepath, append)); +- addOutputSink_nolock(sink); +- } +- else { +- delOutputSink_nolock("file"); +- } +- } +- +- void Logger::setOutputSyslog(bool state, const std::string& ident) +- { +- auto L = lock(); +- if (state == true) { +- std::unique_ptr sink(new SyslogSink(ident)); +- addOutputSink_nolock(sink); +- } +- else { +- delOutputSink_nolock("syslog"); +- } +- } +- +- void Logger::setAuditFile(bool state, const std::string& filepath) +- { +- auto L = lock(); +- if (state == true) { +- std::unique_ptr sink(new AuditFileSink(filepath)); +- addOutputSink_nolock(sink); +- } +- else { +- delOutputSink_nolock("auditfile"); +- } +- } +- +- void Logger::addOutputSink(std::unique_ptr& sink) +- { +- auto L = lock(); +- addOutputSink_nolock(sink); +- } +- +- void Logger::addOutputSink_nolock(std::unique_ptr& sink) +- { +- _sinks.emplace(sink->name(), std::move(sink)); +- } +- +- void Logger::delOutputSink(const std::string& name) +- { +- auto L = lock(); +- delOutputSink_nolock(name); +- } +- +- void Logger::delOutputSink_nolock(const std::string& name) +- { +- _sinks.erase(name); +- } +- +- LogStream Logger::operator()(const std::string& file, const int line, const std::string& function, LogStream::Level level) +- { +- const LogStream::Source source = { +- filenameFromPath(file, /*include_extension=*/true), line, function +- }; +- return LogStream(*this, source, level); +- } +- +- void Logger::write(const LogStream::Source& source, const LogStream::Level level, const std::string& message) +- { +- auto L = lock(); +- for (auto& kv_pair : _sinks) { +- auto& sink = kv_pair.second; +- try { +- sink->write(source, level, message); +- } +- catch(const std::exception& ex) { +- std::cerr << "Warning: sink->write failed for " << sink->name() << " sink: " << ex.what() << std::endl; +- } +- } +- } +- +- /* +- * Generate a timestamp string in the form: +- * . +- */ +- const std::string Logger::timestamp() +- { +- struct timeval tv_now = { 0, 0 }; +- +- if (gettimeofday(&tv_now, nullptr) != 0) { +- throw std::runtime_error("gettimeofday"); +- } +- +- /* +- * The following piece of code should work fine until +- * Sat Nov 20 17:46:39 UTC 2286. +- */ +- char buffer[16]; +- const int length = snprintf(buffer, sizeof buffer, "%.10" PRIu64 ".%03" PRIu64, +- (uint64_t)tv_now.tv_sec, +- (uint64_t)(tv_now.tv_usec / 1000)); +- +- if (length < 1 || static_cast(length) > (sizeof buffer - 1)) { +- throw std::runtime_error("Failed to convert timestamp to string"); +- } +- +- return std::string(buffer, (size_t)length); +- } +-} /* namespace usbguard */ +- +diff --git a/src/Library/Logger.hpp b/src/Library/Logger.hpp +deleted file mode 100644 +index a6abaad..0000000 +--- a/src/Library/Logger.hpp ++++ /dev/null +@@ -1,135 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include "Typedefs.hpp" +- +-#include +-#include +-#include +-#include +-#include +- +-namespace usbguard +-{ +- class Logger; +- +- class DLL_PUBLIC LogStream : public std::ostringstream +- { +- public: +- struct Source { +- std::string file; +- int line; +- std::string function; +- }; +- +- static const std::string sourceToString(const Source& source); +- +- enum class Level : int { +- Audit = -2, +- Error = -1, +- Warning = 0, +- Info = 1, +- Debug = 2, +- Trace = 3 +- }; +- +- static const std::string levelToString(Level level); +- +- LogStream(Logger& logger, const Source& source, Level level); +- LogStream(const LogStream& rhs); +- +- ~LogStream(); +- +- private: +- Logger& _logger; +- Source _source; +- Level _level; +- }; +- +- class DLL_PUBLIC LogSink +- { +- public: +- LogSink(const std::string& name); +- virtual ~LogSink(); +- +- const std::string& name() const; +- +- virtual void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) = 0; +- +- private: +- std::string _name; +- }; +- +- class DLL_PUBLIC Logger +- { +- public: +- Logger(); +- ~Logger(); +- +- void setEnabled(bool state, LogStream::Level level = LogStream::Level::Warning); +- bool isEnabled(LogStream::Level level) const; +- +- void setOutputConsole(bool state); +- void setOutputFile(bool state, const std::string& filepath = std::string(), bool append = true); +- void setOutputSyslog(bool state, const std::string& ident = std::string()); +- void setAuditFile(bool state, const std::string& filepath); +- +- void addOutputSink(std::unique_ptr& sink); +- void delOutputSink(const std::string& name); +- +- LogStream operator()(const std::string& file, int line, const std::string& function, LogStream::Level level); +- +- void write(const LogStream::Source& source, LogStream::Level level, const std::string& message); +- +- /* +- * Generate a timestamp string in the form: +- * . +- */ +- static const std::string timestamp(); +- +- private: +- void addOutputSink_nolock(std::unique_ptr& sink); +- void delOutputSink_nolock(const std::string& name); +- +- std::unique_lock lock() const; +- +- mutable std::mutex _mutex; +- bool _enabled; +- LogStream::Level _level; +- std::map> _sinks; +- }; +- +- extern DLL_PUBLIC Logger G_logger; +- +-#if defined(__GNUC__) +-# define USBGUARD_SOURCE_FILE __BASE_FILE__ +-#else +-# define USBGUARD_SOURCE_FILE __FILE__ +-#endif +- +-#define USBGUARD_LOGGER usbguard::G_logger +- +-#define USBGUARD_FUNCTION __func__ +- +-#define USBGUARD_LOG(level) \ +- if (USBGUARD_LOGGER.isEnabled(usbguard::LogStream::Level::level)) \ +- USBGUARD_LOGGER(USBGUARD_SOURCE_FILE, __LINE__, USBGUARD_FUNCTION, usbguard::LogStream::Level::level) +- +-} /* namespace usbguard */ +diff --git a/src/Library/Policy.cpp b/src/Library/Policy.cpp +deleted file mode 100644 +index fd30d40..0000000 +--- a/src/Library/Policy.cpp ++++ /dev/null +@@ -1,37 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "Policy.hpp" +-#include "Exception.hpp" +- +-namespace usbguard +-{ +- std::string Policy::eventTypeToString(Policy::EventType event) +- { +- switch(event) { +- case Policy::EventType::Insert: +- return "Insert"; +- case Policy::EventType::Update: +- return "Update"; +- case Policy::EventType::Remove: +- return "Remove"; +- default: +- throw USBGUARD_BUG("unknown Policy::EventType value"); +- } +- } +-} /* namespace usbguard */ +diff --git a/src/Library/Policy.hpp b/src/Library/Policy.hpp +deleted file mode 100644 +index f670e4b..0000000 +--- a/src/Library/Policy.hpp ++++ /dev/null +@@ -1,38 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +- +-namespace usbguard +-{ +- class DLL_PUBLIC Policy +- { +- public: +- enum class EventType +- { +- Insert = 1, +- Update = 2, +- Remove = 3, +- }; +- +- static std::string eventTypeToString(EventType event); +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/Predicates.hpp b/src/Library/Predicates.hpp +deleted file mode 100644 +index 21c54a2..0000000 +--- a/src/Library/Predicates.hpp ++++ /dev/null +@@ -1,38 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include "Typedefs.hpp" +-#include +- +-namespace usbguard +-{ +- namespace Predicates DLL_PUBLIC +- { +- /* +- * Return true if the source set is a subset of the +- * target set. Otherwise return false. +- */ +- template +- bool isSubsetOf(const T& source, const T& target) +- { +- USBGUARD_LOG(Trace) << "generic isSubsetOf"; +- return source == target; +- } +- } +-} /* namespace usbguard */ +diff --git a/src/Library/RandomStateCondition.cpp b/src/Library/RandomStateCondition.cpp +index 4ebf12c..57bf4e5 100644 +--- a/src/Library/RandomStateCondition.cpp ++++ b/src/Library/RandomStateCondition.cpp +@@ -16,13 +16,19 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "RandomStateCondition.hpp" +-#include "RuleParser.hpp" ++ ++#include "usbguard/RuleParser.hpp" ++ + #include + + namespace usbguard + { +- RandomStateCondition::RandomStateCondition(const String& true_probability, bool negated) ++ RandomStateCondition::RandomStateCondition(const std::string& true_probability, bool negated) + : RuleConditionBase("random", true_probability, negated), + _rng_gen(_rng_device()), + _true_probability(true_probability.empty() ? 0.5 : std::stod(true_probability)), +diff --git a/src/Library/RandomStateCondition.hpp b/src/Library/RandomStateCondition.hpp +index a26d68a..ce9910a 100644 +--- a/src/Library/RandomStateCondition.hpp ++++ b/src/Library/RandomStateCondition.hpp +@@ -17,9 +17,15 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Rule.hpp" ++ ++#include "usbguard/RuleCondition.hpp" ++ + #include + + namespace usbguard +@@ -27,7 +33,7 @@ namespace usbguard + class RandomStateCondition : public RuleConditionBase + { + public: +- RandomStateCondition(const String& true_probability, bool negated = false); ++ RandomStateCondition(const std::string& true_probability, bool negated = false); + RandomStateCondition(const RandomStateCondition& rhs); + bool update(const Rule& rule); + RuleConditionBase * clone() const; +diff --git a/src/Library/Rule.cpp b/src/Library/Rule.cpp +deleted file mode 100644 +index 18ecb03..0000000 +--- a/src/Library/Rule.cpp ++++ /dev/null +@@ -1,356 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "RulePrivate.hpp" +-#include "Common/Utility.hpp" +- +-namespace usbguard { +- template<> +- String toRuleString(const String& value) +- { +- return Utility::quoteEscapeString(value); +- } +- +- const uint32_t Rule::RootID = std::numeric_limits::min(); +- const uint32_t Rule::DefaultID = std::numeric_limits::max(); +- const uint32_t Rule::LastID = std::numeric_limits::max() - 2; +- const uint32_t Rule::ImplicitID = std::numeric_limits::max() - 1; +- +- Rule::Rule() +- { +- d_pointer = new RulePrivate(*this); +- } +- +- Rule::~Rule() +- { +- delete d_pointer; +- d_pointer = nullptr; +- } +- +- Rule::Rule(const Rule& rhs) +- { +- d_pointer = new RulePrivate(*this, *rhs.d_pointer); +- } +- +- const Rule& Rule::operator=(const Rule& rhs) +- { +- RulePrivate* n_pointer = new RulePrivate(*this, *rhs.d_pointer); +- delete d_pointer; +- d_pointer = n_pointer; +- return *this; +- } +- +- void Rule::setRuleID(uint32_t rule_id) +- { +- d_pointer->setRuleID(rule_id); +- } +- +- uint32_t Rule::getRuleID() const +- { +- return d_pointer->getRuleID(); +- } +- +- void Rule::setTarget(Rule::Target target) +- { +- d_pointer->setTarget(target); +- } +- +- Rule::Target Rule::getTarget() const +- { +- return d_pointer->getTarget(); +- } +- +- void Rule::setDeviceID(const USBDeviceID& value) +- { +- d_pointer->setDeviceID(value); +- } +- +- const USBDeviceID& Rule::getDeviceID() const +- { +- return d_pointer->getDeviceID(); +- } +- +- const Rule::Attribute& Rule::attributeDeviceID() const +- { +- return d_pointer->attributeDeviceID(); +- } +- +- Rule::Attribute& Rule::attributeDeviceID() +- { +- return d_pointer->attributeDeviceID(); +- } +- +- void Rule::setSerial(const String& value) +- { +- d_pointer->setSerial(value); +- } +- +- const String& Rule::getSerial() const +- { +- return d_pointer->getSerial(); +- } +- +- const Rule::Attribute& Rule::attributeSerial() const +- { +- return d_pointer->attributeSerial(); +- } +- +- Rule::Attribute& Rule::attributeSerial() +- { +- return d_pointer->attributeSerial(); +- } +- +- void Rule::setName(const String& value) +- { +- d_pointer->setName(value); +- } +- +- const String& Rule::getName() const +- { +- return d_pointer->getName(); +- } +- +- const Rule::Attribute& Rule::attributeName() const +- { +- return d_pointer->attributeName(); +- } +- +- Rule::Attribute& Rule::attributeName() +- { +- return d_pointer->attributeName(); +- } +- +- void Rule::setHash(const String& value) +- { +- d_pointer->setHash(value); +- } +- +- const String& Rule::getHash() const +- { +- return d_pointer->getHash(); +- } +- +- const Rule::Attribute& Rule::attributeHash() const +- { +- return d_pointer->attributeHash(); +- } +- +- Rule::Attribute& Rule::attributeHash() +- { +- return d_pointer->attributeHash(); +- } +- +- void Rule::setParentHash(const String& value) +- { +- d_pointer->setParentHash(value); +- } +- +- const String& Rule::getParentHash() const +- { +- return d_pointer->getParentHash(); +- } +- +- const Rule::Attribute& Rule::attributeParentHash() const +- { +- return d_pointer->attributeParentHash(); +- } +- +- Rule::Attribute& Rule::attributeParentHash() +- { +- return d_pointer->attributeParentHash(); +- } +- +- void Rule::setViaPort(const String& value) +- { +- d_pointer->setViaPort(value); +- } +- +- const String& Rule::getViaPort() const +- { +- return d_pointer->getViaPort(); +- } +- +- const Rule::Attribute& Rule::attributeViaPort() const +- { +- return d_pointer->attributeViaPort(); +- } +- +- Rule::Attribute& Rule::attributeViaPort() +- { +- return d_pointer->attributeViaPort(); +- } +- +- const Rule::Attribute& Rule::attributeWithInterface() const +- { +- return d_pointer->attributeWithInterface(); +- } +- +- Rule::Attribute& Rule::attributeWithInterface() +- { +- return d_pointer->attributeWithInterface(); +- } +- +- const Rule::Attribute& Rule::attributeConditions() const +- { +- return d_pointer->attributeConditions(); +- } +- +- Rule::Attribute& Rule::attributeConditions() +- { +- return d_pointer->attributeConditions(); +- } +- +- void Rule::setTimeoutSeconds(uint32_t timeout_seconds) +- { +- d_pointer->setTimeoutSeconds(timeout_seconds); +- } +- +- uint32_t Rule::getTimeoutSeconds() const +- { +- return d_pointer->getTimeoutSeconds(); +- } +- +- bool Rule::appliesTo(Pointer rhs) const +- { +- return appliesTo(*rhs); +- } +- +- bool Rule::appliesTo(const Rule& rhs) const +- { +- return d_pointer->appliesTo(rhs); +- } +- +- bool Rule::appliesTo(const Rule& rhs) +- { +- updateMetaDataCounters(/*applied=*/false, /*evaluated=*/true); +- return d_pointer->appliesTo(rhs); +- } +- +- bool Rule::isImplicit() const +- { +- return d_pointer->getRuleID() == Rule::DefaultID; +- } +- +- Rule::operator bool() const +- { +- return !(getTarget() == Target::Unknown || +- getTarget() == Target::Invalid); +- } +- +- String Rule::toString(bool invalid) const +- { +- return d_pointer->toString(invalid); +- } +- +- void Rule::updateMetaDataCounters(bool applied, bool evaluated) +- { +- d_pointer->updateMetaDataCounters(applied, evaluated); +- } +- +- Rule Rule::fromString(const String& rule_string) +- { +- return RulePrivate::fromString(rule_string); +- } +- +- RulePrivate* Rule::internal() +- { +- return d_pointer; +- } +- +- const RulePrivate* Rule::internal() const +- { +- return d_pointer; +- } +- +- static const std::vector > target_ttable = { +- { "allow", Rule::Target::Allow }, +- { "block", Rule::Target::Block }, +- { "reject", Rule::Target::Reject }, +- { "match", Rule::Target::Match }, +- { "device", Rule::Target::Device } +- }; +- +- const String Rule::targetToString(const Rule::Target target) +- { +- for (auto ttable_entry : target_ttable) { +- if (ttable_entry.second == target) { +- return ttable_entry.first; +- } +- } +- throw std::runtime_error("Invalid rule target string"); +- } +- +- Rule::Target Rule::targetFromString(const String& target_string) +- { +- for (auto ttable_entry : target_ttable) { +- if (ttable_entry.first == target_string) { +- return ttable_entry.second; +- } +- } +- throw std::runtime_error("Invalid rule target string"); +- } +- +- uint32_t Rule::targetToInteger(const Rule::Target target) +- { +- return static_cast(target); +- } +- +- Rule::Target Rule::targetFromInteger(const uint32_t target_integer) +- { +- switch(target_integer) { +- case static_cast(Rule::Target::Allow): +- case static_cast(Rule::Target::Block): +- case static_cast(Rule::Target::Reject): +- case static_cast(Rule::Target::Match): +- case static_cast(Rule::Target::Device): +- break; +- default: +- throw std::runtime_error("Invalid rule target integer value"); +- } +- return static_cast(target_integer); +- } +- +- static const std::vector > set_operator_ttable = { +- { "all-of", Rule::SetOperator::AllOf }, +- { "one-of", Rule::SetOperator::OneOf }, +- { "none-of", Rule::SetOperator::NoneOf }, +- { "equals", Rule::SetOperator::Equals }, +- { "equals-ordered", Rule::SetOperator::EqualsOrdered }, +- { "match", Rule::SetOperator::Match } +- }; +- +- const String Rule::setOperatorToString(const Rule::SetOperator& op) +- { +- for (auto ttable_entry : set_operator_ttable) { +- if (ttable_entry.second == op) { +- return ttable_entry.first; +- } +- } +- throw std::runtime_error("Invalid set operator string"); +- } +- +- Rule::SetOperator Rule::setOperatorFromString(const String& set_operator_string) +- { +- for (auto ttable_entry : set_operator_ttable) { +- if (ttable_entry.first == set_operator_string) { +- return ttable_entry.second; +- } +- } +- throw std::runtime_error("Invalid set operator string"); +- } +-} /* namespace usbguard */ +diff --git a/src/Library/Rule.hpp b/src/Library/Rule.hpp +deleted file mode 100644 +index 37dad59..0000000 +--- a/src/Library/Rule.hpp ++++ /dev/null +@@ -1,480 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include "Typedefs.hpp" +-#include "USB.hpp" +-#include "Predicates.hpp" +-#include "Utility.hpp" +-#include "RuleCondition.hpp" +-#include "Logger.hpp" +-#include "Exception.hpp" +- +-#include +-#include +- +-namespace usbguard { +- template +- String toRuleString(T* const value) +- { +- return value->toRuleString(); +- } +- +- template +- String toRuleString(const T& value) +- { +- return value.toRuleString(); +- } +- +- template<> +- String DLL_PUBLIC toRuleString(const String& value); +- +- class RulePrivate; +- class DLL_PUBLIC Rule +- { +- public: +- /** +- * Rule target enumeration. +- */ +- enum class Target { +- Allow = 0, /**< Devices matching this rule will be authorized */ +- Block = 1, /**< Devices matching this rule will not be authorized */ +- Reject = 2, /**< Devices matching this rule will not be authorized and will be detached */ +- Match = 3, /**< Special target which can be used to trigger actions. The rule wont affect the final decision. */ +- Unknown = 4, /**< Unknown target. Used for default constructed rules. */ +- Device = 5, /**< Special target which can only be used for a rule that represents a single device */ +- Invalid = 6 +- }; +- +- static const String targetToString(Target target); +- static Target targetFromString(const String& target_string); +- +- static uint32_t targetToInteger(Target target); +- static Target targetFromInteger(uint32_t target_integer); +- +- enum class SetOperator +- { +- AllOf, +- OneOf, +- NoneOf, +- Equals, +- EqualsOrdered, +- Match /* Special operator: matches anything, cannot be used directly in a rule */ +- }; +- +- static const String setOperatorToString(const Rule::SetOperator& op); +- static SetOperator setOperatorFromString(const String& set_operator_string); +- +- /**< Sequence number of the (fake) root rule */ +- static const uint32_t RootID; +- /**< Sequence number assigned to default constructed rules. Cannot be used for searching. */ +- static const uint32_t DefaultID; +- /**< Sequence number for specifying that the last rule in the ruleset should be used in context of the operation */ +- static const uint32_t LastID; +- /**< Sequence number of the implicit target rule */ +- static const uint32_t ImplicitID; +- +- template +- class Attribute +- { +- public: +- Attribute(const char * name) +- { +- _name = name; +- _set_operator = SetOperator::Equals; +- } +- +- Attribute(const Attribute& rhs) +- { +- _name = rhs._name; +- _set_operator = rhs._set_operator; +- _values = rhs._values; +- } +- +- void setSetOperator(SetOperator op) +- { +- _set_operator = op; +- } +- +- SetOperator setOperator() const +- { +- return _set_operator; +- } +- +- void append(ValueType&& value) +- { +- _values.emplace_back(std::move(value)); +- } +- +- void append(const ValueType& value) +- { +- _values.push_back(value); +- } +- +- size_t count() const +- { +- return _values.size(); +- } +- +- bool empty() const +- { +- return count() == 0; +- } +- +- void clear() +- { +- _values.clear(); +- _set_operator = SetOperator::Equals; +- } +- +- const ValueType& get() const +- { +- if (count() == 1) { +- return _values[0]; +- } +- else if (count() == 0) { +- throw std::runtime_error("BUG: Accessing an empty attribute"); +- } +- else { +- throw std::runtime_error("BUG: Accessing a multivalued attribute using get()"); +- } +- } +- +- const ValueType& get(size_t index) const +- { +- return _values.at(index); +- } +- +- void set(ValueType&& value) +- { +- if (count() > 1) { +- throw std::runtime_error("BUG: Setting single value for a multivalued attribute"); +- } +- if (count() == 0) { +- append(value); +- } +- else { +- _values[0] = std::move(value); +- } +- } +- +- void set(const ValueType& value) +- { +- if (count() > 1) { +- throw std::runtime_error("BUG: Setting single value for a multivalued attribute"); +- } +- if (count() == 0) { +- append(value); +- } +- else { +- _values[0] = value; +- } +- } +- +- void set(const std::vector& values, SetOperator op) +- { +- _values = values; +- _set_operator = op; +- } +- +- bool appliesTo(const Attribute& target) const +- { +- USBGUARD_LOG(Trace) << "entry:" +- << " source=" << this->toRuleString() +- << " target=" << target.toRuleString(); +- +- bool applies = false; +- +- /* Nothing applies to anything */ +- if (empty()) { +- USBGUARD_LOG(Debug) << "empty source value, setting applies=true"; +- applies = true; +- } +- else { +- USBGUARD_LOG(Debug) << "set_operator=" << setOperatorToString(setOperator()); +- switch(setOperator()) { +- case SetOperator::Match: +- applies = true; +- break; +- case SetOperator::AllOf: +- applies = setSolveAllOf(_values, target._values); +- break; +- case SetOperator::OneOf: +- applies = setSolveOneOf(_values, target._values); +- break; +- case SetOperator::NoneOf: +- applies = setSolveNoneOf(_values, target._values); +- break; +- case SetOperator::Equals: +- applies = setSolveEquals(_values, target._values); +- break; +- case SetOperator::EqualsOrdered: +- applies = setSolveEqualsOrdered(_values, target._values); +- break; +- default: +- throw USBGUARD_BUG("Invalid set operator value"); +- } +- } +- +- USBGUARD_LOG(Trace) << "return:" +- << " applies=" << applies; +- +- return applies; +- } +- +- String toRuleString() const +- { +- String result; +- +- result.append(_name); +- result.append(" "); +- +- const bool nondefault_op = setOperator() != SetOperator::Equals; +- const bool multiset_form = count() > 1 || nondefault_op; +- +- if (multiset_form) { +- if (nondefault_op) { +- result.append(setOperatorToString(setOperator())); +- result.append(" "); +- } +- result.append("{ "); +- } +- +- for(const auto& value : _values) { +- result.append(usbguard::toRuleString(value)); +- result.append(" "); +- } +- +- if (multiset_form) { +- result.append("}"); +- } +- else { +- /* +- * Remove the trailing space in case of a single +- * valued attribute. +- */ +- result.erase(result.end() - 1); +- } +- +- return result; +- } +- +- const std::vector& values() const +- { +- return _values; +- } +- +- std::vector& values() +- { +- return _values; +- } +- +- private: +- /* +- * All of the items in source set must match an item in the target set +- */ +- bool setSolveAllOf(const std::vector& source_set, const std::vector& target_set) const +- { +- USBGUARD_LOG(Trace); +- +- for (auto const& source_item : source_set) { +- bool match = false; +- for (auto const& target_item : target_set) { +- if (Predicates::isSubsetOf(source_item, target_item)) { +- match = true; +- break; +- } +- } +- if (!match) { +- return false; +- } +- } +- return true; +- } +- +- /* +- * At least one of the items in the source set must match an item in the target set +- */ +- bool setSolveOneOf(const std::vector& source_set, const std::vector& target_set) const +- { +- USBGUARD_LOG(Trace); +- +- for (auto const& source_item : source_set) { +- for (auto const& target_item : target_set) { +- if (Predicates::isSubsetOf(source_item, target_item)) { +- return true; +- } +- } +- } +- return false; +- } +- +- /* +- * None of the the items in the rule set must match any item in the +- * applies_to set +- */ +- bool setSolveNoneOf(const std::vector& source_set, const std::vector& target_set) const +- { +- USBGUARD_LOG(Trace); +- +- for (auto const& source_item : source_set) { +- for (auto const& target_item : target_set) { +- if (Predicates::isSubsetOf(source_item, target_item)) { +- return false; +- } +- } +- } +- return true; +- } +- +- /* +- * Every item in the rule set must match one item in the +- * applies_to set and the sets have to have the same number +- * of items +- */ +- bool setSolveEquals(const std::vector& source_set, const std::vector& target_set) const +- { +- USBGUARD_LOG(Trace); +- +- if (source_set.size() != target_set.size()) { +- return false; +- } +- else { +- for (auto const& source_item : source_set) { +- bool match = false; +- for (auto const& target_item : target_set) { +- if (Predicates::isSubsetOf(source_item, target_item)) { +- match = true; +- break; +- } +- } +- if (!match) { +- return false; +- } +- } +- return true; +- } +- } +- +- /* +- * The sets are treated as arrays and they have to me equal +- * (same number of items at the same positions) +- */ +- bool setSolveEqualsOrdered(const std::vector& source_set, const std::vector& target_set) const +- { +- USBGUARD_LOG(Trace); +- +- if (source_set.size() != target_set.size()) { +- return false; +- } +- for (size_t i = 0; i < source_set.size(); ++i) { +- if (!Predicates::isSubsetOf(source_set[i], target_set[i])) { +- return false; +- } +- } +- return false; +- } +- +- String _name; +- SetOperator _set_operator; +- std::vector _values; +- }; +- +- /** +- * Construct a default rule. +- * This rule matches only a default rule and cannot be converted to a string +- * representation. +- */ +- Rule(); +- ~Rule(); +- Rule(const Rule& rhs); +- const Rule& operator=(const Rule& rhs); +- +- void setRuleID(uint32_t rule_id); +- uint32_t getRuleID() const; +- +- void setTarget(Rule::Target target); +- Target getTarget() const; +- +- void setDeviceID(const USBDeviceID& value); +- const USBDeviceID& getDeviceID() const; +- const Attribute& attributeDeviceID() const; +- Attribute& attributeDeviceID(); +- +- void setSerial(const String& value); +- const String& getSerial() const; +- const Attribute& attributeSerial() const; +- Attribute& attributeSerial(); +- +- void setName(const String& value); +- const String& getName() const; +- const Attribute& attributeName() const; +- Attribute& attributeName(); +- +- void setHash(const String& value); +- const String& getHash() const; +- const Attribute& attributeHash() const; +- Attribute& attributeHash(); +- +- void setParentHash(const String& value); +- const String& getParentHash() const; +- const Rule::Attribute& attributeParentHash() const; +- Rule::Attribute& attributeParentHash(); +- +- void setViaPort(const String& value); +- const String& getViaPort() const; +- const Attribute& attributeViaPort() const; +- Attribute& attributeViaPort(); +- +- /* +- * Set/get for a single value isn't useful for the +- * with-interface attribute as it usualy contains +- * multiple values. Therefore, we provide only the +- * attribute accessors in this case. +- */ +- const Attribute& attributeWithInterface() const; +- Attribute& attributeWithInterface(); +- +- const Attribute& attributeConditions() const; +- Attribute& attributeConditions(); +- +- void setTimeoutSeconds(uint32_t timeout_seconds); +- uint32_t getTimeoutSeconds() const; +- +- bool appliesTo(Pointer rhs) const; +- bool appliesTo(const Rule& rhs) const; +- bool appliesTo(const Rule& rhs); +- bool isImplicit() const; +- +- +- operator bool() const; +- String toString(bool invalid = false) const; +- +- void updateMetaDataCounters(bool applied = true, bool evaluated = false); +- +- RulePrivate* internal(); +- const RulePrivate* internal() const; +- +- /*** Static methods ***/ +- static Rule fromString(const String& rule_string); +- +- private: +- RulePrivate* d_pointer; +- }; +-} /* namespace usbguard */ +diff --git a/src/Library/RuleAppliedCondition.cpp b/src/Library/RuleAppliedCondition.cpp +index e3bf95f..cb62316 100644 +--- a/src/Library/RuleAppliedCondition.cpp ++++ b/src/Library/RuleAppliedCondition.cpp +@@ -16,9 +16,15 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "RuleAppliedCondition.hpp" +-#include "RuleParser.hpp" + #include "RulePrivate.hpp" ++ ++#include "usbguard/RuleParser.hpp" ++ + #include + #ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE +@@ -27,7 +33,7 @@ + + namespace usbguard + { +- RuleAppliedCondition::RuleAppliedCondition(const String& elapsed_time, bool negated) ++ RuleAppliedCondition::RuleAppliedCondition(const std::string& elapsed_time, bool negated) + : RuleConditionBase("rule-applied", elapsed_time, negated) + { + _elapsed_time = std::chrono::steady_clock::duration(stringToSeconds(elapsed_time)); +@@ -62,7 +68,7 @@ namespace usbguard + return new RuleAppliedCondition(*this); + } + +- uint64_t RuleAppliedCondition::stringToSeconds(const String& string) ++ uint64_t RuleAppliedCondition::stringToSeconds(const std::string& string) + { + struct ::tm tm = { }; + +diff --git a/src/Library/RuleAppliedCondition.hpp b/src/Library/RuleAppliedCondition.hpp +index d8ab450..46dff42 100644 +--- a/src/Library/RuleAppliedCondition.hpp ++++ b/src/Library/RuleAppliedCondition.hpp +@@ -17,9 +17,15 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Rule.hpp" ++ + #include + + namespace usbguard +@@ -27,12 +33,12 @@ namespace usbguard + class RuleAppliedCondition : public RuleConditionBase + { + public: +- RuleAppliedCondition(const String& elapsed_time, bool negated = false); ++ RuleAppliedCondition(const std::string& elapsed_time, bool negated = false); + RuleAppliedCondition(const RuleAppliedCondition& rhs); + bool update(const Rule& rule); + RuleConditionBase * clone() const; + protected: +- static uint64_t stringToSeconds(const String& string); ++ static uint64_t stringToSeconds(const std::string& string); + private: + std::chrono::steady_clock::duration _elapsed_time; + }; +diff --git a/src/Library/RuleCondition.cpp b/src/Library/RuleCondition.cpp +deleted file mode 100644 +index 79084e8..0000000 +--- a/src/Library/RuleCondition.cpp ++++ /dev/null +@@ -1,225 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "RuleCondition.hpp" +-#include "Rule.hpp" +-#include "Logger.hpp" +- +-#include +-#include +- +-namespace usbguard +-{ +- RuleConditionBase::RuleConditionBase(const String& identifier, const String& parameter, bool negated) +- : _identifier(identifier), +- _parameter(parameter), +- _negated(negated) +- { +- } +- +- RuleConditionBase::RuleConditionBase(const String& identifier, bool negated) +- : _identifier(identifier), +- _negated(negated) +- { +- } +- +- RuleConditionBase::RuleConditionBase(const RuleConditionBase& rhs) +- : _identifier(rhs._identifier), +- _parameter(rhs._parameter), +- _negated(rhs._negated) +- { +- } +- +- RuleConditionBase::~RuleConditionBase() +- { +- fini(); +- } +- +- void RuleConditionBase::init(Interface * const interface_ptr) +- { +- (void)interface_ptr; +- } +- +- void RuleConditionBase::fini() +- { +- } +- +- bool RuleConditionBase::evaluate(const Rule& rule) +- { +- return isNegated() ? !update(rule) : update(rule); +- } +- +- const String& RuleConditionBase::identifier() const +- { +- return _identifier; +- } +- +- const String& RuleConditionBase::parameter() const +- { +- return _parameter; +- } +- +- bool RuleConditionBase::hasParameter() const +- { +- return !_parameter.empty(); +- } +- +- bool RuleConditionBase::isNegated() const +- { +- return _negated; +- } +- +- const String RuleConditionBase::toString() const +- { +- String condition_string; +- +- if (isNegated()) { +- condition_string.append("!"); +- } +- +- condition_string.append(identifier()); +- +- if (hasParameter()) { +- condition_string.append("("); +- condition_string.append(parameter()); /* TODO: Escape parameter string */ +- condition_string.append(")"); +- } +- +- return condition_string; +- } +- +- const String RuleConditionBase::toRuleString() const +- { +- return toString(); +- } +-} /* namespace usbguard */ +- +-#include "AllowedMatchesCondition.hpp" +-#include "LocaltimeCondition.hpp" +-#include "FixedStateCondition.hpp" +-#include "RandomStateCondition.hpp" +-#include "RuleAppliedCondition.hpp" +-#include "RuleEvaluatedCondition.hpp" +- +-#include +-#include +- +-namespace usbguard +-{ +- RuleConditionBase* RuleConditionBase::getImplementation(const String& condition_string) +- { +- if (condition_string.empty()) { +- throw std::runtime_error("Empty condition"); +- } +- +- const bool negated = condition_string[0] == '!'; +- const size_t identifier_start = negated ? 1 : 0; +- const size_t p_pos = condition_string.find_first_of('('); +- +- String identifier; +- String parameter; +- +- if (p_pos == std::string::npos) { +- /* +- * The rest of the condition_string should be +- * a condition identifier -- without a parameter. +- */ +- identifier = condition_string.substr(identifier_start); +- +- if (identifier.size() < 1) { +- throw std::runtime_error("Invalid condition string. Missing identifier."); +- } +- } +- else { +- const size_t parameter_size = condition_string.size() - p_pos; +- +- if (parameter_size < 3 /* two parentheses + at least one character */) { +- throw std::runtime_error("Invalid condition string. Invalid parameter."); +- } +- +- const size_t identifier_size = p_pos - identifier_start; +- identifier = condition_string.substr(identifier_start, identifier_size); +- +- if (condition_string[condition_string.size() - 1] != ')') { +- throw std::runtime_error("Invalid condition string. Malformed parameter."); +- } +- +- parameter = condition_string.substr(p_pos + 1, parameter_size - 2); +- } +- +- return getImplementation(identifier, parameter, negated); +- } +- +- RuleConditionBase* RuleConditionBase::getImplementation(const String& identifier, const String& parameter, bool negated) +- { +- if (identifier == "allowed-matches") { +- return new AllowedMatchesCondition(parameter, negated); +- } +- if (identifier == "localtime") { +- return new LocaltimeCondition(parameter, negated); +- } +- if (identifier == "true") { +- return new FixedStateCondition(true, negated); +- } +- if (identifier == "false") { +- return new FixedStateCondition(false, negated); +- } +- if (identifier == "random") { +- return new RandomStateCondition(parameter, negated); +- } +- if (identifier == "rule-applied") { +- return new RuleAppliedCondition(parameter, negated); +- } +- if (identifier == "rule-evaluated") { +- return new RuleEvaluatedCondition(parameter, negated); +- } +- throw std::runtime_error("Unknown rule condition"); +- } +- +- RuleCondition::RuleCondition() +- { +- } +- +- RuleCondition::RuleCondition(const String& condition_string) +- : _condition(RuleConditionBase::getImplementation(condition_string)) +- { +- } +- +- RuleCondition::RuleCondition(const RuleCondition& rhs) +- : _condition(rhs._condition->clone()) +- { +- } +- +- RuleCondition::RuleCondition(RuleCondition&& rhs) +- : _condition(std::move(rhs._condition)) +- { +- } +- +- RuleCondition& RuleCondition::operator=(const RuleCondition& rhs) +- { +- _condition.reset(rhs._condition->clone()); +- return *this; +- } +- +- RuleCondition& RuleCondition::operator=(RuleCondition&& rhs) +- { +- _condition = std::move(rhs._condition); +- return *this; +- } +-} /* namespace usbguard */ +- +diff --git a/src/Library/RuleCondition.hpp b/src/Library/RuleCondition.hpp +deleted file mode 100644 +index aec979b..0000000 +--- a/src/Library/RuleCondition.hpp ++++ /dev/null +@@ -1,87 +0,0 @@ +-// +-// Copyright (C) 2016 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include "Typedefs.hpp" +- +-namespace usbguard +-{ +- class Interface; +- class Rule; +- class RuleConditionBase +- { +- public: +- RuleConditionBase(const String& identifier, const String& parameter, bool negated = false); +- RuleConditionBase(const String& identifier, bool negated = false); +- RuleConditionBase(const RuleConditionBase& rhs); +- virtual ~RuleConditionBase(); +- +- virtual void init(Interface * const interface_ptr); +- virtual void fini(); +- virtual bool update(const Rule& rule) = 0; +- virtual RuleConditionBase* clone() const = 0; +- +- bool evaluate(const Rule& rule); +- const String& identifier() const; +- const String& parameter() const; +- bool hasParameter() const; +- bool isNegated() const; +- const String toString() const; +- const String toRuleString() const; +- +- static RuleConditionBase* getImplementation(const String& condition_string); +- static RuleConditionBase* getImplementation(const String& identifier, const String& parameter, bool negated); +- +- private: +- const String _identifier; +- const String _parameter; +- const bool _negated; +- }; +- +- class RuleCondition +- { +- public: +- RuleCondition(); +- RuleCondition(const String& condition_string); +- RuleCondition(const RuleCondition& rhs); +- RuleCondition(RuleCondition&& rhs); +- +- RuleCondition& operator=(const RuleCondition& rhs); +- RuleCondition& operator=(RuleCondition&& rhs); +- +- RuleConditionBase* operator->() +- { +- return _condition.get(); +- } +- +- RuleConditionBase& operator*() +- { +- return *_condition.get(); +- } +- +- String toRuleString() const +- { +- return _condition->toRuleString(); +- } +- +- private: +- UniquePointer _condition; +- }; +-} /*namespace usbguard */ +- +diff --git a/src/Library/RuleEvaluatedCondition.cpp b/src/Library/RuleEvaluatedCondition.cpp +index 68d93ed..81ea728 100644 +--- a/src/Library/RuleEvaluatedCondition.cpp ++++ b/src/Library/RuleEvaluatedCondition.cpp +@@ -16,10 +16,17 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "RuleEvaluatedCondition.hpp" +-#include "RuleParser.hpp" + #include "RulePrivate.hpp" ++ ++#include "usbguard/RuleParser.hpp" ++ + #include ++ + #ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE + #include +@@ -27,7 +34,7 @@ + + namespace usbguard + { +- RuleEvaluatedCondition::RuleEvaluatedCondition(const String& elapsed_time, bool negated) ++ RuleEvaluatedCondition::RuleEvaluatedCondition(const std::string& elapsed_time, bool negated) + : RuleConditionBase("rule-applied", elapsed_time, negated) + { + _elapsed_time = std::chrono::steady_clock::duration(stringToSeconds(elapsed_time)); +@@ -62,7 +69,7 @@ namespace usbguard + return new RuleEvaluatedCondition(*this); + } + +- uint64_t RuleEvaluatedCondition::stringToSeconds(const String& string) ++ uint64_t RuleEvaluatedCondition::stringToSeconds(const std::string& string) + { + struct ::tm tm = { }; + +diff --git a/src/Library/RuleEvaluatedCondition.hpp b/src/Library/RuleEvaluatedCondition.hpp +index 3595dc2..967c38e 100644 +--- a/src/Library/RuleEvaluatedCondition.hpp ++++ b/src/Library/RuleEvaluatedCondition.hpp +@@ -17,9 +17,15 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" +-#include "RuleCondition.hpp" +-#include "Rule.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/Rule.hpp" ++ + #include + + namespace usbguard +@@ -27,14 +33,13 @@ namespace usbguard + class RuleEvaluatedCondition : public RuleConditionBase + { + public: +- RuleEvaluatedCondition(const String& elapsed_time, bool negated = false); ++ RuleEvaluatedCondition(const std::string& elapsed_time, bool negated = false); + RuleEvaluatedCondition(const RuleEvaluatedCondition& rhs); + bool update(const Rule& rule); + RuleConditionBase * clone() const; + protected: +- static uint64_t stringToSeconds(const String& string); ++ static uint64_t stringToSeconds(const std::string& string); + private: + std::chrono::steady_clock::duration _elapsed_time; + }; + } /* namespace usbguard */ +- +diff --git a/src/Library/RuleParser.cpp b/src/Library/RuleParser.cpp +deleted file mode 100644 +index 40a0a08..0000000 +--- a/src/Library/RuleParser.cpp ++++ /dev/null +@@ -1,81 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include +- +-#include "RuleParser.hpp" +-#include "RuleParser/Grammar.hpp" +-#include "RuleParser/Actions.hpp" +- +-#include "Typedefs.hpp" +-#include "RulePrivate.hpp" +-#include "USB.hpp" +-#include "Common/Utility.hpp" +-#include "Logger.hpp" +- +-#include +-#include +-#include +- +-#include +- +-namespace usbguard +-{ +- Rule parseRuleFromString(const String& rule_spec, const String& file, size_t line, bool trace) +- { +- try { +- Rule rule; +-#if HAVE_PEGTL_LTE_1_3_1 +- if (!trace) { +- pegtl::parse(rule_spec, file, rule); +- } +- else { +- pegtl::parse(rule_spec, file, rule); +- } +-#else +- if (!trace) { +- pegtl::parse_string(rule_spec, file, rule); +- } +- else { +- pegtl::parse_string(rule_spec, file, rule); +- } +-#endif +- return rule; +- } +- catch(const pegtl::parse_error& ex) { +- RuleParserError error(rule_spec); +- +- error.setHint(ex.what()); +-#if HAVE_PEGTL_LTE_1_3_1 +- error.setOffset(ex.positions[0].column); +-#else +- error.setOffset(ex.positions[0].byte_in_line); +-#endif +- +- if (!file.empty() || line != 0) { +- error.setFileInfo(file, line); +- } +- +- throw error; +- } +- catch(const std::exception& ex) { +- +- throw; +- } +- } +-} /* namespace usbguard */ +diff --git a/src/Library/RuleParser.hpp b/src/Library/RuleParser.hpp +deleted file mode 100644 +index 265aacd..0000000 +--- a/src/Library/RuleParser.hpp ++++ /dev/null +@@ -1,105 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include "Typedefs.hpp" +-#include "Rule.hpp" +-#include +- +-namespace usbguard +-{ +- class RuleParserError : public std::exception +- { +- public: +- RuleParserError(const std::string& rule_spec, const std::string& hint = "", +- const std::string& file = "", size_t error_line = 0, unsigned int error_offset = 0) +- : _rule_spec(rule_spec), +- _hint(hint), +- _offset(error_offset), +- _file(file), +- _line(error_line) +- { +- } +- +- void setHint(const std::string& hint) +- { +- _hint = hint; +- } +- +- void setOffset(size_t offset) +- { +- _offset = offset; +- } +- +- void setFileInfo(const std::string& file, size_t error_line, size_t error_offset = 0) +- { +- _file = file; +- _line = error_line; +- _offset = error_offset; +- } +- +- const char *what() const noexcept +- { +- return "RuleParserError"; +- } +- +- const std::string& rule() const +- { +- return _rule_spec; +- } +- +- const std::string& hint() const +- { +- return _hint; +- } +- +- bool hasFileInfo() const +- { +- return !_file.empty(); +- } +- +- const std::string fileInfo() const +- { +- return _file + ": line=" + std::to_string(_line) + ": offset=" + std::to_string(_offset); +- } +- +- const std::string& file() const +- { +- return _file; +- } +- +- size_t line() const +- { +- return _line; +- } +- +- size_t offset() const +- { +- return _offset; +- } +- +- protected: +- const std::string _rule_spec; +- std::string _hint; +- size_t _offset; +- std::string _file; +- size_t _line; +- }; +- +- DLL_PUBLIC Rule parseRuleFromString(const String& rule_spec, const String& file = String(), size_t line = 0, bool trace = false); +-} /* namespace usbguard */ +diff --git a/src/Library/RuleParser/Actions.hpp b/src/Library/RuleParser/Actions.hpp +index a11a96b..da63273 100644 +--- a/src/Library/RuleParser/Actions.hpp ++++ b/src/Library/RuleParser/Actions.hpp +@@ -17,7 +17,13 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Utility.hpp" + #include "Common/Utility.hpp" ++ + #include + + namespace usbguard +@@ -76,9 +82,9 @@ namespace usbguard + } + }; + +- static const String stringValueFromRule(const String& value) ++ static const std::string stringValueFromRule(const std::string& value) + { +- const String string_raw(value.substr(1, value.size() - 2)); ++ const std::string string_raw(value.substr(1, value.size() - 2)); + return Utility::unescapeString(string_raw); + } + +diff --git a/src/Library/RuleParser/Grammar.hpp b/src/Library/RuleParser/Grammar.hpp +index b8b21d3..31967b8 100644 +--- a/src/Library/RuleParser/Grammar.hpp ++++ b/src/Library/RuleParser/Grammar.hpp +@@ -17,6 +17,10 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "Actions.hpp" + #include + +diff --git a/src/Library/RulePrivate.cpp b/src/Library/RulePrivate.cpp +index 7a3bdc2..af4477a 100644 +--- a/src/Library/RulePrivate.cpp ++++ b/src/Library/RulePrivate.cpp +@@ -16,11 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "RulePrivate.hpp" +-#include "RuleParser.hpp" +-#include "Logger.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/RuleParser.hpp" ++#include "usbguard/Logger.hpp" ++ + namespace usbguard { + RulePrivate::RulePrivate(Rule& p_instance) + : //_p_instance(p_instance), +@@ -37,7 +42,6 @@ namespace usbguard { + _rule_id = Rule::DefaultID; + _target = Rule::Target::Invalid; + _conditions_state = 0; +- _timeout_seconds = 0; + } + + RulePrivate::RulePrivate(Rule& p_instance, const RulePrivate& rhs) +@@ -71,7 +75,6 @@ namespace usbguard { + _conditions = rhs._conditions; + + _conditions_state = rhs._conditions_state; +- _timeout_seconds = rhs._timeout_seconds; + + return *this; + #if 0 +@@ -94,7 +97,7 @@ namespace usbguard { + { + } + +- bool RulePrivate::appliesTo(Pointer rhs, bool parent_insensitive) const ++ bool RulePrivate::appliesTo(std::shared_ptr rhs, bool parent_insensitive) const + { + return appliesTo(*rhs, parent_insensitive); + } +@@ -247,11 +250,6 @@ namespace usbguard { + _conditions_state = state; + } + +- uint32_t RulePrivate::getTimeoutSeconds() const +- { +- return _timeout_seconds; +- } +- + void RulePrivate::setRuleID(uint32_t rule_id) + { + _rule_id = rule_id; +@@ -292,102 +290,102 @@ namespace usbguard { + return _device_id; + } + +- void RulePrivate::setSerial(const String& value) ++ void RulePrivate::setSerial(const std::string& value) + { + _serial.set(value); + } + +- const String& RulePrivate::getSerial() const ++ const std::string& RulePrivate::getSerial() const + { + return _serial.get(); + } + +- const Rule::Attribute& RulePrivate::attributeSerial() const ++ const Rule::Attribute& RulePrivate::attributeSerial() const + { + return _serial; + } + +- Rule::Attribute& RulePrivate::attributeSerial() ++ Rule::Attribute& RulePrivate::attributeSerial() + { + return _serial; + } + +- void RulePrivate::setName(const String& value) ++ void RulePrivate::setName(const std::string& value) + { + _name.set(value); + } + +- const String& RulePrivate::getName() const ++ const std::string& RulePrivate::getName() const + { + return _name.get(); + } + +- const Rule::Attribute& RulePrivate::attributeName() const ++ const Rule::Attribute& RulePrivate::attributeName() const + { + return _name; + } + +- Rule::Attribute& RulePrivate::attributeName() ++ Rule::Attribute& RulePrivate::attributeName() + { + return _name; + } + +- void RulePrivate::setHash(const String& value) ++ void RulePrivate::setHash(const std::string& value) + { + _hash.set(value); + } + +- const String& RulePrivate::getHash() const ++ const std::string& RulePrivate::getHash() const + { + return _hash.get(); + } + +- const Rule::Attribute& RulePrivate::attributeHash() const ++ const Rule::Attribute& RulePrivate::attributeHash() const + { + return _hash; + } + +- Rule::Attribute& RulePrivate::attributeHash() ++ Rule::Attribute& RulePrivate::attributeHash() + { + return _hash; + } + +- void RulePrivate::setParentHash(const String& value) ++ void RulePrivate::setParentHash(const std::string& value) + { + _parent_hash.set(value); + } + +- const String& RulePrivate::getParentHash() const ++ const std::string& RulePrivate::getParentHash() const + { + return _parent_hash.get(); + } + +- const Rule::Attribute& RulePrivate::attributeParentHash() const ++ const Rule::Attribute& RulePrivate::attributeParentHash() const + { + return _parent_hash; + } + +- Rule::Attribute& RulePrivate::attributeParentHash() ++ Rule::Attribute& RulePrivate::attributeParentHash() + { + return _parent_hash; + } + +- void RulePrivate::setViaPort(const String& value) ++ void RulePrivate::setViaPort(const std::string& value) + { + _via_port.set(value); + } + +- const String& RulePrivate::getViaPort() const ++ const std::string& RulePrivate::getViaPort() const + { + return _via_port.get(); + } + +- const Rule::Attribute& RulePrivate::attributeViaPort() const ++ const Rule::Attribute& RulePrivate::attributeViaPort() const + { + return _via_port; + } + +- Rule::Attribute& RulePrivate::attributeViaPort() ++ Rule::Attribute& RulePrivate::attributeViaPort() + { + return _via_port; + } +@@ -412,13 +410,8 @@ namespace usbguard { + return _conditions; + } + +- void RulePrivate::setTimeoutSeconds(uint32_t timeout_seconds) +- { +- _timeout_seconds = timeout_seconds; +- } +- + template +- static void toString_appendNonEmptyAttribute(String& rule_string, const Rule::Attribute& attribute) ++ static void toString_appendNonEmptyAttribute(std::string& rule_string, const Rule::Attribute& attribute) + { + if (attribute.empty()) { + return; +@@ -430,9 +423,9 @@ namespace usbguard { + return; + } + +- String RulePrivate::toString(bool invalid) const ++ std::string RulePrivate::toString(bool invalid) const + { +- String rule_string; ++ std::string rule_string; + + try { + rule_string.append(Rule::targetToString(_target)); +@@ -467,7 +460,7 @@ namespace usbguard { + return _meta; + } + +- Rule RulePrivate::fromString(const String& rule_string) ++ Rule RulePrivate::fromString(const std::string& rule_string) + { + return parseRuleFromString(rule_string); + } +diff --git a/src/Library/RulePrivate.hpp b/src/Library/RulePrivate.hpp +index c9fdd21..f32ca55 100644 +--- a/src/Library/RulePrivate.hpp ++++ b/src/Library/RulePrivate.hpp +@@ -17,9 +17,14 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include "Rule.hpp" +-#include "RuleCondition.hpp" ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Rule.hpp" ++ + #include + + namespace usbguard { +@@ -56,7 +61,7 @@ namespace usbguard { + const RulePrivate& operator=(const RulePrivate& rhs); + ~RulePrivate(); + +- bool appliesTo(Pointer rhs, bool parent_insensitive = false) const; ++ bool appliesTo(std::shared_ptr rhs, bool parent_insensitive = false) const; + bool appliesTo(const Rule& rhs, bool parent_insensitive = false) const; + bool appliesToWithConditions(const Rule& rhs, bool with_update = false); + +@@ -78,30 +83,30 @@ namespace usbguard { + const Rule::Attribute& attributeDeviceID() const; + Rule::Attribute& attributeDeviceID(); + +- void setSerial(const String& value); +- const String& getSerial() const; +- const Rule::Attribute& attributeSerial() const; +- Rule::Attribute& attributeSerial(); ++ void setSerial(const std::string& value); ++ const std::string& getSerial() const; ++ const Rule::Attribute& attributeSerial() const; ++ Rule::Attribute& attributeSerial(); + +- void setName(const String& value); +- const String& getName() const; +- const Rule::Attribute& attributeName() const; +- Rule::Attribute& attributeName(); ++ void setName(const std::string& value); ++ const std::string& getName() const; ++ const Rule::Attribute& attributeName() const; ++ Rule::Attribute& attributeName(); + +- void setHash(const String& value); +- const String& getHash() const; +- const Rule::Attribute& attributeHash() const; +- Rule::Attribute& attributeHash(); ++ void setHash(const std::string& value); ++ const std::string& getHash() const; ++ const Rule::Attribute& attributeHash() const; ++ Rule::Attribute& attributeHash(); + +- void setParentHash(const String& value); +- const String& getParentHash() const; +- const Rule::Attribute& attributeParentHash() const; +- Rule::Attribute& attributeParentHash(); ++ void setParentHash(const std::string& value); ++ const std::string& getParentHash() const; ++ const Rule::Attribute& attributeParentHash() const; ++ Rule::Attribute& attributeParentHash(); + +- void setViaPort(const String& value); +- const String& getViaPort() const; +- const Rule::Attribute& attributeViaPort() const; +- Rule::Attribute& attributeViaPort(); ++ void setViaPort(const std::string& value); ++ const std::string& getViaPort() const; ++ const Rule::Attribute& attributeViaPort() const; ++ Rule::Attribute& attributeViaPort(); + + /* + * Set/get for a single value isn't useful for the +@@ -115,17 +120,14 @@ namespace usbguard { + const Rule::Attribute& attributeConditions() const; + Rule::Attribute& attributeConditions(); + +- void setTimeoutSeconds(uint32_t timeout_seconds); +- uint32_t getTimeoutSeconds() const; +- +- String toString(bool invalid = false) const; ++ std::string toString(bool invalid = false) const; + + MetaData& metadata(); + const MetaData& metadata() const; + void updateMetaDataCounters(bool applied = true, bool evaluated = false); + + /*** Static methods ***/ +- static Rule fromString(const String& rule_string); ++ static Rule fromString(const std::string& rule_string); + + private: + //Rule& _p_instance; +@@ -133,14 +135,13 @@ namespace usbguard { + uint32_t _rule_id; + Rule::Target _target; + Rule::Attribute _device_id; +- Rule::Attribute _serial; +- Rule::Attribute _name; +- Rule::Attribute _hash; +- Rule::Attribute _parent_hash; +- Rule::Attribute _via_port; ++ Rule::Attribute _serial; ++ Rule::Attribute _name; ++ Rule::Attribute _hash; ++ Rule::Attribute _parent_hash; ++ Rule::Attribute _via_port; + Rule::Attribute _with_interface; + Rule::Attribute _conditions; + uint64_t _conditions_state; +- uint32_t _timeout_seconds; + }; + } +diff --git a/src/Library/RuleSet.cpp b/src/Library/RuleSet.cpp +deleted file mode 100644 +index d1e70e9..0000000 +--- a/src/Library/RuleSet.cpp ++++ /dev/null +@@ -1,127 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "Typedefs.hpp" +-#include "RuleSetPrivate.hpp" +- +-namespace usbguard { +- RuleSet::RuleSet(Interface * const interface_ptr) +- { +- d_pointer = new RuleSetPrivate(*this, interface_ptr); +- } +- +- RuleSet::~RuleSet() +- { +- delete d_pointer; +- d_pointer = nullptr; +- } +- +- RuleSet::RuleSet(const RuleSet& rhs) +- { +- d_pointer = new RuleSetPrivate(*this, *rhs.d_pointer); +- } +- +- const RuleSet& RuleSet::operator=(const RuleSet& rhs) +- { +- RuleSetPrivate * n_pointer = new RuleSetPrivate(*this, *rhs.d_pointer); +- delete d_pointer; +- d_pointer = n_pointer; +- return *this; +- } +- +- void RuleSet::load(const String& path) +- { +- d_pointer->load(path); +- } +- +- void RuleSet::load(std::istream& stream) +- { +- d_pointer->load(stream); +- } +- +- void RuleSet::save(const String& path) const +- { +- d_pointer->save(path); +- } +- +- void RuleSet::save(std::ostream& stream) const +- { +- d_pointer->save(stream); +- } +- +- void RuleSet::setDefaultTarget(Rule::Target target) +- { +- d_pointer->setDefaultTarget(target); +- } +- +- Rule::Target RuleSet::getDefaultTarget() const +- { +- return d_pointer->getDefaultTarget(); +- } +- +- void RuleSet::setDefaultAction(const String& action) +- { +- d_pointer->setDefaultAction(action); +- } +- +- uint32_t RuleSet::appendRule(const Rule& rule, uint32_t parent_id) +- { +- return d_pointer->appendRule(rule, parent_id); +- } +- +- uint32_t RuleSet::upsertRule(const Rule& match_rule, const Rule& new_rule, const bool parent_insensitive) +- { +- return d_pointer->upsertRule(match_rule, new_rule, parent_insensitive); +- } +- +- Pointer RuleSet::getRule(uint32_t id) +- { +- return d_pointer->getRule(id); +- } +- +- bool RuleSet::removeRule(uint32_t id) +- { +- return d_pointer->removeRule(id); +- } +- +- Pointer RuleSet::getFirstMatchingRule(Pointer device_rule, uint32_t from_id) const +- { +- return d_pointer->getFirstMatchingRule(device_rule, from_id); +- } +- +- PointerVector RuleSet::getRules() +- { +- return d_pointer->getRules(); +- } +- +- Pointer RuleSet::getTimedOutRule() +- { +- return d_pointer->getTimedOutRule(); +- } +- +- uint32_t RuleSet::assignID(Pointer rule) +- { +- return d_pointer->assignID(rule); +- } +- +- uint32_t RuleSet::assignID() +- { +- return d_pointer->assignID(); +- } +- +-} /* namespace usbguard */ +diff --git a/src/Library/RuleSet.hpp b/src/Library/RuleSet.hpp +deleted file mode 100644 +index 07ffa82..0000000 +--- a/src/Library/RuleSet.hpp ++++ /dev/null +@@ -1,143 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include +-#include +-#include +-#include +- +-namespace usbguard { +- class RuleSetPrivate; +- class Interface; +- class DLL_PUBLIC RuleSet +- { +- public: +- /** +- * Construct an empty ruleset. +- */ +- RuleSet(Interface * const interface_ptr); +- RuleSet(const RuleSet& rhs); +- const RuleSet& operator=(const RuleSet& rhs); +- ~RuleSet(); +- +- /** +- * Load a ruleset from a file at `path'. +- * Internally, this opens an input file stream and calls load(std::istream& stream). +- */ +- void load(const String& path); +- +- /** +- * Load a ruleset from an input stream. +- * The stream is read using std::getline() and each line is parsed as a separate rule. +- * Empty lines are skipped. +- */ +- void load(std::istream& stream); +- +- /** +- * Save the ruleset to a file at `path'. +- * If a file exists at `path', it will be overwritten. Internally, this opens an output +- * stream and calls save(std::ostream& stream). +- */ +- void save(const String& path) const; +- +- /** +- * Write the ruleset to an output stream. +- * Each rule is serialized to it's string representation and written line by line to +- * the output stream. +- */ +- void save(std::ostream& stream) const; +- +- /** +- * Set an implicit default target which will be used if there's no match for a device +- * rule. +- */ +- void setDefaultTarget(Rule::Target target); +- +- /** +- * Get the implicit target value. +- */ +- Rule::Target getDefaultTarget() const; +- +- /** +- * Set an implicit default action which will be used if there's no match for a device +- * rule. +- */ +- void setDefaultAction(const String& action); +- +- /** +- * Assign a sequence number to a rule and append it to the rule set. +- * If `parent_id' is not specified, the rule will be appended at the end od the ruleset. +- * The method returns the sequence number assigned to the rule. +- */ +- uint32_t appendRule(const Rule& rule, uint32_t parent_id = Rule::LastID); +- +- /** +- * Search for a rule that matches `match_rule' rule and update it with a rule specified +- * by `new_rule'. Fail if multiple rules match. If there are no matching rules, append +- * the `new_rule' rule to the rule set. +- * +- * Returns the id of the updated or new rule. +- */ +- uint32_t upsertRule(const Rule& match_rule, const Rule& new_rule, bool parent_insensitive = false); +- +- /** +- * Get a rule pointer to a rule with the specified sequence number. +- * Returns nullptr if no such rule exists. +- */ +- Pointer getRule(uint32_t id); +- +- /** +- * Remove a rule from the ruleset. +- * The method returns true if a rule was removed and false otherwise. +- */ +- bool removeRule(uint32_t id); +- +- /** +- * Find first rule in the ruleset which matched the specified device rule. +- * If `from_id' isn't specified, the method searches from the beginning of the ruleset. +- * If no matching rule is found, nullptr is returned. +- */ +- Pointer getFirstMatchingRule(Pointer device_rule, uint32_t from_id = 1) const; +- +- /** +- * Get all rules from the set. +- */ +- PointerVector getRules(); +- +- /** +- * Get the oldest rule that timed out and should be removed from the ruleset. +- * Returns nullptr if there are not timed out rules. +- */ +- Pointer getTimedOutRule(); +- +- /** +- * Assign a unique sequence number to a rule. +- * Return the assigned sequence number. +- */ +- uint32_t assignID(Pointer rule); +- +- /** +- * Generate a unique sequence number. +- */ +- uint32_t assignID(); +- +- private: +- RuleSetPrivate* d_pointer; +- }; +-} +diff --git a/src/Library/RuleSetPrivate.cpp b/src/Library/RuleSetPrivate.cpp +index 6188fc3..fe447d9 100644 +--- a/src/Library/RuleSetPrivate.cpp ++++ b/src/Library/RuleSetPrivate.cpp +@@ -16,11 +16,17 @@ + // + // Authors: Daniel Kopecek + // +-#include "Typedefs.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "RuleSetPrivate.hpp" + #include "RulePrivate.hpp" +-#include "RuleParser.hpp" +-#include "Exception.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/RuleParser.hpp" ++#include "usbguard/Exception.hpp" ++ + #include + + namespace usbguard { +@@ -31,7 +37,7 @@ namespace usbguard { + { + (void)_p_instance; + _default_target = Rule::Target::Block; +- _default_action = String(); ++ _default_action = std::string(); + _id_next = Rule::RootID + 1; + } + +@@ -48,7 +54,6 @@ namespace usbguard { + _default_action = rhs._default_action; + _id_next = rhs._id_next.load(); + _rules = rhs._rules; +- _rules_timed = rhs._rules_timed; + return *this; + } + +@@ -56,7 +61,7 @@ namespace usbguard { + { + } + +- void RuleSetPrivate::load(const String& path) ++ void RuleSetPrivate::load(const std::string& path) + { + std::ifstream stream(path); + if (!stream.is_open()) { +@@ -81,7 +86,7 @@ namespace usbguard { + } while(stream.good()); + } + +- void RuleSetPrivate::save(const String& path) const ++ void RuleSetPrivate::save(const std::string& path) const + { + std::ofstream stream(path, std::fstream::trunc); + if (!stream.is_open()) { +@@ -113,7 +118,7 @@ namespace usbguard { + return _default_target; + } + +- void RuleSetPrivate::setDefaultAction(const String& action) ++ void RuleSetPrivate::setDefaultAction(const std::string& action) + { + std::unique_lock op_lock(_op_mutex); + _default_action = action; +@@ -127,7 +132,7 @@ namespace usbguard { + op_lock.lock(); + } + +- auto rule_ptr = makePointer(rule); ++ auto rule_ptr = std::make_shared(rule); + + /* + * If the rule doesn't already have a sequence number +@@ -167,18 +172,13 @@ namespace usbguard { + } + } + +- /* If the rule is timed, put it into the priority queue */ +- if (rule_ptr->getTimeoutSeconds() > 0) { +- _rules_timed.push(rule_ptr); +- } +- + return rule_ptr->getRuleID(); + } + + uint32_t RuleSetPrivate::upsertRule(const Rule& match_rule, const Rule& new_rule, const bool parent_insensitive) + { + std::unique_lock op_lock(_op_mutex); +- Pointer matching_rule; ++ std::shared_ptr matching_rule; + + for (auto& rule_ptr : _rules) { + if (rule_ptr->internal()->appliesTo(match_rule, parent_insensitive)) { +@@ -202,7 +202,7 @@ namespace usbguard { + } + } + +- Pointer RuleSetPrivate::getRule(uint32_t id) ++ std::shared_ptr RuleSetPrivate::getRule(uint32_t id) + { + std::unique_lock op_lock(_op_mutex); + for (auto const& rule : _rules) { +@@ -227,7 +227,7 @@ namespace usbguard { + throw Exception("Rule set remove", "rule id", "id doesn't exist"); + } + +- Pointer RuleSetPrivate::getFirstMatchingRule(Pointer device_rule, uint32_t from_id) const ++ std::shared_ptr RuleSetPrivate::getFirstMatchingRule(std::shared_ptr device_rule, uint32_t from_id) const + { + (void)from_id; /* TODO */ + std::unique_lock op_lock(_op_mutex); +@@ -238,7 +238,7 @@ namespace usbguard { + } + } + +- Pointer default_rule = makePointer(); ++ std::shared_ptr default_rule = std::make_shared(); + + default_rule->setRuleID(Rule::ImplicitID); + default_rule->setTarget(_default_target); +@@ -246,9 +246,9 @@ namespace usbguard { + return default_rule; + } + +- PointerVector RuleSetPrivate::getRules() ++ std::vector> RuleSetPrivate::getRules() + { +- PointerVector rules; ++ std::vector> rules; + + for (auto const& rule : _rules) { + rules.push_back(rule); +@@ -257,29 +257,7 @@ namespace usbguard { + return rules; + } + +- Pointer RuleSetPrivate::getTimedOutRule() +- { +- std::unique_lock op_lock(_op_mutex); +- +- if (_rules_timed.size() < 1) { +- return nullptr; +- } +- +- Pointer oldest_rule = _rules_timed.top(); +- std::chrono::steady_clock::time_point tp_current = \ +- std::chrono::steady_clock::now(); +- +- if ((tp_current - oldest_rule->internal()->metadata().tp_created) \ +- < std::chrono::seconds(oldest_rule->getTimeoutSeconds())) { +- return nullptr; +- } else { +- _rules_timed.pop(); +- } +- +- return oldest_rule; +- } +- +- uint32_t RuleSetPrivate::assignID(Pointer rule) ++ uint32_t RuleSetPrivate::assignID(std::shared_ptr rule) + { + rule->setRuleID(assignID()); + return rule->getRuleID(); +diff --git a/src/Library/RuleSetPrivate.hpp b/src/Library/RuleSetPrivate.hpp +index 699a030..e0f4344 100644 +--- a/src/Library/RuleSetPrivate.hpp ++++ b/src/Library/RuleSetPrivate.hpp +@@ -17,9 +17,13 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include +-#include "Typedefs.hpp" +-#include "RuleSet.hpp" ++#endif ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/RuleSet.hpp" ++ + #include + #include + #include +@@ -33,21 +37,20 @@ namespace usbguard { + const RuleSetPrivate& operator=(const RuleSetPrivate& rhs); + ~RuleSetPrivate(); + +- void load(const String& path); ++ void load(const std::string& path); + void load(std::istream& stream); +- void save(const String& path) const; ++ void save(const std::string& path) const; + void save(std::ostream& stream) const; + void setDefaultTarget(Rule::Target target); + Rule::Target getDefaultTarget() const; +- void setDefaultAction(const String& action); ++ void setDefaultAction(const std::string& action); + uint32_t appendRule(const Rule& rule, uint32_t parent_id = Rule::LastID, bool lock = true); + uint32_t upsertRule(const Rule& match_rule, const Rule& new_rule, bool parent_insensitive = false); +- Pointer getRule(uint32_t id); ++ std::shared_ptr getRule(uint32_t id); + bool removeRule(uint32_t id); +- Pointer getFirstMatchingRule(Pointer device_rule, uint32_t from_id = 1) const; +- PointerVector getRules(); +- Pointer getTimedOutRule(); +- uint32_t assignID(Pointer rule); ++ std::shared_ptr getFirstMatchingRule(std::shared_ptr device_rule, uint32_t from_id = 1) const; ++ std::vector> getRules(); ++ uint32_t assignID(std::shared_ptr rule); + uint32_t assignID(); + + private: +@@ -56,9 +59,8 @@ namespace usbguard { + RuleSet& _p_instance; + Interface * const _interface_ptr; + Rule::Target _default_target; +- String _default_action; ++ std::string _default_action; + Atomic _id_next; +- PointerVector _rules; +- PointerPQueue _rules_timed; ++ std::vector> _rules; + }; + } +diff --git a/src/Library/SysFSDevice.cpp b/src/Library/SysFSDevice.cpp +index 3cda3c0..ba20289 100644 +--- a/src/Library/SysFSDevice.cpp ++++ b/src/Library/SysFSDevice.cpp +@@ -16,12 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "SysFSDevice.hpp" +-#include "Logger.hpp" +-#include "Exception.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ + #ifndef _POSIX_C_SOURCE + #define _POSIX_C_SOURCE + #endif +@@ -37,7 +41,7 @@ namespace usbguard + { + } + +- SysFSDevice::SysFSDevice(const String& sysfs_path, bool without_parent) ++ SysFSDevice::SysFSDevice(const std::string& sysfs_path, bool without_parent) + : _sysfs_path(sysfs_path), + _sysfs_name(filenameFromPath(_sysfs_path, /*include_extension=*/true)), + _sysfs_dirfd(-1) +@@ -95,12 +99,12 @@ namespace usbguard + return *this; + } + +- const String& SysFSDevice::getPath() const ++ const std::string& SysFSDevice::getPath() const + { + return _sysfs_path; + } + +- const String& SysFSDevice::getName() const ++ const std::string& SysFSDevice::getName() const + { + return _sysfs_name; + } +@@ -110,12 +114,12 @@ namespace usbguard + return _uevent; + } + +- const String& SysFSDevice::getParentPath() const ++ const std::string& SysFSDevice::getParentPath() const + { + return _sysfs_parent_path; + } + +- int SysFSDevice::openAttribute(const String& name) const ++ int SysFSDevice::openAttribute(const std::string& name) const + { + USBGUARD_LOG(Trace) << "name=" << name; + +@@ -126,21 +130,21 @@ namespace usbguard + return fd; + } + +- String SysFSDevice::readAttribute(const String& name, bool strip_last_null, bool optional) const ++ std::string SysFSDevice::readAttribute(const std::string& name, bool strip_last_null, bool optional) const + { + USBGUARD_LOG(Trace) << "name=" << name; + + const int fd = openat(_sysfs_dirfd, name.c_str(), O_RDONLY); + if (fd < 0) { + if (optional && errno == ENOENT) { +- return String(); ++ return std::string(); + } + else { + throw ErrnoException("SysFSDevice", name, errno); + } + } + try { +- String buffer(4096, 0); ++ std::string buffer(4096, 0); + ssize_t rc = -1; + USBGUARD_SYSCALL_THROW("SysFSDevice", + (rc = read(fd, &buffer[0], buffer.capacity())) < 0); +@@ -150,7 +154,7 @@ namespace usbguard + buffer.resize(static_cast(rc) - 1); + } + else { +- return String(); ++ return std::string(); + } + } + else { +@@ -167,7 +171,7 @@ namespace usbguard + } + } + +- void SysFSDevice::setAttribute(const String& name, const String& value) ++ void SysFSDevice::setAttribute(const std::string& name, const std::string& value) + { + USBGUARD_LOG(Trace) << "name=" << name << " value=" << value; + USBGUARD_LOG(Trace) << "path=" << _sysfs_path; +@@ -195,7 +199,7 @@ namespace usbguard + + void SysFSDevice::reloadUEvent() + { +- const String uevent_string = readAttribute("uevent"); ++ const std::string uevent_string = readAttribute("uevent"); + _uevent = UEvent::fromString(uevent_string, /*attributes_only=*/true); + } + } /* namespace usbguard */ +diff --git a/src/Library/SysFSDevice.hpp b/src/Library/SysFSDevice.hpp +index c159323..2f39ff2 100644 +--- a/src/Library/SysFSDevice.hpp ++++ b/src/Library/SysFSDevice.hpp +@@ -17,9 +17,15 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + + #include "UEvent.hpp" +-#include "Typedefs.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++ ++#include + + namespace usbguard + { +@@ -27,26 +33,26 @@ namespace usbguard + { + public: + SysFSDevice(); +- SysFSDevice(const String& sysfs_path, bool without_parent = false); ++ SysFSDevice(const std::string& sysfs_path, bool without_parent = false); + SysFSDevice(SysFSDevice&& device); + ~SysFSDevice(); + SysFSDevice& operator=(SysFSDevice&& rhs_device); + +- const String& getPath() const; +- const String& getName() const; ++ const std::string& getPath() const; ++ const std::string& getName() const; + const UEvent& getUEvent() const; +- const String& getParentPath() const; +- String readAttribute(const String& name, bool strip_last_null = false, bool optional = false) const; +- void setAttribute(const String& name, const String& value); +- int openAttribute(const String& name) const; ++ const std::string& getParentPath() const; ++ std::string readAttribute(const std::string& name, bool strip_last_null = false, bool optional = false) const; ++ void setAttribute(const std::string& name, const std::string& value); ++ int openAttribute(const std::string& name) const; + + void reload(); + private: + void reloadUEvent(); + +- String _sysfs_path; +- String _sysfs_name; +- String _sysfs_parent_path; ++ std::string _sysfs_path; ++ std::string _sysfs_name; ++ std::string _sysfs_parent_path; + int _sysfs_dirfd; + UEvent _uevent; + }; +diff --git a/src/Library/Typedefs.cpp b/src/Library/Typedefs.cpp +deleted file mode 100644 +index 28464d5..0000000 +--- a/src/Library/Typedefs.cpp ++++ /dev/null +@@ -1,29 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "Typedefs.hpp" +- +-namespace usbguard { +- +- template<> +- bool matches(const String& a, const String& b) +- { +- return a == b; +- } +- +-} /* namespace usbguard */ +diff --git a/src/Library/Typedefs.hpp b/src/Library/Typedefs.hpp +deleted file mode 100644 +index 13b1fc8..0000000 +--- a/src/Library/Typedefs.hpp ++++ /dev/null +@@ -1,145 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-namespace usbguard { +- /* +- * Char string typedefs +- */ +- typedef std::string String; +- typedef std::vector StringVector; +- typedef std::list StringList; +- +- template +- using StringMap = std::map; +- +- template +- using StringKeyMap = std::map; +- +- template +- using StringVectorMap = std::map; +- +- template +- bool matches(const T& a, const T& b) +- { +- return a == b; +- } +- +- template<> +- bool matches(const String& a, const String& b); +- +- /* +- * Smart Pointer typedefs and custom operations +- */ +- template +- using Pointer = std::shared_ptr; +- +- template > +- using UniquePointer = std::unique_ptr; +- +- template +- using PointerVector = std::vector >; +- +- template +- using PointerMap = std::map >; +- +- template +- using PointerPQueue = std::priority_queue >; +- +- template +- static inline Pointer makePointer(Args&&... args) +- { +- return std::make_shared(std::forward(args)...); +- } +- +- template +- static inline UniquePointer makeUniquePointer(Args&&... args) +- { +- return std::move(std::unique_ptr(new pointer_type(std::forward(args)...))); +- } +- +- namespace MapOp { +- template +- typename map_type::mapped_type findOne(const map_type& map, const typename map_type::key_type& key) +- { +- auto it = map.find(key); +- if (it == map.end()) { +- return typename map_type::mapped_type(); +- } else { +- return it->second; +- } +- } +- } +- +- namespace PointerMapOp { +- template +- Pointer findOne(const PointerMap& map, +- const key_type& key) +- { +- auto it = map.find(key); +- if (it == map.end()) { +- return Pointer(nullptr); +- } else { +- return it->second; +- } +- } +- } +- +- /* +- * Atomic +- */ +- template +- using Atomic = std::atomic; +- +- /* +- * Symbol visibility +- */ +- #if defined _WIN32 || defined __CYGWIN__ +- #ifdef BUILDING_DLL +- #ifdef __GNUC__ +- #define DLL_PUBLIC __attribute__ ((dllexport)) +- #else +- #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. +- #endif +- #else +- #ifdef __GNUC__ +- #define DLL_PUBLIC __attribute__ ((dllimport)) +- #else +- #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. +- #endif +- #endif +- #define DLL_LOCAL +- #else +- #if __GNUC__ >= 4 +- #define DLL_PUBLIC __attribute__ ((visibility ("default"))) +- #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) +- #else +- #define DLL_PUBLIC +- #define DLL_LOCAL +- #endif +- #endif +-} /* namespace usbguard */ +diff --git a/src/Library/UEvent.cpp b/src/Library/UEvent.cpp +index c007d7e..a55b421 100644 +--- a/src/Library/UEvent.cpp ++++ b/src/Library/UEvent.cpp +@@ -16,9 +16,14 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "UEvent.hpp" + #include "UEventParser.hpp" +-#include "Logger.hpp" ++ ++#include "usbguard/Logger.hpp" + + namespace usbguard + { +@@ -37,7 +42,7 @@ namespace usbguard + return *this; + } + +- UEvent UEvent::fromString(const String& uevent_string, bool attributes_only, bool trace) ++ UEvent UEvent::fromString(const std::string& uevent_string, bool attributes_only, bool trace) + { + UEvent uevent; + parseUEventFromString(uevent_string, uevent, attributes_only, trace); +@@ -49,35 +54,35 @@ namespace usbguard + _attributes.clear(); + } + +- void UEvent::setAttribute(const String& name, const String& value) ++ void UEvent::setAttribute(const std::string& name, const std::string& value) + { + USBGUARD_LOG(Trace) << "Setting attribute: " << name << "=" << value; + _attributes[name] = value; + } + +- String UEvent::getAttribute(const String& name) const ++ std::string UEvent::getAttribute(const std::string& name) const + { + auto it = _attributes.find(name); + if (it == _attributes.end()) { +- return String(); ++ return std::string(); + } else { + return it->second; + } + } + +- bool UEvent::hasAttribute(const String& name) const ++ bool UEvent::hasAttribute(const std::string& name) const + { + return _attributes.count(name) == 1; + } + +- String UEvent::getHeaderLine() const ++ std::string UEvent::getHeaderLine() const + { + if (!hasAttribute("ACTION") || + !hasAttribute("DEVPATH")) { + throw std::runtime_error("uevent: missing required header line values"); + } + +- String header_line; ++ std::string header_line; + + header_line.append(getAttribute("ACTION")); + header_line.append(1, '@'); +@@ -86,9 +91,9 @@ namespace usbguard + return header_line; + } + +- String UEvent::toString(char separator) const ++ std::string UEvent::toString(char separator) const + { +- String uevent_string = getHeaderLine(); ++ std::string uevent_string = getHeaderLine(); + + uevent_string.append(1, separator); + +@@ -104,7 +109,7 @@ namespace usbguard + + bool UEvent::hasRequiredAttributes() const + { +- for (const String name : { "ACTION", "DEVPATH", "SUBSYSTEM" }) { ++ for (const std::string name : { "ACTION", "DEVPATH", "SUBSYSTEM" }) { + if (!hasAttribute(name)) { + return false; + } +diff --git a/src/Library/UEvent.hpp b/src/Library/UEvent.hpp +index faa7930..f042e0d 100644 +--- a/src/Library/UEvent.hpp ++++ b/src/Library/UEvent.hpp +@@ -17,8 +17,14 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif + +-#include "Typedefs.hpp" ++#include "usbguard/Typedefs.hpp" ++ ++#include ++#include + + namespace usbguard + { +@@ -29,18 +35,18 @@ namespace usbguard + UEvent(UEvent&& rhs); + UEvent& operator=(UEvent&& rhs); + +- static UEvent fromString(const String& uevent_string, bool attributes_only = false, bool trace = false); ++ static UEvent fromString(const std::string& uevent_string, bool attributes_only = false, bool trace = false); + + void clear(); +- void setAttribute(const String& name, const String& value); +- String getAttribute(const String& name) const; +- bool hasAttribute(const String& name) const; ++ void setAttribute(const std::string& name, const std::string& value); ++ std::string getAttribute(const std::string& name) const; ++ bool hasAttribute(const std::string& name) const; + bool hasRequiredAttributes() const; + +- String getHeaderLine() const; +- String toString(char separator = '\0') const; ++ std::string getHeaderLine() const; ++ std::string toString(char separator = '\0') const; + + private: +- StringKeyMap _attributes; ++ std::map _attributes; + }; + } /* namespace usbguard */ +diff --git a/src/Library/UEventDeviceManager.cpp b/src/Library/UEventDeviceManager.cpp +index b6e3418..bdf4ad0 100644 +--- a/src/Library/UEventDeviceManager.cpp ++++ b/src/Library/UEventDeviceManager.cpp +@@ -16,19 +16,22 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #if defined(HAVE_UEVENT) + #include "UEventDeviceManager.hpp" + #include "UEventParser.hpp" + #include "SysFSDevice.hpp" +-#include "Logger.hpp" +-#include "Exception.hpp" +-#include "USB.hpp" + #include "Base64.hpp" + #include "Common/FDInputStream.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++#include "usbguard/USB.hpp" ++ + #include + #include + #include +@@ -51,7 +54,7 @@ namespace usbguard { + * Look for the parent USB device and set the parent id + * if we find one. + */ +- const String sysfs_parent_path(sysfs_device.getParentPath()); ++ const std::string sysfs_parent_path(sysfs_device.getParentPath()); + const SysFSDevice sysfs_parent_device(sysfs_parent_path); + + if (sysfs_parent_device.getUEvent().getAttribute("DEVTYPE") == "usb_device") { +@@ -68,8 +71,8 @@ namespace usbguard { + /* + * Set USB ID + */ +- const String id_vendor(sysfs_device.readAttribute("idVendor", /*strip_last_null=*/true)); +- const String id_product(sysfs_device.readAttribute("idProduct", /*strip_last_null=*/true)); ++ const std::string id_vendor(sysfs_device.readAttribute("idVendor", /*strip_last_null=*/true)); ++ const std::string id_product(sysfs_device.readAttribute("idProduct", /*strip_last_null=*/true)); + const USBDeviceID device_id(id_vendor, id_product); + setDeviceID(device_id); + /* +@@ -83,7 +86,7 @@ namespace usbguard { + /* + * Sync authorization target + */ +- const String authorized_value(sysfs_device.readAttribute("authorized", /*strip_last_null=*/true)); ++ const std::string authorized_value(sysfs_device.readAttribute("authorized", /*strip_last_null=*/true)); + + if (authorized_value == "0") { + setTarget(Rule::Target::Block); +@@ -130,7 +133,7 @@ namespace usbguard { + return _sysfs_device; + } + +- const String& UEventDevice::getSysPath() const ++ const std::string& UEventDevice::getSysPath() const + { + return _sysfs_device.getPath(); + } +@@ -223,7 +226,7 @@ namespace usbguard { + /* + * Manager + */ +- UEventDeviceManager::UEventDeviceManager(DeviceManagerHooks& hooks, const String& sysfs_root, bool dummy_mode) ++ UEventDeviceManager::UEventDeviceManager(DeviceManagerHooks& hooks, const std::string& sysfs_root, bool dummy_mode) + : DeviceManager(hooks), + _thread(this, &UEventDeviceManager::thread), + _uevent_fd(-1), +@@ -321,12 +324,12 @@ namespace usbguard { + } + } + +- Pointer UEventDeviceManager::applyDevicePolicy(uint32_t id, Rule::Target target) ++ std::shared_ptr UEventDeviceManager::applyDevicePolicy(uint32_t id, Rule::Target target) + { + USBGUARD_LOG(Trace) << "id=" << id + << " target=" << Rule::targetToString(target); + +- Pointer device = std::static_pointer_cast(getDevice(id)); ++ std::shared_ptr device = std::static_pointer_cast(getDevice(id)); + std::unique_lock device_lock(device->refDeviceMutex()); + + sysfsApplyTarget(device->sysfsDevice(), target); +@@ -402,8 +405,8 @@ namespace usbguard { + + void UEventDeviceManager::sysfsApplyTarget(SysFSDevice& sysfs_device, Rule::Target target) + { +- String name; +- String value("0"); ++ std::string name; ++ std::string value("0"); + + switch (target) { + case Rule::Target::Allow: +@@ -475,7 +478,7 @@ namespace usbguard { + + void UEventDeviceManager::ueventProcessRead() + { +- String buffer(4096, 0); ++ std::string buffer(4096, 0); + + struct iovec iov[1]; + iov[0].iov_base = (void *)&buffer[0]; +@@ -568,9 +571,9 @@ namespace usbguard { + + void UEventDeviceManager::ueventProcessUEvent(const UEvent& uevent) + { +- const String subsystem = uevent.getAttribute("SUBSYSTEM"); +- const String devtype = uevent.getAttribute("DEVTYPE"); +- const String action = uevent.getAttribute("ACTION"); ++ const std::string subsystem = uevent.getAttribute("SUBSYSTEM"); ++ const std::string devtype = uevent.getAttribute("DEVTYPE"); ++ const std::string action = uevent.getAttribute("ACTION"); + + if (subsystem != "usb" || devtype != "usb_device") { + USBGUARD_LOG(Debug) << "Ignoring non-USB device:" +@@ -580,7 +583,7 @@ namespace usbguard { + return; + } + +- const String sysfs_devpath = _sysfs_root + uevent.getAttribute("DEVPATH"); ++ const std::string sysfs_devpath = _sysfs_root + uevent.getAttribute("DEVPATH"); + + try { + std::unique_lock lock(_enumeration_mutex); +@@ -600,7 +603,7 @@ namespace usbguard { + * Do some additional sanity checking. + */ + if (sysfs_device.getUEvent().hasAttribute("DEVTYPE")) { +- const String devtype = sysfs_device.getUEvent().getAttribute("DEVTYPE"); ++ const std::string devtype = sysfs_device.getUEvent().getAttribute("DEVTYPE"); + if (devtype != "usb_device") { + USBGUARD_LOG(Warning) << sysfs_devpath << ": UEvent DEVTYPE mismatch." + << " Expected \"usb_device\", got \"" << devtype << "\""; +@@ -640,10 +643,10 @@ namespace usbguard { + } + } + +- bool UEventDeviceManager::ueventEnumerateComparePath(const std::pair& a, const std::pair& b) ++ bool UEventDeviceManager::ueventEnumerateComparePath(const std::pair& a, const std::pair& b) + { +- const String base_a = filenameFromPath(a.second, /*include_extension=*/true); +- const String base_b = filenameFromPath(b.second, /*include_extension=*/true); ++ const std::string base_a = filenameFromPath(a.second, /*include_extension=*/true); ++ const std::string base_b = filenameFromPath(b.second, /*include_extension=*/true); + const bool a_has_usb_prefix = (0 == base_a.compare(0, 3, "usb")); + const bool b_has_usb_prefix = (0 == base_b.compare(0, 3, "usb")); + +@@ -673,7 +676,7 @@ namespace usbguard { + USBGUARD_LOG(Trace); + return loadFiles(_sysfs_root + "/bus/usb/devices", + UEventDeviceManager::ueventEnumerateFilterDevice, +- [this](const String& devpath, const String& buspath) ++ [this](const std::string& devpath, const std::string& buspath) + { + return ueventEnumerateTriggerDevice(devpath, buspath); + }, +@@ -685,7 +688,7 @@ namespace usbguard { + USBGUARD_LOG(Trace); + return loadFiles(_sysfs_root + "/bus/usb/devices", + UEventDeviceManager::ueventEnumerateFilterDevice, +- [this](const String& devpath, const String& buspath) ++ [this](const std::string& devpath, const std::string& buspath) + { + (void)buspath; + UEvent uevent; +@@ -704,7 +707,7 @@ namespace usbguard { + UEventDeviceManager::ueventEnumerateComparePath); + } + +- String UEventDeviceManager::ueventEnumerateFilterDevice(const String& filepath, const struct dirent* direntry) ++ std::string UEventDeviceManager::ueventEnumerateFilterDevice(const std::string& filepath, const struct dirent* direntry) + { + #if defined(_DIRENT_HAVE_D_TYPE) + if (direntry->d_type != DT_UNKNOWN) { +@@ -714,7 +717,7 @@ namespace usbguard { + case DT_DIR: + return filepath; + default: +- return String(); ++ return std::string(); + } + } + else { +@@ -729,7 +732,7 @@ namespace usbguard { + * Cannot stat, skip this entry. + */ + USBGUARD_LOG(Warning) << "lstat(" << filepath << "): errno=" << errno; +- return String(); ++ return std::string(); + } + if (S_ISLNK(st.st_mode)) { + return symlinkPath(filepath, &st); +@@ -738,16 +741,16 @@ namespace usbguard { + return filepath; + } + else { +- return String(); ++ return std::string(); + } + #if defined(_DIRENT_HAVE_D_TYPE) + } + #endif + /* UNREACHABLE */ +- return String(); ++ return std::string(); + } + +- int UEventDeviceManager::ueventEnumerateTriggerDevice(const String& devpath, const String& buspath) ++ int UEventDeviceManager::ueventEnumerateTriggerDevice(const std::string& devpath, const std::string& buspath) + { + USBGUARD_LOG(Trace) << "devpath=" << devpath << " buspath=" << buspath; + +@@ -776,7 +779,7 @@ namespace usbguard { + USBGUARD_LOG(Trace) << "id=" << id; + + try { +- Pointer device = \ ++ std::shared_ptr device = \ + std::static_pointer_cast(DeviceManager::getDevice(id)); + + device->sysfsDevice().reload(); +@@ -811,7 +814,7 @@ namespace usbguard { + void UEventDeviceManager::processDeviceInsertion(SysFSDevice& sysfs_device, const bool signal_present) + { + try { +- Pointer device = makePointer(*this, sysfs_device); ++ std::shared_ptr device = std::make_shared(*this, sysfs_device); + + if (device->isController() && !_enumeration_only_mode) { + USBGUARD_LOG(Debug) << "Setting default blocked state for controller device to " << _default_blocked_state; +@@ -861,19 +864,19 @@ namespace usbguard { + sysfsApplyTarget(sysfs_device, Rule::Target::Reject); + } + +- void UEventDeviceManager::insertDevice(Pointer device) ++ void UEventDeviceManager::insertDevice(std::shared_ptr device) + { + DeviceManager::insertDevice(std::static_pointer_cast(device)); + std::unique_lock device_lock(device->refDeviceMutex()); + learnSysPath(device->getSysPath(), device->getID()); + } + +- void UEventDeviceManager::processDeviceRemoval(const String& sysfs_devpath) ++ void UEventDeviceManager::processDeviceRemoval(const std::string& sysfs_devpath) + { + USBGUARD_LOG(Trace) << "sysfs_devpath=" << sysfs_devpath; + + try { +- Pointer device = removeDevice(sysfs_devpath); ++ std::shared_ptr device = removeDevice(sysfs_devpath); + DeviceEvent(DeviceManager::EventType::Remove, device); + } catch(...) { + /* Ignore for now */ +@@ -882,7 +885,7 @@ namespace usbguard { + } + } + +- Pointer UEventDeviceManager::removeDevice(const String& syspath) ++ std::shared_ptr UEventDeviceManager::removeDevice(const std::string& syspath) + { + /* + * FIXME: device map locking +@@ -891,13 +894,13 @@ namespace usbguard { + throw Exception("removeDevice", syspath, "unknown syspath, cannot remove device"); + } + +- Pointer device = DeviceManager::removeDevice(getIDFromSysPath(syspath)); ++ std::shared_ptr device = DeviceManager::removeDevice(getIDFromSysPath(syspath)); + _syspath_map.erase(syspath); + + return device; + } + +- uint32_t UEventDeviceManager::getIDFromSysPath(const String& syspath) const ++ uint32_t UEventDeviceManager::getIDFromSysPath(const std::string& syspath) const + { + uint32_t id = 0; + const bool known = knownSysPath(syspath, &id); +@@ -909,7 +912,7 @@ namespace usbguard { + throw Exception("UEventDeviceManager", syspath, "unknown syspath"); + } + +- bool UEventDeviceManager::knownSysPath(const String& syspath, uint32_t * id_ptr) const ++ bool UEventDeviceManager::knownSysPath(const std::string& syspath, uint32_t * id_ptr) const + { + auto it = _syspath_map.find(syspath); + +@@ -928,13 +931,13 @@ namespace usbguard { + return known; + } + +- void UEventDeviceManager::learnSysPath(const String& syspath, uint32_t id) ++ void UEventDeviceManager::learnSysPath(const std::string& syspath, uint32_t id) + { + USBGUARD_LOG(Trace) << "syspath=" << syspath << " id=" << id; + _syspath_map[syspath] = id; + } + +- void UEventDeviceManager::forgetSysPath(const String& syspath) ++ void UEventDeviceManager::forgetSysPath(const std::string& syspath) + { + _syspath_map.erase(syspath); + } +diff --git a/src/Library/UEventDeviceManager.hpp b/src/Library/UEventDeviceManager.hpp +index 4143fce..b7adb60 100644 +--- a/src/Library/UEventDeviceManager.hpp ++++ b/src/Library/UEventDeviceManager.hpp +@@ -17,22 +17,24 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #if defined(HAVE_UEVENT) + +-#include "Typedefs.hpp" + #include "Common/Thread.hpp" +- +-#include "DeviceManager.hpp" +-#include "Device.hpp" +-#include "Rule.hpp" + #include "SysFSDevice.hpp" +-#include "USB.hpp" + +-#include ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/DeviceManager.hpp" ++#include "usbguard/Device.hpp" ++#include "usbguard/Rule.hpp" ++#include "usbguard/USB.hpp" + ++#include + #include ++ + #include + #include + +@@ -45,7 +47,7 @@ namespace usbguard { + UEventDevice(UEventDeviceManager& device_manager, SysFSDevice& sysfs_device); + + SysFSDevice& sysfsDevice(); +- const String& getSysPath() const; ++ const std::string& getSysPath() const; + bool isController() const override; + + private: +@@ -66,7 +68,7 @@ namespace usbguard { + using DeviceManager::insertDevice; + + public: +- UEventDeviceManager(DeviceManagerHooks& hooks, const String& sysfs_root = USBGUARD_SYSFS_ROOT, bool dummy_mode = false); ++ UEventDeviceManager(DeviceManagerHooks& hooks, const std::string& sysfs_root = USBGUARD_SYSFS_ROOT, bool dummy_mode = false); + ~UEventDeviceManager(); + + void setDefaultBlockedState(bool state) override; +@@ -76,43 +78,43 @@ namespace usbguard { + void stop() override; + void scan() override; + +- Pointer applyDevicePolicy(uint32_t id, Rule::Target target) override; +- void insertDevice(Pointer device); +- Pointer removeDevice(const String& syspath); ++ std::shared_ptr applyDevicePolicy(uint32_t id, Rule::Target target) override; ++ void insertDevice(std::shared_ptr device); ++ std::shared_ptr removeDevice(const std::string& syspath); + +- uint32_t getIDFromSysPath(const String& syspath) const; ++ uint32_t getIDFromSysPath(const std::string& syspath) const; + + protected: + int ueventOpen(); + int ueventDummyOpen(); + void sysfsApplyTarget(SysFSDevice& sysfs_device, Rule::Target target); + +- bool knownSysPath(const String& syspath, uint32_t * id = nullptr) const; +- void learnSysPath(const String& syspath, uint32_t id = 0); +- void forgetSysPath(const String& syspath); ++ bool knownSysPath(const std::string& syspath, uint32_t * id = nullptr) const; ++ void learnSysPath(const std::string& syspath, uint32_t id = 0); ++ void forgetSysPath(const std::string& syspath); + + void thread(); + void ueventProcessRead(); + void ueventProcessUEvent(const UEvent& uevent); +- static bool ueventEnumerateComparePath(const std::pair& a, const std::pair& b); ++ static bool ueventEnumerateComparePath(const std::pair& a, const std::pair& b); + int ueventEnumerateDevices(); + int ueventEnumerateDummyDevices(); + +- static String ueventEnumerateFilterDevice(const String& filepath, const struct dirent* direntry); +- int ueventEnumerateTriggerDevice(const String& devpath, const String& buspath); ++ static std::string ueventEnumerateFilterDevice(const std::string& filepath, const struct dirent* direntry); ++ int ueventEnumerateTriggerDevice(const std::string& devpath, const std::string& buspath); + + void processDevicePresence(SysFSDevice& sysfs_device); + + void processDeviceInsertion(SysFSDevice& sysfs_device, bool signal_present); + void processDevicePresence(uint32_t id); +- void processDeviceRemoval(const String& sysfs_devpath); ++ void processDeviceRemoval(const std::string& sysfs_devpath); + + private: + Thread _thread; + int _uevent_fd; + int _wakeup_fd; +- StringKeyMap _syspath_map; +- String _sysfs_root; ++ std::map _syspath_map; ++ std::string _sysfs_root; + bool _default_blocked_state; + bool _enumeration_only_mode; + bool _dummy_mode; +diff --git a/src/Library/UEventParser.cpp b/src/Library/UEventParser.cpp +index 528f323..d785a6c 100644 +--- a/src/Library/UEventParser.cpp ++++ b/src/Library/UEventParser.cpp +@@ -16,13 +16,16 @@ + // + // Authors: Daniel Kopecek + // ++#ifdef HAVE_BUILD_CONFIG_H + #include ++#endif + + #include "UEventParser.hpp" + #include "UEvent.hpp" +-#include "Logger.hpp" + #include "Common/Utility.hpp" + ++#include "usbguard/Logger.hpp" ++ + #include + #include + +@@ -47,10 +50,10 @@ namespace usbguard + throw pegtl::parse_error("invalid attribute format", in); + } + +- const String key = in.string().substr(0, p); +- const String value = trim(in.string().substr(p + 1, std::string::npos), String("\n\0", 2)); ++ const std::string key = in.string().substr(0, p); ++ const std::string value = trim(in.string().substr(p + 1, std::string::npos), std::string("\n\0", 2)); + +- for (const String header_key : { "ACTION", "DEVPATH" }) { ++ for (const std::string header_key : { "ACTION", "DEVPATH" }) { + if (key == header_key) { + if (value != uevent.getAttribute(header_key)) { + throw pegtl::parse_error("header value mismatch", in); +@@ -90,7 +93,7 @@ namespace usbguard + }; + } /* namespace UEventParser */ + +- void parseUEventFromFile(const String& uevent_path, UEvent& uevent, bool attributes_only, bool trace) ++ void parseUEventFromFile(const std::string& uevent_path, UEvent& uevent, bool attributes_only, bool trace) + { + std::ifstream uevent_stream(uevent_path); + +@@ -111,22 +114,22 @@ namespace usbguard + } + + template +- void parseUEventFromString(const String& uevent_string, UEvent& uevent, bool trace) ++ void parseUEventFromString(const std::string& uevent_string, UEvent& uevent, bool trace) + { + try { + #if HAVE_PEGTL_LTE_1_3_1 + if (!trace) { +- pegtl::parse(uevent_string, String(), uevent); ++ pegtl::parse(uevent_string, std::string(), uevent); + } + else { +- pegtl::parse(uevent_string, String(), uevent); ++ pegtl::parse(uevent_string, std::string(), uevent); + } + #else + if (!trace) { +- pegtl::parse_string(uevent_string, String(), uevent); ++ pegtl::parse_string(uevent_string, std::string(), uevent); + } + else { +- pegtl::parse_string(uevent_string, String(), uevent); ++ pegtl::parse_string(uevent_string, std::string(), uevent); + } + #endif + } +@@ -135,7 +138,7 @@ namespace usbguard + } + } + +- void parseUEventFromString(const String& uevent_string, UEvent& uevent, bool attributes_only, bool trace) ++ void parseUEventFromString(const std::string& uevent_string, UEvent& uevent, bool attributes_only, bool trace) + { + if (attributes_only) { + parseUEventFromString(uevent_string, uevent, trace); +diff --git a/src/Library/UEventParser.hpp b/src/Library/UEventParser.hpp +index 5e42794..4927179 100644 +--- a/src/Library/UEventParser.hpp ++++ b/src/Library/UEventParser.hpp +@@ -17,8 +17,12 @@ + // Authors: Daniel Kopecek + // + #pragma once ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Typedefs.hpp" + +-#include "Typedefs.hpp" + #include + + using namespace pegtl; +@@ -58,6 +62,6 @@ namespace usbguard + + } /* namespace UEventParser */ + +- void parseUEventFromFile(const String& uevent_path, UEvent& uevent, bool attributes_only = false, bool trace = false); +- void parseUEventFromString(const String& uevent_string, UEvent& uevent, bool attributes_only = false, bool trace = false); ++ void parseUEventFromFile(const std::string& uevent_path, UEvent& uevent, bool attributes_only = false, bool trace = false); ++ void parseUEventFromString(const std::string& uevent_string, UEvent& uevent, bool attributes_only = false, bool trace = false); + } /* namespace usbguard */ +diff --git a/src/Library/USB.cpp b/src/Library/USB.cpp +deleted file mode 100644 +index bc4a0fd..0000000 +--- a/src/Library/USB.cpp ++++ /dev/null +@@ -1,519 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include "USB.hpp" +-#include "Common/ByteOrder.hpp" +-#include "Common/Utility.hpp" +-#include "Logger.hpp" +-#include +-#include +-#include +- +-namespace usbguard { +- USBDeviceID::USBDeviceID() +- { +- } +- +- USBDeviceID::USBDeviceID(const String& vendor_id, const String& product_id) +- { +- checkDeviceID(vendor_id, product_id); +- setVendorID(vendor_id); +- setProductID(product_id); +- } +- +- USBDeviceID::USBDeviceID(const USBDeviceID& rhs) +- { +- _vendor_id = rhs._vendor_id; +- _product_id = rhs._product_id; +- } +- +- void USBDeviceID::checkDeviceID(const String& vendor_id, const String& product_id) +- { +- if (vendor_id.empty() || vendor_id == "*") { +- /* product id must be empty or "*" */ +- if (!product_id.empty() && product_id != "*") { +- throw std::runtime_error("Invalid USB device id format"); +- } +- } +- if (vendor_id.size() > USB_VID_STRING_MAX_LENGTH) { +- throw std::runtime_error("Vendor ID string size out of range"); +- } +- if (product_id.size() > USB_PID_STRING_MAX_LENGTH) { +- throw std::runtime_error("Product ID string size out of range"); +- } +- } +- +- void USBDeviceID::setVendorID(const String& vendor_id) +- { +- checkDeviceID(vendor_id, _product_id); +- _vendor_id = vendor_id; +- } +- +- void USBDeviceID::setProductID(const String& product_id) +- { +- checkDeviceID(_vendor_id, product_id); +- _product_id = product_id; +- } +- +- const String& USBDeviceID::getVendorID() const +- { +- return _vendor_id; +- } +- +- const String& USBDeviceID::getProductID() const +- { +- return _product_id; +- } +- +- String USBDeviceID::toRuleString() const +- { +- return _vendor_id + ":" + _product_id; +- } +- +- String USBDeviceID::toString() const +- { +- return toRuleString(); +- } +- +- bool USBDeviceID::isSubsetOf(const USBDeviceID& rhs) const +- { +- if (_vendor_id.empty() || _vendor_id == "*") { +- return true; +- } +- else if (_vendor_id != rhs._vendor_id) { +- return false; +- } +- +- if (_product_id.empty() || _product_id == "*") { +- return true; +- } +- else if (_product_id != rhs._product_id) { +- return false; +- } +- +- return true; +- } +- +- template<> +- bool Predicates::isSubsetOf(const USBDeviceID& source, const USBDeviceID& target) +- { +- USBGUARD_LOG(Trace) << "source=" << source.toString() << " target=" << target.toString(); +- const bool result = source.isSubsetOf(target); +- USBGUARD_LOG(Trace) << "result=" << result; +- return result; +- } +- +- USBInterfaceType::USBInterfaceType() +- { +- _bClass = 0; +- _bSubClass = 0; +- _bProtocol = 0; +- _mask = 0; +- } +- +- USBInterfaceType::USBInterfaceType(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask) +- { +- _bClass = bClass; +- _bSubClass = bSubClass; +- _bProtocol = bProtocol; +- _mask = mask; +- } +- +- USBInterfaceType::USBInterfaceType(const USBInterfaceDescriptor& descriptor, uint8_t mask) +- { +- _bClass = descriptor.bInterfaceClass; +- _bSubClass = descriptor.bInterfaceSubClass; +- _bProtocol = descriptor.bInterfaceProtocol; +- _mask = mask; +- } +- +- USBInterfaceType::USBInterfaceType(const std::string& type_string) +- { +- std::vector tokens; +- tokenizeString(type_string, tokens, ":", /*trim_empty=*/false); +- +- _bClass = 0; +- _bSubClass = 0; +- _bProtocol = 0; +- _mask = 0; +- +- if (tokens.size() != 3) { +- throw std::runtime_error("Invalid type_string"); +- } +- +- if (tokens[0].size() != 2) { +- throw std::runtime_error("Invalid type_string"); +- } +- else { +- _bClass = stringToNumber(tokens[0], 16); +- _mask |= MatchClass; +- } +- +- if (tokens[1] != "*") { +- if (tokens[1].size() != 2) { +- throw std::runtime_error("Invalid type_string"); +- } +- else { +- _bSubClass = stringToNumber(tokens[1], 16); +- _mask |= MatchSubClass; +- } +- } +- +- if (tokens[2] != "*") { +- if (tokens[2].size() != 2) { +- throw std::runtime_error("Invalid type_string"); +- } +- else { +- _bProtocol = stringToNumber(tokens[2], 16); +- _mask |= MatchProtocol; +- } +- } +- +- if (!(_mask == (MatchAll) || +- _mask == (MatchClass|MatchSubClass) || +- _mask == (MatchClass))) { +- throw std::runtime_error("Invalid type_string"); +- } +- } +- +- bool USBInterfaceType::operator==(const USBInterfaceType& rhs) const +- { +- return (_bClass == rhs._bClass && +- _bSubClass == rhs._bSubClass && +- _bProtocol == rhs._bProtocol && +- _mask == rhs._mask); +- } +- +- bool USBInterfaceType::appliesTo(const USBInterfaceType& rhs) const +- { +- if (_mask & MatchClass) { +- if (_bClass != rhs._bClass) { +- return false; +- } +- } +- if (_mask & MatchSubClass) { +- if (_bSubClass != rhs._bSubClass) { +- return false; +- } +- } +- if (_mask & MatchProtocol) { +- if (_bProtocol != rhs._bProtocol) { +- return false; +- } +- } +- return true; +- } +- +- template<> +- bool Predicates::isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target) +- { +- return source.appliesTo(target); +- } +- +- const String USBInterfaceType::typeString() const +- { +- return USBInterfaceType::typeString(_bClass, _bSubClass, _bProtocol, _mask); +- } +- +- const String USBInterfaceType::toRuleString() const +- { +- return typeString(); +- } +- +- const String USBInterfaceType::typeString(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask) +- { +- String type_string(""); +- +- if (mask & MatchClass) { +- type_string.append(numberToString(bClass, "", 16, 2, '0') + ":"); +- +- if (mask & MatchSubClass) { +- type_string.append(numberToString(bSubClass, "", 16, 2, '0') + ":"); +- +- if (mask & MatchProtocol) { +- type_string.append(numberToString(bProtocol, "", 16, 2, '0')); +- } +- else { +- type_string.append("*"); +- } +- } +- else { +- type_string.append("*:*"); +- } +- } +- else { +- throw std::runtime_error("BUG: cannot create type string, invalid mask"); +- } +- +- return type_string; +- } +- +- void USBParseDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- const USBDeviceDescriptor* device_raw = reinterpret_cast(descriptor_raw); +- USBDeviceDescriptor* device_out = reinterpret_cast(descriptor_out); +- +- /* Copy 1:1 */ +- *device_out = *device_raw; +- +- /* Convert multibyte field to host endianness */ +- device_out->bcdUSB = busEndianToHost(device_raw->bcdUSB); +- device_out->idVendor = busEndianToHost(device_raw->idVendor); +- device_out->idProduct = busEndianToHost(device_raw->idProduct); +- device_out->bcdDevice = busEndianToHost(device_raw->bcdDevice); +- } +- +- void USBParseConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- const USBConfigurationDescriptor* configuration_raw = reinterpret_cast(descriptor_raw); +- USBConfigurationDescriptor* configuration_out = reinterpret_cast(descriptor_out); +- +- /* Copy 1:1 */ +- *configuration_out = *configuration_raw; +- +- /* Convert multibyte field to host endianness */ +- configuration_out->wTotalLength = busEndianToHost(configuration_raw->wTotalLength); +- } +- +- void USBParseInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- const USBInterfaceDescriptor* interface_raw = reinterpret_cast(descriptor_raw); +- USBInterfaceDescriptor* interface_out = reinterpret_cast(descriptor_out); +- +- /* Copy 1:1 */ +- *interface_out = *interface_raw; +- } +- +- void USBParseEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- const USBEndpointDescriptor* endpoint_raw = reinterpret_cast(descriptor_raw); +- USBEndpointDescriptor* endpoint_out = reinterpret_cast(descriptor_out); +- +- *endpoint_out = *endpoint_raw; +- endpoint_out->wMaxPacketSize = busEndianToHost(endpoint_raw->wMaxPacketSize); +- } +- +- void USBParseAudioEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- const USBAudioEndpointDescriptor* endpoint_raw = reinterpret_cast(descriptor_raw); +- USBAudioEndpointDescriptor* endpoint_out = reinterpret_cast(descriptor_out); +- +- *endpoint_out = *endpoint_raw; +- endpoint_out->wMaxPacketSize = busEndianToHost(endpoint_raw->wMaxPacketSize); +- } +- +- void USBParseUnknownDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- (void)parser; +- *descriptor_out = *descriptor_raw; +- } +- +- void USBDescriptorParserHooks::parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) +- { +- USBGUARD_LOG(Trace); +- +- const auto type = static_cast(descriptor_raw->bHeader.bDescriptorType); +- const auto size = descriptor_raw->bHeader.bLength; +- +- switch(type) { +- case USBDescriptorType::Device: +- switch (size) { +- case sizeof(USBDeviceDescriptor): +- USBParseDeviceDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- default: +- throw Exception("USB descriptor parser", "device descriptor", "unexpected descriptor size"); +- } +- break; +- case USBDescriptorType::Configuration: +- switch (size) { +- case sizeof(USBConfigurationDescriptor): +- USBParseConfigurationDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- default: +- throw Exception("USB descriptor parser", "configuration descriptor", "unexpected descriptor size"); +- } +- break; +- case USBDescriptorType::Interface: +- switch (size) { +- case sizeof(USBInterfaceDescriptor): +- USBParseInterfaceDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- default: +- throw Exception("USB descriptor parser", "interface descriptor", "unexpected descriptor size"); +- } +- break; +- case USBDescriptorType::Endpoint: +- switch (size) { +- case sizeof(USBEndpointDescriptor): +- USBParseEndpointDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- case sizeof(USBAudioEndpointDescriptor): +- USBParseAudioEndpointDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- default: +- throw Exception("USB descriptor parser", "endpoint descriptor", "unexpected descriptor size"); +- } +- break; +- case USBDescriptorType::String: +- case USBDescriptorType::AssociationInterface: +- case USBDescriptorType::Unknown: +- default: +- USBParseUnknownDescriptor(parser, descriptor_raw, descriptor_out); +- return; +- } +- /* UNREACHABLE */ +- } +- +- void USBDescriptorParserHooks::loadUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor) +- { +- (void)parser; +- (void)descriptor; +- USBGUARD_LOG(Trace); +- } +- +- USBDescriptorParser::USBDescriptorParser(USBDescriptorParserHooks& hooks) +- : _hooks(hooks) +- { +- } +- +- size_t USBDescriptorParser::parse(std::istream& stream) +- { +- size_t size_processed = 0; +- +- while (stream.good()) { +- USBDescriptorHeader header; +- stream.read(reinterpret_cast(&header), sizeof header); +- +- if (stream.gcount() != sizeof header) { +- /* +- * If we read nothing and the stream if at EOF, just break +- * the loop and return normally. Checking the sanity of the +- * parsed descriptor data is up to the higher layers. +- */ +- if (stream.gcount() == 0 && stream.eof()) { +- break; +- } +- /* +- * Otherwise throw an exception because there's unknown garbage +- * in the stream which cannot be a valid USB descriptor. +- */ +- else { +- throw std::runtime_error("Cannot parse descriptor data: partial read while reading header data"); +- } +- } +- +- /* +- * The bLength value has to be at least 2, because that is the size of the USB +- * descriptor header. +- */ +- if (header.bLength < sizeof(USBDescriptorHeader)) { +- throw std::runtime_error("Invalid descriptor data: bLength is less than the size of the header"); +- } +- +- /* +- * Let's try to read the rest of the descriptor data before we start looking +- * for the descriptor type handler. If there's not enough data in the stream, +- * then there's no point for searching for the handler. +- */ +- USBDescriptor descriptor; +- +- descriptor.bHeader = header; +- memset(&descriptor.bDescriptorData, 0, sizeof descriptor.bDescriptorData); +- +- /* +- * We read (bLength - header_size) amount of data here because the bLength value +- * counts in the size of the header too and we already read it from the stream. +- */ +- stream.read(reinterpret_cast(&descriptor.bDescriptorData), header.bLength - sizeof(USBDescriptorHeader)); +- +- if (stream.gcount() != (std::streamsize)(header.bLength - sizeof(USBDescriptorHeader))) { +- throw std::runtime_error("Invalid descriptor data: bLength value larger than the amount of available data"); +- } +- +- USBDescriptor descriptor_parsed; +- descriptor_parsed.bHeader = header; +- memset(&descriptor_parsed.bDescriptorData, 0, sizeof descriptor_parsed.bDescriptorData); +- +- _hooks.parseUSBDescriptor(this, &descriptor, &descriptor_parsed); +- _hooks.loadUSBDescriptor(this, &descriptor_parsed); +- +- setDescriptor(header.bDescriptorType, descriptor_parsed); +- size_processed += header.bLength; +- } +- +- return size_processed; +- } +- +- const std::vector* USBDescriptorParser::getDescriptor(uint8_t bDescriptorType) const +- { +- auto const& it = _dstate_map.find(bDescriptorType); +- if (it == _dstate_map.end()) { +- return nullptr; +- } +- return &it->second; +- } +- +- void USBDescriptorParser::setDescriptor(uint8_t bDescriptorType, const USBDescriptor& descriptor) +- { +- auto& descriptors = _dstate_map[bDescriptorType]; +- bool set = false; +- for (auto& stored_descriptor : descriptors) { +- if (stored_descriptor.bHeader.bLength == descriptor.bHeader.bLength) { +- stored_descriptor = descriptor; +- set = true; +- } +- } +- if (!set) { +- descriptors.push_back(descriptor); +- } +- /* +- * Count in the descriptor no matter if we overwrote one or not. +- * We are counting all occurences of a descriptor type. +- */ +- ++_count_map[bDescriptorType]; +- } +- +- void USBDescriptorParser::delDescriptor(uint8_t bDescriptorType) +- { +- _dstate_map.erase(bDescriptorType); +- } +- +- bool USBDescriptorParser::haveDescriptor(uint8_t bDescriptorType) const +- { +- return _dstate_map.count(bDescriptorType) > 0; +- } +- +- const std::vector> USBDescriptorParser::getDescriptorCounts() const +- { +- std::vector> counts; +- +- for (auto const& kv : _count_map) { +- counts.push_back(std::make_pair(kv.first, kv.second)); +- } +- +- std::sort(counts.begin(), counts.end()); +- +- return counts; +- } +-} /* namespace usbguard */ +diff --git a/src/Library/USB.hpp b/src/Library/USB.hpp +deleted file mode 100644 +index 3058157..0000000 +--- a/src/Library/USB.hpp ++++ /dev/null +@@ -1,270 +0,0 @@ +-// +-// Copyright (C) 2015 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include "Predicates.hpp" +- +-#include +-#include +-#include +-#include +-#include +- +-namespace usbguard { +- /* +- * Maximum lenght of a string that is read from a USB descriptor +- * Since the string descriptors have an 8-bit length field, the +- * maximum lenght of a string stored in a string descriptor is +- * UINT8_MAX minus the size of the length field (1 byte) and the +- * size of the type field (1 byte). +- */ +- const size_t USB_GENERIC_STRING_MAX_LENGTH = UINT8_MAX - 2; +- +- /* Maximum lenght of the vendor id in string form */ +- const size_t USB_VID_STRING_MAX_LENGTH = 4; +- +- /* Maximum lenght of the product id in string form */ +- const size_t USB_PID_STRING_MAX_LENGTH = 4; +- +- /* Maximum lenght of the port in string form */ +- const size_t USB_PORT_STRING_MAX_LENGTH = PATH_MAX; +- +- /* +- * NOTE: The USB specification dictates that all multibyte data fields +- * are in little-endian form. The structures defined bellow are +- * used for platform-independed passing of the USB descriptor +- * data to the Device class. The Device class assumes that the +- * values are in host-specific endianness. +- */ +- const uint8_t USB_DESCRIPTOR_TYPE_UNKNOWN = 0x00; +- const uint8_t USB_DESCRIPTOR_TYPE_DEVICE = 0x01; +- const uint8_t USB_DESCRIPTOR_TYPE_CONFIGURATION = 0x02; +- const uint8_t USB_DESCRIPTOR_TYPE_STRING = 0x03; +- const uint8_t USB_DESCRIPTOR_TYPE_INTERFACE = 0x04; +- const uint8_t USB_DESCRIPTOR_TYPE_ENDPOINT = 0x05; +- const uint8_t USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE = 0x0b; +- +- enum class USBDescriptorType : uint8_t { +- Unknown = USB_DESCRIPTOR_TYPE_UNKNOWN, +- Device = USB_DESCRIPTOR_TYPE_DEVICE, +- Configuration = USB_DESCRIPTOR_TYPE_CONFIGURATION, +- String = USB_DESCRIPTOR_TYPE_STRING, +- Interface = USB_DESCRIPTOR_TYPE_INTERFACE, +- Endpoint = USB_DESCRIPTOR_TYPE_ENDPOINT, +- AssociationInterface = USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE +- }; +- +- struct DLL_PUBLIC USBDescriptorHeader +- { +- uint8_t bLength; +- uint8_t bDescriptorType; +- } __attribute__((packed)); +- +- struct DLL_PUBLIC USBDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint8_t bDescriptorData[256-sizeof(USBDescriptorHeader)]; +- } __attribute__((packed)); +- +- struct DLL_PUBLIC USBDeviceDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint16_t bcdUSB; +- uint8_t bDeviceClass; +- uint8_t bDeviceSubClass; +- uint8_t bDeviceProtocol; +- uint8_t bMaxPacketSize; +- uint16_t idVendor; +- uint16_t idProduct; +- uint16_t bcdDevice; +- uint8_t iManufacturer; +- uint8_t iProduct; +- uint8_t iSerialNumber; +- uint8_t bNumConfigurations; +- } __attribute__((packed)); +- +- struct DLL_PUBLIC USBConfigurationDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint16_t wTotalLength; +- uint8_t bNumInterfaces; +- uint8_t bConfigurationValue; +- uint8_t iConfiguration; +- uint8_t bmAttributes; +- uint8_t bMaxPower; +- } __attribute__((packed)); +- +- struct DLL_PUBLIC USBInterfaceDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint8_t bInterfaceNumber; +- uint8_t bAlternateSetting; +- uint8_t bNumEndpoints; +- uint8_t bInterfaceClass; +- uint8_t bInterfaceSubClass; +- uint8_t bInterfaceProtocol; +- uint8_t iInterface; +- } __attribute__((packed)); +- +- struct USBEndpointDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint8_t bEndpointAddress; +- uint8_t bmAttributes; +- uint16_t wMaxPacketSize; +- uint8_t bInterval; +- } __attribute__((packed)); +- +- struct USBAudioEndpointDescriptor +- { +- struct USBDescriptorHeader bHeader; +- uint8_t bEndpointAddress; +- uint8_t bmAttributes; +- uint16_t wMaxPacketSize; +- uint8_t bInterval; +- uint8_t bRefresh; +- uint8_t bSynchAddress; +- } __attribute__((packed)); +- +- class DLL_PUBLIC USBDeviceID +- { +- public: +- USBDeviceID(); +- USBDeviceID(const String& vendor_id, const String& product_id = String()); +- USBDeviceID(const USBDeviceID& rhs); +- +- static void checkDeviceID(const String& vendor_id, const String& product_id); +- +- void setVendorID(const String& vendor_id); +- void setProductID(const String& product_id); +- +- const String& getVendorID() const; +- const String& getProductID() const; +- +- String toRuleString() const; +- String toString() const; +- bool isSubsetOf(const USBDeviceID& rhs) const; +- +- private: +- String _vendor_id; +- String _product_id; +- }; +- +- namespace Predicates DLL_PUBLIC +- { +- template<> +- bool isSubsetOf(const USBDeviceID& source, const USBDeviceID& target); +- } +- +- class DLL_PUBLIC USBInterfaceType +- { +- public: +- static const uint8_t MatchClass = 1<<0; +- static const uint8_t MatchSubClass = 1<<1; +- static const uint8_t MatchProtocol = 1<<2; +- static const uint8_t MatchAll = MatchClass|MatchSubClass|MatchProtocol; +- +- USBInterfaceType(); +- USBInterfaceType(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll); +- USBInterfaceType(const USBInterfaceDescriptor& descriptor, uint8_t mask = MatchAll); +- USBInterfaceType(const std::string& type_string); +- +- bool operator==(const USBInterfaceType& rhs) const; +- bool appliesTo(const USBInterfaceType& rhs) const; +- +- const String typeString() const; +- const String toRuleString() const; +- static const String typeString(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll); +- +- private: +- uint8_t _bClass; +- uint8_t _bSubClass; +- uint8_t _bProtocol; +- uint8_t _mask; +- }; +- +- namespace Predicates DLL_PUBLIC +- { +- template<> +- bool isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target); +- } +- +- class USBDescriptorParser; +- +- class DLL_PUBLIC USBDescriptorParserHooks +- { +- public: +- virtual void parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_in, USBDescriptor* descriptor_out); +- virtual void loadUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); +- }; +- +- class DLL_PUBLIC USBDescriptorParser +- { +- public: +- USBDescriptorParser(USBDescriptorParserHooks& hooks); +- +- /** +- * Initiate parsing of USB descriptors from an input stream. +- * +- * Returns number of bytes succesfully parsed/processed from +- * the stream. +- */ +- size_t parse(std::istream& stream); +- +- /** +- * Return a pointer to a USBDescriptor of type bDescriptorType that +- * is stored in the USB descriptor state. If there's no such descriptor, +- * then nullptr is returned. +- */ +- const std::vector* getDescriptor(uint8_t bDescriptorType) const; +- +- /** +- * Set the active instance of an USB descriptor of bDescriptorType type. +- */ +- void setDescriptor(uint8_t bDescriptorType, const USBDescriptor& descriptor); +- +- /** +- * Delete the active instance of an USB descriptor of bDescriptorType type. +- */ +- void delDescriptor(uint8_t bDescriptorType); +- +- /** +- * Returns true if the descriptor state contains a USB descriptor of type bDescriptorType. +- */ +- bool haveDescriptor(uint8_t bDescriptorType) const; +- +- /** +- * Returns a vector of (bDescriptorType, count) pairs. +- */ +- const std::vector> getDescriptorCounts() const; +- +- private: +- USBDescriptorParserHooks& _hooks; +- +- std::unordered_map> _dstate_map; /**< Descriptor State Map */ +- std::unordered_map _count_map; +- }; +- +- void DLL_PUBLIC USBParseDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- void DLL_PUBLIC USBParseConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- void DLL_PUBLIC USBParseInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- void DLL_PUBLIC USBParseEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- void DLL_PUBLIC USBParseAudioEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- void DLL_PUBLIC USBParseUnknownDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); +- +-} /* namespace usbguard */ +diff --git a/src/Library/USBGuard.cpp b/src/Library/USBGuard.cpp +deleted file mode 100644 +index 27955ab..0000000 +--- a/src/Library/USBGuard.cpp ++++ /dev/null +@@ -1,75 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#include +- +-#include "USBGuard.hpp" +-#include "ConfigFile.hpp" +-#include "Exception.hpp" +-#include "Logger.hpp" +- +-#include +-#include +- +-#ifndef USBGUARD_DAEMON_CONF_PATH +-# warning "Using hard-coded USBGUARD_DAEMON_CONF_PATH value" +-# define USBGUARD_DAEMON_CONF_PATH "/etc/usbguard/usbguard-daemon.conf" +-#endif +- +-namespace usbguard +-{ +- std::string getDaemonConfigPath() +- { +- USBGUARD_LOG(Trace); +- const char * const envval = getenv("USBGUARD_DAEMON_CONF"); +- +- if (envval != nullptr) { +- USBGUARD_LOG(Debug) << "Returning environment variable path: " << envval; +- return std::string(envval); +- } +- else { +- USBGUARD_LOG(Debug) << "Returning build-time path: " << USBGUARD_DAEMON_CONF_PATH; +- return std::string(USBGUARD_DAEMON_CONF_PATH); +- } +- } +- +- std::string getIPCAccessControlFilesPath() +- { +- USBGUARD_LOG(Trace); +- const std::string daemon_conf_path = getDaemonConfigPath(); +- ConfigFile daemon_conf; +- daemon_conf.open(daemon_conf_path); +- +- if (daemon_conf.hasSettingValue("IPCAccessControlFiles")) { +- return daemon_conf.getSettingValue("IPCAccessControlFiles"); +- } +- +- throw Exception("getIPCAccessControlFilesPath", daemon_conf_path, "IPCAccessControlFiles not set"); +- } +- +- std::string getIPCAccessControlFileBasename(const std::string& name, bool is_group) +- { +- USBGUARD_LOG(Trace) << "name=" << name << " is_group=" << is_group; +- std::string basename; +- if (is_group) { +- basename.append(":"); +- } +- basename.append(name); +- return basename; +- } +-} /* namespace usbguard */ +diff --git a/src/Library/USBGuard.hpp b/src/Library/USBGuard.hpp +deleted file mode 100644 +index 7950c88..0000000 +--- a/src/Library/USBGuard.hpp ++++ /dev/null +@@ -1,28 +0,0 @@ +-// +-// Copyright (C) 2017 Red Hat, Inc. +-// +-// 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 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 General Public License +-// along with this program. If not, see . +-// +-// Authors: Daniel Kopecek +-// +-#pragma once +-#include "Typedefs.hpp" +-#include +- +-namespace usbguard +-{ +- DLL_PUBLIC std::string getDaemonConfigPath(); +- DLL_PUBLIC std::string getIPCAccessControlFilesPath(); +- DLL_PUBLIC std::string getIPCAccessControlFileBasename(const std::string& name, bool is_group); +-} /* namespace usbguard */ +diff --git a/src/Library/Utility.cpp b/src/Library/Utility.cpp +index cd2e6d9..68287b8 100644 +--- a/src/Library/Utility.cpp ++++ b/src/Library/Utility.cpp +@@ -16,18 +16,24 @@ + // + // Authors: Daniel Kopecek + // +-#include "Typedefs.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ + #include "Utility.hpp" + #include "Common/Utility.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++ + #include + + namespace usbguard + { + namespace Utility + { +- String escapeString(const String& string_raw) ++ std::string escapeString(const std::string& string_raw) + { +- String result; ++ std::string result; + const std::locale c_locale("C"); + + for (auto it = string_raw.cbegin(); it != string_raw.cend(); ++it) { +@@ -54,7 +60,7 @@ namespace usbguard + if (std::isprint(c, c_locale)) { + result.push_back((char)c); + } else { +- const String hexbyte = numberToString((uint8_t)c, "\\x", 16, 2, '0'); ++ const std::string hexbyte = numberToString((uint8_t)c, "\\x", 16, 2, '0'); + result.append(hexbyte); + } + } +@@ -62,9 +68,9 @@ namespace usbguard + return result; + } + +- String unescapeString(const String& string_escaped) ++ std::string unescapeString(const std::string& string_escaped) + { +- String result; ++ std::string result; + bool escaped = false; + const std::locale c_locale("C"); + +@@ -94,7 +100,7 @@ namespace usbguard + throw std::runtime_error("Invalid \\xHH escape sequence: HH is not a hexadecimal number"); + } + +- const String hexbyte(hb, 2); ++ const std::string hexbyte(hb, 2); + result.push_back((char)stringToNumber(hexbyte, 16)); + + ++it; +@@ -123,9 +129,9 @@ namespace usbguard + return result; + } + +- String quoteEscapeString(const String& value) ++ std::string quoteEscapeString(const std::string& value) + { +- String result; ++ std::string result; + result.push_back('"'); + result.append(escapeString(value)); + result.push_back('"'); +diff --git a/src/Library/Utility.hpp b/src/Library/Utility.hpp +index 2764dd3..94a9ad1 100644 +--- a/src/Library/Utility.hpp ++++ b/src/Library/Utility.hpp +@@ -17,14 +17,20 @@ + // Authors: Daniel Kopecek + // + #pragma once +-#include "Typedefs.hpp" ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Typedefs.hpp" ++ ++#include + + namespace usbguard + { + namespace Utility + { +- String escapeString(const String& value); +- String unescapeString(const String& value); +- String quoteEscapeString(const String& value); ++ std::string escapeString(const std::string& value); ++ std::string unescapeString(const std::string& value); ++ std::string quoteEscapeString(const std::string& value); + } + } /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Audit.cpp b/src/Library/public/usbguard/Audit.cpp +new file mode 100644 +index 0000000..e692733 +--- /dev/null ++++ b/src/Library/public/usbguard/Audit.cpp +@@ -0,0 +1,255 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Audit.hpp" ++#include "Exception.hpp" ++#include "Logger.hpp" ++ ++#include ++ ++namespace usbguard ++{ ++ ++ AuditIdentity::AuditIdentity() ++ { ++ _uid = getuid(); ++ _pid = getpid(); ++ } ++ ++ AuditIdentity::AuditIdentity(uid_t uid, pid_t pid) ++ { ++ _uid = uid; ++ _pid = pid; ++ } ++ ++ std::string AuditIdentity::toString() const ++ { ++ std::string identity_string; ++ ++ identity_string.append("{ uid="); ++ identity_string.append(numberToString(_uid)); ++ identity_string.append(" pid="); ++ identity_string.append(numberToString(_pid)); ++ identity_string.append(" }"); ++ ++ return identity_string; ++ } ++ ++ AuditEvent::AuditEvent(const AuditIdentity& identity) ++ : _confirmed(false), ++ _identity(identity) ++ { ++ ++ } ++ ++ AuditEvent::AuditEvent(AuditEvent&& event) ++ : _confirmed(event._confirmed), ++ _identity(std::move(event._identity)), ++ _message(std::move(event._message)) ++ { ++ event.setConfirmed(true); ++ } ++ ++ AuditEvent::~AuditEvent() ++ { ++ if (!_confirmed) { ++ failure(); ++ } ++ } ++ ++ void AuditEvent::confirm(const std::string& result) ++ { ++ USBGUARD_LOG(Audit) << "result=" << result \ ++ << " identity=" << _identity.toString() \ ++ << " " << _message; ++ setConfirmed(true); ++ } ++ ++ void AuditEvent::success() ++ { ++ confirm("SUCCESS"); ++ } ++ ++ void AuditEvent::failure() ++ { ++ confirm("FAILURE"); ++ } ++ ++ void AuditEvent::setConfirmed(bool state) ++ { ++ _confirmed = state; ++ } ++ ++ std::string& AuditEvent::refMessage() ++ { ++ return _message; ++ } ++ ++ Audit::Audit(const AuditIdentity& identity) ++ : _identity(identity) ++ { ++ ++ } ++ ++ AuditEvent Audit::policyEvent(std::shared_ptr rule, Policy::EventType event) ++ { ++ return policyEvent(_identity, rule, event); ++ } ++ ++ AuditEvent Audit::policyEvent(std::shared_ptr new_rule, std::shared_ptr old_rule) ++ { ++ return policyEvent(_identity, new_rule, old_rule); ++ } ++ ++ AuditEvent Audit::policyEvent(std::shared_ptr device, Policy::EventType event) ++ { ++ return policyEvent(_identity, device, event); ++ } ++ ++ AuditEvent Audit::policyEvent(std::shared_ptr device, Rule::Target old_target, Rule::Target new_target) ++ { ++ return policyEvent(_identity, device, old_target, new_target); ++ } ++ ++ AuditEvent Audit::deviceEvent(std::shared_ptr device, DeviceManager::EventType event) ++ { ++ return deviceEvent(_identity, device, event); ++ } ++ ++ AuditEvent Audit::deviceEvent(std::shared_ptr new_device, std::shared_ptr old_device) ++ { ++ return deviceEvent(_identity, new_device, old_device); ++ } ++ ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Policy."; ++ message += Policy::eventTypeToString(event); ++ ++ message += " rule.id="; ++ message += numberToString(rule->getRuleID()); ++ ++ message += " rule='"; ++ message += rule->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++ ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr new_rule, std::shared_ptr old_rule) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Policy."; ++ message += Policy::eventTypeToString(Policy::EventType::Update); ++ ++ message += " rule.id="; ++ message += numberToString(old_rule->getRuleID()); ++ ++ message += " rule.old='"; ++ message += old_rule->toString(); ++ message += "'"; ++ ++ message += " rule.new='"; ++ message += new_rule->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++ ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Policy.Device."; ++ message += Policy::eventTypeToString(event); ++ ++ message += " target="; ++ message += Rule::targetToString(device->getTarget()); ++ ++ message += " device='"; ++ message += device->getDeviceRule()->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++ ++ AuditEvent Audit::policyEvent(const AuditIdentity& identity, std::shared_ptr device, Rule::Target old_target, Rule::Target new_target) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Policy.Device."; ++ message += Policy::eventTypeToString(Policy::EventType::Update); ++ ++ message += " target.old="; ++ message += Rule::targetToString(old_target); ++ ++ message += " target.new="; ++ message += Rule::targetToString(new_target); ++ ++ message += " device='"; ++ message += device->getDeviceRule()->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++ ++ AuditEvent Audit::deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Device."; ++ message += DeviceManager::eventTypeToString(event); ++ ++ message += " device='"; ++ message += device->getDeviceRule()->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++ ++ AuditEvent Audit::deviceEvent(const AuditIdentity& identity, std::shared_ptr new_device, std::shared_ptr old_device) ++ { ++ AuditEvent audit_event(identity); ++ auto& message = audit_event.refMessage(); ++ ++ message += "type=Device."; ++ message += DeviceManager::eventTypeToString(DeviceManager::EventType::Update); ++ ++ message += " device.old='"; ++ message += old_device->getDeviceRule()->toString(); ++ message += "'"; ++ ++ message += " device.new='"; ++ message += new_device->getDeviceRule()->toString(); ++ message += "'"; ++ ++ return audit_event; ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Audit.hpp b/src/Library/public/usbguard/Audit.hpp +new file mode 100644 +index 0000000..398d4c2 +--- /dev/null ++++ b/src/Library/public/usbguard/Audit.hpp +@@ -0,0 +1,120 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Device.hpp" ++#include "DeviceManager.hpp" ++#include "Logger.hpp" ++#include "Policy.hpp" ++#include "Rule.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ class DLL_PUBLIC AuditIdentity ++ { ++ public: ++ AuditIdentity(); ++ AuditIdentity(uid_t uid, pid_t pid); ++ ++ std::string toString() const; ++ private: ++ uid_t _uid; ++ pid_t _pid; ++ }; ++ ++ class DLL_PUBLIC AuditEvent ++ { ++ AuditEvent(const AuditIdentity& identity); ++ public: ++ AuditEvent(AuditEvent&& event); ++ AuditEvent(const AuditEvent& event) = delete; ++ ~AuditEvent(); ++ ++ void success(); ++ void failure(); ++ ++ private: ++ void confirm(const std::string& result); ++ void setConfirmed(bool state); ++ std::string& refMessage(); ++ ++ bool _confirmed; ++ AuditIdentity _identity; ++ std::string _message; ++ ++ friend class Audit; ++ }; ++ ++ class DLL_PUBLIC Audit ++ { ++ public: ++ Audit(const AuditIdentity& identity); ++ ++ AuditEvent policyEvent(std::shared_ptr rule, Policy::EventType event); ++ AuditEvent policyEvent(std::shared_ptr new_rule, std::shared_ptr old_rule); ++ AuditEvent policyEvent(std::shared_ptr device, Policy::EventType event); ++ AuditEvent policyEvent(std::shared_ptr device, Rule::Target old_target, Rule::Target new_target); ++ ++ AuditEvent deviceEvent(std::shared_ptr device, DeviceManager::EventType event); ++ AuditEvent deviceEvent(std::shared_ptr new_device, std::shared_ptr old_device); ++ ++ /* ++ * Audit policy changes: ++ * - rule append ++ * - rule remove ++ * - rule update ++ * - policy parameter change ++ * ++ * Audit data: ++ * - who: uid + pid ++ * - when: time ++ * - what: append, remove, update ++ * - update: old, new ++ */ ++ static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr rule, Policy::EventType event); ++ static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr new_rule, std::shared_ptr old_rule); ++ static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Policy::EventType event); ++ static AuditEvent policyEvent(const AuditIdentity& identity, std::shared_ptr device, Rule::Target old_target, Rule::Target new_target); ++ ++ /* ++ * Audit device changes: ++ * - device insertion ++ * - device removal ++ * - device authorization target change ++ * ++ * Audit data: ++ * - who: uid + pid ++ * - when: time ++ * - what: insert, remove, authorization target ++ * - change: old, new ++ */ ++ static AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr device, DeviceManager::EventType event); ++ static AuditEvent deviceEvent(const AuditIdentity& identity, std::shared_ptr new_device, std::shared_ptr old_device); ++ ++ private: ++ AuditIdentity _identity; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/ConfigFile.cpp b/src/Library/public/usbguard/ConfigFile.cpp +new file mode 100644 +index 0000000..5d4c843 +--- /dev/null ++++ b/src/Library/public/usbguard/ConfigFile.cpp +@@ -0,0 +1,66 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "ConfigFilePrivate.hpp" ++ ++namespace usbguard ++{ ++ ConfigFile::ConfigFile(const std::vector& known_names) ++ { ++ d_pointer = new ConfigFilePrivate(*this, known_names); ++ } ++ ++ ConfigFile::~ConfigFile() ++ { ++ delete d_pointer; ++ } ++ ++ void ConfigFile::open(const std::string& path) ++ { ++ d_pointer->open(path); ++ } ++ ++ void ConfigFile::write() ++ { ++ d_pointer->write(); ++ } ++ ++ void ConfigFile::close() ++ { ++ d_pointer->close(); ++ } ++ ++ const std::string& ConfigFile::getSettingValue(const std::string& name) const ++ { ++ return d_pointer->getSettingValue(name); ++ } ++ ++ void ConfigFile::setSettingValue(const std::string& name, std::string& value) ++ { ++ d_pointer->setSettingValue(name, value); ++ } ++ ++ bool ConfigFile::hasSettingValue(const std::string& name) const ++ { ++ return d_pointer->hasSettingValue(name); ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/ConfigFile.hpp b/src/Library/public/usbguard/ConfigFile.hpp +new file mode 100644 +index 0000000..44aaf8f +--- /dev/null ++++ b/src/Library/public/usbguard/ConfigFile.hpp +@@ -0,0 +1,45 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++namespace usbguard { ++ class ConfigFilePrivate; ++ class DLL_PUBLIC ConfigFile ++ { ++ public: ++ ConfigFile(const std::vector& known_names = std::vector()); ++ ~ConfigFile(); ++ ++ void open(const std::string& path); ++ void write(); ++ void close(); ++ ++ void setSettingValue(const std::string& name, std::string& value); ++ bool hasSettingValue(const std::string& name) const; ++ const std::string& getSettingValue(const std::string& name) const; ++ ++ private: ++ ConfigFilePrivate* d_pointer; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Device.cpp b/src/Library/public/usbguard/Device.cpp +new file mode 100644 +index 0000000..49067c4 +--- /dev/null ++++ b/src/Library/public/usbguard/Device.cpp +@@ -0,0 +1,199 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "DevicePrivate.hpp" ++ ++namespace usbguard { ++ Device::Device(DeviceManager& manager) ++ { ++ d_pointer = new DevicePrivate(*this, manager); ++ } ++ ++ Device::~Device() ++ { ++ delete d_pointer; ++ d_pointer = nullptr; ++ } ++ ++ Device::Device(const Device& rhs) ++ { ++ d_pointer = new DevicePrivate(*this, *rhs.d_pointer); ++ } ++ ++ const Device& Device::operator=(const Device &rhs) ++ { ++ DevicePrivate* n_pointer = new DevicePrivate(*this, *rhs.d_pointer); ++ delete d_pointer; ++ d_pointer = n_pointer; ++ return *this; ++ } ++ ++ DeviceManager& Device::manager() const ++ { ++ return d_pointer->manager(); ++ } ++ ++ std::mutex& Device::refDeviceMutex() ++ { ++ return d_pointer->refDeviceMutex(); ++ } ++ ++ std::shared_ptr Device::getDeviceRule(const bool with_port, const bool with_parent_hash, const bool match_rule) ++ { ++ return d_pointer->getDeviceRule(with_port, with_parent_hash, match_rule); ++ } ++ ++ std::string Device::hashString(const std::string& value) const ++ { ++ return d_pointer->hashString(value); ++ } ++ ++ void Device::initializeHash() ++ { ++ d_pointer->initializeHash(); ++ } ++ ++ void Device::updateHash(const void * const ptr, const size_t size) ++ { ++ d_pointer->updateHash(ptr, size); ++ } ++ ++ void Device::updateHash(std::istream& descriptor_stream, const size_t expected_size) ++ { ++ d_pointer->updateHash(descriptor_stream, expected_size); ++ } ++ ++ std::string Device::finalizeHash() ++ { ++ return d_pointer->finalizeHash(); ++ } ++ ++ const std::string& Device::getHash() const ++ { ++ return d_pointer->getHash(); ++ } ++ ++ void Device::setParentHash(const std::string& hash) ++ { ++ d_pointer->setParentHash(hash); ++ } ++ ++ void Device::setID(uint32_t id) ++ { ++ d_pointer->setID(id); ++ } ++ ++ uint32_t Device::getID() const ++ { ++ return d_pointer->getID(); ++ } ++ ++ void Device::setParentID(uint32_t id) ++ { ++ d_pointer->setParentID(id); ++ } ++ ++ uint32_t Device::getParentID() const ++ { ++ return d_pointer->getParentID(); ++ } ++ ++ void Device::setTarget(Rule::Target target) ++ { ++ d_pointer->setTarget(target); ++ } ++ ++ Rule::Target Device::getTarget() const ++ { ++ return d_pointer->getTarget(); ++ } ++ ++ void Device::setName(const std::string& name) ++ { ++ d_pointer->setName(name); ++ } ++ ++ const std::string& Device::getName() const ++ { ++ return d_pointer->getName(); ++ } ++ ++ void Device::setDeviceID(const USBDeviceID& device_id) ++ { ++ d_pointer->setDeviceID(device_id); ++ } ++ ++ const USBDeviceID& Device::getDeviceID() const ++ { ++ return d_pointer->getDeviceID(); ++ } ++ ++ void Device::setPort(const std::string& port) ++ { ++ d_pointer->setPort(port); ++ } ++ ++ const std::string& Device::getPort() const ++ { ++ return d_pointer->getPort(); ++ } ++ ++ void Device::setSerial(const std::string& serial_number) ++ { ++ d_pointer->setSerial(serial_number); ++ } ++ ++ const std::string& Device::getSerial() const ++ { ++ return d_pointer->getSerial(); ++ } ++ ++ std::vector& Device::refMutableInterfaceTypes() ++ { ++ return d_pointer->refMutableInterfaceTypes(); ++ } ++ ++ const std::vector& Device::getInterfaceTypes() const ++ { ++ return d_pointer->getInterfaceTypes(); ++ } ++ ++ void Device::loadDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) ++ { ++ d_pointer->loadDeviceDescriptor(parser, descriptor); ++ } ++ ++ void Device::loadConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) ++ { ++ d_pointer->loadConfigurationDescriptor(parser, descriptor); ++ } ++ ++ void Device::loadInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) ++ { ++ d_pointer->loadInterfaceDescriptor(parser, descriptor); ++ } ++ ++ void Device::loadEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* const descriptor) ++ { ++ d_pointer->loadEndpointDescriptor(parser, descriptor); ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Device.hpp b/src/Library/public/usbguard/Device.hpp +new file mode 100644 +index 0000000..d5a8130 +--- /dev/null ++++ b/src/Library/public/usbguard/Device.hpp +@@ -0,0 +1,90 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Rule.hpp" ++#include "Typedefs.hpp" ++#include "USB.hpp" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++namespace usbguard { ++ class DeviceManager; ++ class DevicePrivate; ++ class DLL_PUBLIC Device ++ { ++ public: ++ Device(DeviceManager& manager); ++ ~Device(); ++ Device(const Device& rhs); ++ const Device& operator=(const Device& rhs); ++ ++ DeviceManager& manager() const; ++ ++ std::mutex& refDeviceMutex(); ++ std::shared_ptr getDeviceRule(bool with_port = true, bool with_parent_hash = true, bool match_rule = false); ++ std::string hashString(const std::string& value) const; ++ void initializeHash(); ++ void updateHash(const void * ptr, size_t size); ++ void updateHash(std::istream& descriptor_stream, size_t expected_size); ++ std::string finalizeHash(); ++ const std::string& getHash() const; ++ ++ void setParentHash(const std::string& hash); ++ ++ void setID(uint32_t id); ++ uint32_t getID() const; ++ ++ void setParentID(uint32_t id); ++ uint32_t getParentID() const; ++ ++ void setTarget(Rule::Target target); ++ Rule::Target getTarget() const; ++ ++ void setName(const std::string& name); ++ const std::string& getName() const; ++ ++ void setDeviceID(const USBDeviceID& device_id); ++ const USBDeviceID& getDeviceID() const; ++ ++ void setPort(const std::string& port); ++ const std::string& getPort() const; ++ ++ void setSerial(const std::string& serial_number); ++ const std::string& getSerial() const; ++ ++ std::vector& refMutableInterfaceTypes(); ++ const std::vector& getInterfaceTypes() const; ++ ++ virtual bool isController() const = 0; ++ ++ void loadDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); ++ void loadConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); ++ void loadInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); ++ void loadEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); ++ ++ private: ++ DevicePrivate *d_pointer; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/DeviceManager.cpp b/src/Library/public/usbguard/DeviceManager.cpp +new file mode 100644 +index 0000000..f7282ad +--- /dev/null ++++ b/src/Library/public/usbguard/DeviceManager.cpp +@@ -0,0 +1,180 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "DeviceManagerPrivate.hpp" ++ ++#include "usbguard/DeviceManagerHooks.hpp" ++#include "usbguard/Exception.hpp" ++ ++namespace usbguard { ++ uint32_t DeviceManager::eventTypeToInteger(DeviceManager::EventType event) ++ { ++ return static_cast(event); ++ } ++ ++ DeviceManager::EventType DeviceManager::eventTypeFromInteger(uint32_t event_integer) ++ { ++ switch(event_integer) { ++ case static_cast(EventType::Insert): ++ case static_cast(EventType::Update): ++ case static_cast(EventType::Remove): ++ break; ++ default: ++ throw std::runtime_error("Invalid event type integer value"); ++ } ++ return static_cast(event_integer); ++ } ++ ++ std::string DeviceManager::eventTypeToString(DeviceManager::EventType event) ++ { ++ switch(event) { ++ case DeviceManager::EventType::Present: ++ return "Present"; ++ case DeviceManager::EventType::Insert: ++ return "Insert"; ++ case DeviceManager::EventType::Remove: ++ return "Remove"; ++ case DeviceManager::EventType::Update: ++ return "Update"; ++ default: ++ throw USBGUARD_BUG("unknown event type"); ++ } ++ } ++ ++ DeviceManager::DeviceManager(DeviceManagerHooks& hooks) ++ { ++ d_pointer = new DeviceManagerPrivate(*this, hooks); ++ } ++ ++ DeviceManager::DeviceManager(const DeviceManager& rhs) ++ { ++ d_pointer = new DeviceManagerPrivate(*this, *rhs.d_pointer); ++ } ++ ++ const DeviceManager& DeviceManager::operator=(const DeviceManager& rhs) ++ { ++ DeviceManagerPrivate* n_pointer = new DeviceManagerPrivate(*this, *rhs.d_pointer); ++ delete d_pointer; ++ d_pointer = n_pointer; ++ return *this; ++ } ++ ++ DeviceManager::~DeviceManager() ++ { ++ delete d_pointer; ++ d_pointer = nullptr; ++ } ++ ++ void DeviceManager::setRestoreControllerDeviceState(bool enabled) ++ { ++ d_pointer->setRestoreControllerDeviceState(enabled); ++ } ++ ++ bool DeviceManager::getRestoreControllerDeviceState() const ++ { ++ return d_pointer->getRestoreControllerDeviceState(); ++ } ++ ++ void DeviceManager::insertDevice(std::shared_ptr device) ++ { ++ d_pointer->insertDevice(device); ++ } ++ ++ std::shared_ptr DeviceManager::removeDevice(uint32_t id) ++ { ++ return d_pointer->removeDevice(id); ++ } ++ ++ std::vector> DeviceManager::getDeviceList() ++ { ++ return d_pointer->getDeviceList(); ++ } ++ ++ std::vector> DeviceManager::getDeviceList(const Rule& query) ++ { ++ std::vector> matching_devices; ++ ++ for (auto const& device : getDeviceList()) { ++ if (query.appliesTo(device->getDeviceRule())) { ++ switch(query.getTarget()) { ++ case Rule::Target::Allow: ++ case Rule::Target::Block: ++ if (device->getTarget() == query.getTarget()) { ++ matching_devices.push_back(device); ++ } ++ break; ++ case Rule::Target::Device: ++ case Rule::Target::Match: ++ matching_devices.push_back(device); ++ break; ++ case Rule::Target::Reject: ++ case Rule::Target::Unknown: ++ case Rule::Target::Invalid: ++ default: ++ throw std::runtime_error("Invalid device query target"); ++ } ++ } ++ } ++ ++ return matching_devices; ++ } ++ ++ std::shared_ptr DeviceManager::getDevice(uint32_t id) ++ { ++ return d_pointer->getDevice(id); ++ } ++ ++ void DeviceManager::DeviceEvent(DeviceManager::EventType event, std::shared_ptr device) ++ { ++ d_pointer->DeviceEvent(event, device); ++ } ++ ++ void DeviceManager::DeviceException(const std::string& message) ++ { ++ d_pointer->DeviceException(message); ++ } ++} /* namespace usbguard */ ++ ++#if defined(HAVE_UEVENT) ++# include "UEventDeviceManager.hpp" ++#endif ++ ++std::shared_ptr usbguard::DeviceManager::create(DeviceManagerHooks& hooks, const std::string& backend) ++{ ++#if defined(HAVE_UEVENT) ++ if (backend == "udev") { ++ USBGUARD_LOG(Warning) << "udev backend is OBSOLETE. Falling back to new default: uevent"; ++ } ++ if (backend == "uevent" || /* transition udev => uevent */backend == "udev") { ++ return std::make_shared(hooks); ++ } ++ if (backend == "dummy") { ++ const char * const device_root_cstr = getenv("USBGUARD_DUMMY_DEVICE_ROOT"); ++ if (device_root_cstr == nullptr) { ++ throw Exception("DeviceManager", "dummy", "USBGUARD_DUMMY_DEVICE_ROOT environment variable not defined"); ++ } ++ const std::string device_root(device_root_cstr); ++ return std::make_shared(hooks, device_root, /*dummy_mode=*/true); ++ } ++#endif ++ throw Exception("DeviceManager", "backend", "requested backend is not available"); ++} +diff --git a/src/Library/public/usbguard/DeviceManager.hpp b/src/Library/public/usbguard/DeviceManager.hpp +new file mode 100644 +index 0000000..89b09d1 +--- /dev/null ++++ b/src/Library/public/usbguard/DeviceManager.hpp +@@ -0,0 +1,87 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Device.hpp" ++#include "Rule.hpp" ++#include "RuleSet.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace usbguard { ++ class DeviceManagerHooks; ++ class DeviceManagerPrivate; ++ class DLL_PUBLIC DeviceManager ++ { ++ public: ++ enum class EventType { ++ Present = 0, ++ Insert = 1, ++ Update = 2, /* use case: writable attribute changed externally */ ++ Remove = 3, ++ }; ++ ++ static uint32_t eventTypeToInteger(EventType event); ++ static EventType eventTypeFromInteger(uint32_t event_integer); ++ static std::string eventTypeToString(EventType event); ++ ++ DeviceManager(DeviceManagerHooks& hooks); ++ DeviceManager(const DeviceManager& rhs); ++ const DeviceManager& operator=(const DeviceManager& rhs); ++ ++ virtual ~DeviceManager(); ++ ++ virtual void setDefaultBlockedState(bool state) = 0; ++ virtual void setEnumerationOnlyMode(bool state) = 0; ++ virtual void start() = 0; ++ virtual void stop() = 0; ++ virtual void scan() = 0; ++ ++ void setRestoreControllerDeviceState(bool enabled); ++ bool getRestoreControllerDeviceState() const; ++ ++ virtual std::shared_ptr applyDevicePolicy(uint32_t id, Rule::Target target) = 0; ++ ++ virtual void insertDevice(std::shared_ptr device); ++ std::shared_ptr removeDevice(uint32_t id); ++ ++ /* Returns a copy of the list of active USB devices */ ++ std::vector> getDeviceList(); ++ std::vector> getDeviceList(const Rule& query); ++ ++ std::shared_ptr getDevice(uint32_t id); ++ std::mutex& refDeviceMapMutex(); ++ ++ /* Call Daemon instance hooks */ ++ void DeviceEvent(EventType event, std::shared_ptr device); ++ void DeviceException(const std::string& message); ++ ++ static std::shared_ptr create(DeviceManagerHooks& hooks, const std::string& backend); ++ ++ private: ++ DeviceManagerPrivate *d_pointer; ++ }; ++ ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/DeviceManagerHooks.cpp b/src/Library/public/usbguard/DeviceManagerHooks.cpp +new file mode 100644 +index 0000000..8c31941 +--- /dev/null ++++ b/src/Library/public/usbguard/DeviceManagerHooks.cpp +@@ -0,0 +1,33 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/DeviceManagerHooks.hpp" ++ ++namespace usbguard ++{ ++ void DeviceManagerHooks::dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) ++ { ++ (void)event; ++ (void)device; ++ /* NOOP */ ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/DeviceManagerHooks.hpp b/src/Library/public/usbguard/DeviceManagerHooks.hpp +new file mode 100644 +index 0000000..c85ee3a +--- /dev/null ++++ b/src/Library/public/usbguard/DeviceManagerHooks.hpp +@@ -0,0 +1,39 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Device.hpp" ++#include "DeviceManager.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++#include ++ ++namespace usbguard ++{ ++ class DLL_PUBLIC DeviceManagerHooks ++ { ++ public: ++ virtual void dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device); ++ virtual uint32_t dmHookAssignID() = 0; ++ virtual void dmHookDeviceException(const std::string& message) = 0; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Exception.hpp b/src/Library/public/usbguard/Exception.hpp +new file mode 100644 +index 0000000..a46d9ee +--- /dev/null ++++ b/src/Library/public/usbguard/Exception.hpp +@@ -0,0 +1,180 @@ ++// ++// Copyright (C) 2016 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE ++#endif ++ ++#include ++#include ++#include ++ ++namespace usbguard ++{ ++ class DLL_PUBLIC Exception : public std::exception ++ { ++ public: ++ Exception(const std::string& context, ++ const std::string& object, ++ const std::string& reason_val) ++ : _context(context), ++ _object(object), ++ _reason(reason_val) ++ { ++ } ++ ++ Exception(const Exception& rhs) ++ : _context(rhs._context), ++ _object(rhs._object), ++ _reason(rhs._reason) ++ { ++ } ++ ++ const std::string& context() const noexcept ++ { ++ return _context; ++ } ++ ++ const std::string& object() const noexcept ++ { ++ return _object; ++ } ++ ++ const std::string& reason() const noexcept ++ { ++ return _reason; ++ } ++ ++ void setContext(const std::string& context) ++ { ++ _context = context; ++ } ++ ++ void setObject(const std::string& object) ++ { ++ _object = object; ++ } ++ ++ void setReason(const std::string& reason_val) ++ { ++ _reason = reason_val; ++ } ++ ++ virtual std::string message() const noexcept ++ { ++ try { ++ return _context + ": " + (!_object.empty() ? _object + ": " : "") + _reason; ++ } ++ catch(...) { ++ return "usbguard::Exception: exception^2"; ++ } ++ } ++ ++ virtual const char * what() const noexcept ++ { ++ return "usbguard::Exception"; ++ } ++ ++ private: ++ std::string _context; ++ std::string _object; ++ std::string _reason; ++ }; ++ ++#define USBGUARD_BUG(m) \ ++ ::usbguard::Exception(__PRETTY_FUNCTION__, "BUG", m) ++ ++ class ErrnoException : public Exception ++ { ++ public: ++ ErrnoException(const std::string& context, const std::string& object, const int errno_value) ++ : Exception(context, object, ErrnoException::reasonFromErrno(errno_value)) ++ { ++ } ++ private: ++ static std::string reasonFromErrno(const int errno_value) ++ { ++ char buffer[1024]; ++ return std::string(strerror_r(errno_value, buffer, sizeof buffer)); ++ } ++ }; ++ ++#define USBGUARD_SYSCALL_THROW(context, syscall_bool_expression) \ ++ do { \ ++ if (syscall_bool_expression) { \ ++ throw usbguard::ErrnoException(context, #syscall_bool_expression, errno); \ ++ } \ ++ } while(0) ++ ++ class IPCException : public Exception ++ { ++ public: ++ IPCException() ++ : Exception("", "", ""), ++ _message_id(0) ++ { ++ } ++ ++ IPCException(const Exception& exception, ++ uint64_t message_id = 0) ++ : Exception(exception), ++ _message_id(message_id) ++ { ++ } ++ ++ IPCException(const std::string& context, ++ const std::string& object, ++ const std::string& reason, ++ uint64_t message_id = 0) ++ : Exception(context, object, reason), ++ _message_id(message_id) ++ { ++ } ++ ++ IPCException(const IPCException& rhs) ++ : Exception(rhs), ++ _message_id(rhs._message_id) ++ { ++ } ++ ++ bool hasMessageID() const noexcept ++ { ++ return _message_id != 0; ++ } ++ ++ uint64_t messageID() const noexcept ++ { ++ return _message_id; ++ } ++ ++ void setMessageID(uint64_t message_id) ++ { ++ _message_id = message_id; ++ } ++ ++ private: ++ uint64_t _message_id; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/IPCClient.cpp b/src/Library/public/usbguard/IPCClient.cpp +new file mode 100644 +index 0000000..4f4e08f +--- /dev/null ++++ b/src/Library/public/usbguard/IPCClient.cpp +@@ -0,0 +1,91 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "IPCClientPrivate.hpp" ++ ++namespace usbguard ++{ ++ IPCClient::IPCClient(bool connected) ++ { ++ d_pointer = new IPCClientPrivate(*this, connected); ++ } ++ ++ IPCClient::~IPCClient() ++ { ++ delete d_pointer; ++ } ++ ++ void IPCClient::connect() ++ { ++ d_pointer->connect(); ++ } ++ ++ void IPCClient::disconnect() ++ { ++ d_pointer->disconnect(/*do_wait*/true); ++ } ++ ++ bool IPCClient::isConnected() const ++ { ++ return d_pointer->isConnected(); ++ } ++ ++ void IPCClient::wait() ++ { ++ d_pointer->wait(); ++ } ++ ++ std::string IPCClient::setParameter(const std::string& name, const std::string& value) ++ { ++ return d_pointer->setParameter(name, value); ++ } ++ ++ std::string IPCClient::getParameter(const std::string& name) ++ { ++ return d_pointer->getParameter(name); ++ } ++ ++ uint32_t IPCClient::appendRule(const std::string& rule_spec, uint32_t parent_id) ++ { ++ return d_pointer->appendRule(rule_spec, parent_id); ++ } ++ ++ void IPCClient::removeRule(uint32_t id) ++ { ++ d_pointer->removeRule(id); ++ } ++ ++ const RuleSet IPCClient::listRules(const std::string& query) ++ { ++ return d_pointer->listRules(query); ++ } ++ ++ uint32_t IPCClient::applyDevicePolicy(uint32_t id, Rule::Target target, bool permanent) ++ { ++ return d_pointer->applyDevicePolicy(id, target, permanent); ++ } ++ ++ const std::vector IPCClient::listDevices(const std::string& query) ++ { ++ return d_pointer->listDevices(query); ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/IPCClient.hpp b/src/Library/public/usbguard/IPCClient.hpp +new file mode 100644 +index 0000000..8ed62ed +--- /dev/null ++++ b/src/Library/public/usbguard/IPCClient.hpp +@@ -0,0 +1,108 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "DeviceManager.hpp" ++#include "Exception.hpp" ++#include "Interface.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++#include ++ ++namespace usbguard ++{ ++ class IPCClientPrivate; ++ class DLL_PUBLIC IPCClient : public Interface ++ { ++ public: ++ IPCClient(bool connected = false); ++ virtual ~IPCClient(); ++ ++ void connect(); ++ void disconnect(); ++ bool isConnected() const; ++ void wait(); ++ ++ std::string setParameter(const std::string& name, const std::string& value) override; ++ std::string getParameter(const std::string& name) override; ++ ++ uint32_t appendRule(const std::string& rule_spec, uint32_t parent_id) override; ++ void removeRule(uint32_t id) override; ++ const RuleSet listRules(const std::string& query) override; ++ const RuleSet listRules() ++ { ++ return listRules("match"); ++ } ++ ++ uint32_t applyDevicePolicy(uint32_t id, Rule::Target target, bool permanent) override; ++ const std::vector listDevices(const std::string& query) override; ++ const std::vector listDevices() /* NOTE: left for compatibility */ ++ { ++ return listDevices("match"); ++ } ++ ++ virtual void IPCConnected() {} ++ ++ virtual void IPCDisconnected(bool exception_initiated, const IPCException& exception) ++ { ++ (void)exception_initiated; ++ (void)exception; ++ } ++ ++ virtual void DevicePresenceChanged(uint32_t id, ++ DeviceManager::EventType event, ++ Rule::Target target, ++ const std::string& device_rule) override ++ { ++ (void)id; ++ (void)event; ++ (void)target; ++ (void)device_rule; ++ } ++ ++ virtual void DevicePolicyChanged(uint32_t id, ++ Rule::Target target_old, ++ Rule::Target target_new, ++ const std::string& device_rule, ++ uint32_t rule_id) override ++ { ++ (void)id; ++ (void)target_old; ++ (void)target_new; ++ (void)device_rule; ++ (void)rule_id; ++ } ++ ++ virtual void ExceptionMessage(const std::string& context, ++ const std::string& object, ++ const std::string& reason) override ++ { ++ (void)context; ++ (void)object; ++ (void)reason; ++ } ++ ++ private: ++ IPCClientPrivate* d_pointer; ++ }; ++ ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/IPCServer.cpp b/src/Library/public/usbguard/IPCServer.cpp +new file mode 100644 +index 0000000..adb2644 +--- /dev/null ++++ b/src/Library/public/usbguard/IPCServer.cpp +@@ -0,0 +1,310 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "IPCServerPrivate.hpp" ++#include "Common/Utility.hpp" ++ ++#include "usbguard/Exception.hpp" ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ void IPCServer::checkAccessControlName(const std::string& name) ++ { ++ if (name.size() > 32) { ++ throw Exception("IPC access control", "name too long", name); ++ } ++ ++ const std::string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; ++ ++ if (name.find_first_not_of(valid_chars) != std::string::npos) { ++ throw Exception("IPC access control", "name contains invalid character(s)", name); ++ } ++ ++ } ++ ++ static const std::vector> section_ttable = { ++ { "ALL", IPCServer::AccessControl::Section::ALL }, ++ { "Policy", IPCServer::AccessControl::Section::POLICY }, ++ { "Parameters", IPCServer::AccessControl::Section::PARAMETERS }, ++ { "Devices", IPCServer::AccessControl::Section::DEVICES }, ++ { "Exceptions", IPCServer::AccessControl::Section::EXCEPTIONS }, ++ { "None", IPCServer::AccessControl::Section::NONE } ++ }; ++ ++ IPCServer::AccessControl::Section IPCServer::AccessControl::sectionFromString(const std::string& section_string) ++ { ++ for (auto ttable_entry : section_ttable) { ++ if (ttable_entry.first == section_string) { ++ return ttable_entry.second; ++ } ++ } ++ throw std::runtime_error("Invalid AccessControl::Section string"); ++ } ++ ++ std::string IPCServer::AccessControl::sectionToString(const IPCServer::AccessControl::Section section) ++ { ++ for (auto ttable_entry : section_ttable) { ++ if (ttable_entry.second == section) { ++ return ttable_entry.first; ++ } ++ } ++ throw std::runtime_error("Invalid AccessControl::Section value"); ++ } ++ ++ static const std::vector> privilege_ttable = { ++ { "ALL", IPCServer::AccessControl::Privilege::ALL }, ++ { "modify", IPCServer::AccessControl::Privilege::MODIFY }, ++ { "list", IPCServer::AccessControl::Privilege::LIST }, ++ { "listen", IPCServer::AccessControl::Privilege::LISTEN }, ++ { "none", IPCServer::AccessControl::Privilege::NONE } ++ }; ++ ++ IPCServer::AccessControl::Privilege IPCServer::AccessControl::privilegeFromString(const std::string& privilege_string) ++ { ++ for (auto ttable_entry : privilege_ttable) { ++ if (ttable_entry.first == privilege_string) { ++ return ttable_entry.second; ++ } ++ } ++ throw std::runtime_error("Invalid AccessControl::Section string"); ++ } ++ ++ std::string IPCServer::AccessControl::privilegeToString(const IPCServer::AccessControl::Privilege privilege) ++ { ++ for (auto ttable_entry : privilege_ttable) { ++ if (ttable_entry.second == privilege) { ++ return ttable_entry.first; ++ } ++ } ++ throw std::runtime_error("Invalid AccessControl::Privilege value"); ++ } ++ ++ IPCServer::AccessControl::AccessControl() ++ { ++ /* Empty: no privileges */ ++ } ++ ++ IPCServer::AccessControl::AccessControl(const std::string& access_control_string) ++ { ++ std::stringstream ss(access_control_string); ++ load(ss); ++ } ++ ++ IPCServer::AccessControl::AccessControl(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) ++ { ++ setPrivilege(section, privilege); ++ } ++ ++ IPCServer::AccessControl::AccessControl(const IPCServer::AccessControl& rhs) ++ : _access_control(rhs._access_control) ++ { ++ } ++ ++ IPCServer::AccessControl& IPCServer::AccessControl::operator=(const IPCServer::AccessControl& rhs) ++ { ++ _access_control = rhs._access_control; ++ return *this; ++ } ++ ++ bool IPCServer::AccessControl::hasPrivilege(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) const ++ { ++ if (section == Section::ALL || section == Section::NONE) { ++ throw USBGUARD_BUG("Cannot test against ALL, NONE sections"); ++ } ++ ++ const auto it = _access_control.find(section); ++ ++ if (it == _access_control.cend()) { ++ return false; ++ } ++ ++ return (it->second & static_cast(privilege)) == static_cast(privilege); ++ } ++ ++ void IPCServer::AccessControl::setPrivilege(IPCServer::AccessControl::Section section, IPCServer::AccessControl::Privilege privilege) ++ { ++ if (section == Section::NONE) { ++ throw USBGUARD_BUG("Cannot set privileges for NONE section"); ++ } ++ if (section == Section::ALL) { ++ for (const auto& value : { ++ Section::POLICY, ++ Section::PARAMETERS, ++ Section::EXCEPTIONS, ++ Section::DEVICES }) { ++ _access_control[value] |= static_cast(privilege); ++ } ++ } ++ else { ++ _access_control[section] |= static_cast(privilege); ++ } ++ } ++ ++ void IPCServer::AccessControl::clear() ++ { ++ _access_control.clear(); ++ } ++ ++ void IPCServer::AccessControl::load(std::istream& stream) ++ { ++ std::string line; ++ size_t line_number = 0; ++ ++ while (std::getline(stream, line)) { ++ ++line_number; ++ const size_t nv_separator = line.find_first_of("="); ++ ++ if (nv_separator == std::string::npos) { ++ continue; ++ } ++ ++ const std::string section_string = trim(line.substr(0, nv_separator)); ++ const Section section = sectionFromString(section_string); ++ ++ const std::string privileges_string = line.substr(nv_separator + 1); ++ std::vector privilege_strings; ++ tokenizeString(privileges_string, privilege_strings, " ,", /*trim_empty=*/true); ++ ++ for (const std::string& privilege_string : privilege_strings) { ++ const Privilege privilege = privilegeFromString(privilege_string); ++ setPrivilege(section, privilege); ++ } ++ } ++ } ++ ++ void IPCServer::AccessControl::save(std::ostream& stream) const ++ { ++ std::string access_control_string; ++ ++ for (auto const& section : { ++ Section::DEVICES, ++ Section::POLICY, ++ Section::PARAMETERS, ++ Section::EXCEPTIONS ++ }) { ++ bool section_is_empty = true; ++ std::string section_string = sectionToString(section); ++ section_string.append("="); ++ ++ for (auto const& privilege : { ++ Privilege::LIST, ++ Privilege::MODIFY, ++ Privilege::LISTEN ++ }) { ++ if (hasPrivilege(section, privilege)) { ++ const std::string privilege_string = privilegeToString(privilege); ++ section_string.append(privilege_string); ++ section_string.append(","); ++ section_is_empty = false; ++ } ++ } ++ ++ if (!section_is_empty) { ++ section_string.pop_back(); ++ access_control_string.append(section_string); ++ access_control_string.append("\n"); ++ } ++ } ++ ++ stream << access_control_string; ++ } ++ ++ void IPCServer::AccessControl::merge(const IPCServer::AccessControl& rhs) ++ { ++ for (auto const& ac_entry : rhs._access_control) { ++ _access_control[ac_entry.first] |= ac_entry.second; ++ } ++ } ++ ++ void IPCServer::AccessControl::merge(const std::string& access_control_string) ++ { ++ const AccessControl access_control(access_control_string); ++ merge(access_control); ++ } ++ ++ IPCServer::IPCServer() ++ { ++ d_pointer = new IPCServerPrivate(*this); ++ } ++ ++ IPCServer::~IPCServer() ++ { ++ delete d_pointer; ++ } ++ ++ void IPCServer::start() ++ { ++ d_pointer->start(); ++ } ++ ++ void IPCServer::stop() ++ { ++ d_pointer->stop(); ++ } ++ ++ void IPCServer::DevicePresenceChanged(uint32_t id, ++ DeviceManager::EventType event, ++ Rule::Target target, ++ const std::string& device_rule) ++ { ++ d_pointer->DevicePresenceChanged(id, event, target, device_rule); ++ } ++ ++ void IPCServer::DevicePolicyChanged(uint32_t id, ++ Rule::Target target_old, ++ Rule::Target target_new, ++ const std::string& device_rule, ++ uint32_t rule_id) ++ { ++ d_pointer->DevicePolicyChanged(id, target_old, target_new, device_rule, rule_id); ++ } ++ ++ void IPCServer::ExceptionMessage(const std::string& context, ++ const std::string& object, ++ const std::string& reason) ++ { ++ d_pointer->ExceptionMessage(context, object, reason); ++ } ++ ++ void IPCServer::addAllowedUID(uid_t uid, const IPCServer::AccessControl& ac) ++ { ++ d_pointer->addAllowedUID(uid, ac); ++ } ++ ++ void IPCServer::addAllowedGID(gid_t gid, const IPCServer::AccessControl& ac) ++ { ++ d_pointer->addAllowedGID(gid, ac); ++ } ++ ++ void IPCServer::addAllowedUsername(const std::string& username, const IPCServer::AccessControl& ac) ++ { ++ d_pointer->addAllowedUsername(username, ac); ++ } ++ ++ void IPCServer::addAllowedGroupname(const std::string& groupname, const IPCServer::AccessControl& ac) ++ { ++ d_pointer->addAllowedGroupname(groupname, ac); ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/IPCServer.hpp b/src/Library/public/usbguard/IPCServer.hpp +new file mode 100644 +index 0000000..cf0242b +--- /dev/null ++++ b/src/Library/public/usbguard/IPCServer.hpp +@@ -0,0 +1,126 @@ ++// ++// Copyright (C) 2016 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "DeviceManager.hpp" ++#include "Interface.hpp" ++#include "Rule.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ class IPCServerPrivate; ++ class DLL_PUBLIC IPCServer : public Interface ++ { ++ public: ++ static void checkAccessControlName(const std::string& name); ++ ++ class AccessControl ++ { ++ public: ++ enum class Section : uint8_t { ++ NONE = 0, ++ DEVICES = 1, ++ POLICY = 2, ++ PARAMETERS = 3, ++ EXCEPTIONS = 4, ++ ALL = 255 ++ }; ++ ++ static Section sectionFromString(const std::string& section_string); ++ static std::string sectionToString(const Section section); ++ ++ enum class Privilege : uint8_t { ++ NONE = 0x00, ++ LIST = 0x01, ++ MODIFY = 0x02, ++ LISTEN = 0x08, ++ ALL = 0xff ++ }; ++ ++ static Privilege privilegeFromString(const std::string& privilege_string); ++ static std::string privilegeToString(const Privilege privilege); ++ ++ AccessControl(); ++ AccessControl(const std::string& access_control_string); ++ AccessControl(Section section, Privilege privilege); ++ AccessControl(const AccessControl& rhs); ++ AccessControl& operator=(const AccessControl& rhs); ++ ++ bool hasPrivilege(Section section, Privilege privilege) const; ++ void setPrivilege(Section section, Privilege privilege); ++ void clear(); ++ void load(std::istream& stream); ++ void save(std::ostream& stream) const; ++ void merge(const AccessControl& rhs); ++ void merge(const std::string& access_control_string); ++ ++ private: ++ struct SectionHash { ++ std::size_t operator()(Section value) const ++ { ++ return static_cast(value); ++ } ++ }; ++ ++ std::unordered_map _access_control; ++ }; ++ ++ IPCServer(); ++ virtual ~IPCServer(); ++ ++ void start(); ++ void stop(); ++ ++ void DevicePresenceChanged(uint32_t id, ++ DeviceManager::EventType event, ++ Rule::Target target, ++ const std::string& device_rule); ++ ++ void DevicePolicyChanged(uint32_t id, ++ Rule::Target target_old, ++ Rule::Target target_new, ++ const std::string& device_rule, ++ uint32_t rule_id); ++ ++ void ExceptionMessage(const std::string& context, ++ const std::string& object, ++ const std::string& reason); ++ ++ void addAllowedUID(uid_t uid, const IPCServer::AccessControl& ac); ++ void addAllowedGID(gid_t gid, const IPCServer::AccessControl& ac); ++ void addAllowedUsername(const std::string& username, const IPCServer::AccessControl& ac); ++ void addAllowedGroupname(const std::string& groupname, const IPCServer::AccessControl& ac); ++ ++ private: ++ IPCServerPrivate* d_pointer; ++ }; ++} /* namespace usbguard */ ++ +diff --git a/src/Library/public/usbguard/Interface.hpp b/src/Library/public/usbguard/Interface.hpp +new file mode 100644 +index 0000000..41f7024 +--- /dev/null ++++ b/src/Library/public/usbguard/Interface.hpp +@@ -0,0 +1,72 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "DeviceManager.hpp" ++#include "Rule.hpp" ++#include "RuleSet.hpp" ++#include "Typedefs.hpp" ++#include "USB.hpp" ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace usbguard ++{ ++ class DLL_PUBLIC Interface ++ { ++ public: ++ /* Parameters */ ++ virtual std::string setParameter(const std::string& name, const std::string& value) = 0; ++ virtual std::string getParameter(const std::string& name) = 0; ++ ++ /* Methods */ ++ virtual uint32_t appendRule(const std::string& rule_spec, ++ uint32_t parent_id) = 0; ++ ++ virtual void removeRule(uint32_t id) = 0; ++ ++ virtual const RuleSet listRules(const std::string& query) = 0; ++ ++ virtual uint32_t applyDevicePolicy(uint32_t id, ++ Rule::Target target, ++ bool permanent) = 0; ++ ++ virtual const std::vector listDevices(const std::string& query) = 0; ++ ++ /* Signals */ ++ virtual void DevicePresenceChanged(uint32_t id, ++ DeviceManager::EventType event, ++ Rule::Target target, ++ const std::string& device_rule) = 0; ++ ++ virtual void DevicePolicyChanged(uint32_t id, ++ Rule::Target target_old, ++ Rule::Target target_new, ++ const std::string& device_rule, ++ uint32_t rule_id) = 0; ++ ++ virtual void ExceptionMessage(const std::string& context, ++ const std::string& object, ++ const std::string& reason) = 0; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Logger.cpp b/src/Library/public/usbguard/Logger.cpp +new file mode 100644 +index 0000000..762b5b6 +--- /dev/null ++++ b/src/Library/public/usbguard/Logger.cpp +@@ -0,0 +1,411 @@ ++// ++// Copyright (C) 2016 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Common/Utility.hpp" ++ ++#include "usbguard/Logger.hpp" ++#include "usbguard/Exception.hpp" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifndef __STDC_FORMAT_MACROS ++#define __STDC_FORMAT_MACROS ++#endif ++#include ++ ++namespace usbguard ++{ ++ /* Instantiate the logger */ ++ Logger G_logger; ++ ++ const std::string LogStream::sourceToString(const Source& source) ++ { ++ return source.file + "@" + std::to_string(source.line) + "/" + source.function; ++ } ++ ++ const std::string LogStream::levelToString(Level level) ++ { ++ switch (level) { ++ case LogStream::Level::Audit: ++ return "(A)"; ++ case LogStream::Level::Error: ++ return "(E)"; ++ case LogStream::Level::Warning: ++ return "(W)"; ++ case LogStream::Level::Info: ++ return "(i)"; ++ case LogStream::Level::Debug: ++ return "(D)"; ++ case LogStream::Level::Trace: ++ return "(T)"; ++ default: ++ throw std::runtime_error("BUG: unknown LogStream level value"); ++ } ++ } ++ ++ LogStream::LogStream(Logger& logger, const Source& source, const Level level) ++ : _logger(logger), ++ _source(source), ++ _level(level) ++ { ++ } ++ ++ LogStream::LogStream(const LogStream& rhs) ++ : std::basic_ios(), ++ std::ostringstream(rhs.str()), ++ _logger(rhs._logger), ++ _source(rhs._source), ++ _level(rhs._level) ++ { ++ } ++ ++ LogStream::~LogStream() ++ { ++ _logger.write(_source, _level, str()); ++ } ++ ++ LogSink::LogSink(const std::string& name) ++ : _name(name) ++ { ++ } ++ ++ LogSink::~LogSink() ++ { ++ } ++ ++ const std::string& LogSink::name() const ++ { ++ return _name; ++ } ++ ++ /* ++ * Internally required sinks ++ */ ++ class OStreamSink : public LogSink ++ { ++ public: ++ OStreamSink(const std::string& name, std::ostream& stream) ++ : LogSink(name), ++ _ostream(stream) ++ { ++ } ++ ++ void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) ++ { ++ _ostream << '[' << Logger::timestamp() << "] "; ++ _ostream << LogStream::levelToString(level) << " "; ++ if (level >= LogStream::Level::Debug) { ++ _ostream << LogStream::sourceToString(source) << ": "; ++ } ++ _ostream << message; ++ _ostream << std::endl; ++ } ++ ++ ~OStreamSink() ++ { ++ _ostream.flush(); ++ } ++ private: ++ std::ostream& _ostream; ++ }; ++ ++ class ConsoleSink : public OStreamSink ++ { ++ public: ++ ConsoleSink() ++ : OStreamSink("console", std::clog) ++ { ++ } ++ }; ++ ++ class SyslogSink : public LogSink ++ { ++ public: ++ SyslogSink(const std::string& ident) ++ : LogSink("syslog"), ++ _ident(ident) ++ { ++ openlog(_ident.c_str(), LOG_NDELAY|LOG_PID|LOG_CONS, LOG_DAEMON); ++ } ++ ++ ~SyslogSink() ++ { ++ closelog(); ++ } ++ ++ int levelToPriority(const LogStream::Level level) ++ { ++ switch (level) { ++ case LogStream::Level::Audit: ++ return LOG_NOTICE; ++ case LogStream::Level::Error: ++ return LOG_ERR; ++ case LogStream::Level::Warning: ++ return LOG_WARNING; ++ case LogStream::Level::Info: ++ return LOG_INFO; ++ case LogStream::Level::Debug: ++ case LogStream::Level::Trace: ++ return LOG_DEBUG; ++ default: ++ throw USBGUARD_BUG("Invalid LogStream::Level value"); ++ } ++ } ++ ++ void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) ++ { ++ std::string log_message; ++ ++ if (level >= LogStream::Level::Debug) { ++ log_message.append(LogStream::sourceToString(source)); ++ log_message.append(": "); ++ } ++ log_message.append(message); ++ ++ syslog(levelToPriority(level), "%s", log_message.c_str()); ++ } ++ ++ private: ++ std::string _ident; ++ }; ++ ++ class FileSink : public OStreamSink ++ { ++ public: ++ FileSink(const std::string& filepath, bool append = true) ++ : OStreamSink("file", _stream) ++ { ++ _filepath = filepath; ++ _stream.open(filepath, append ? std::fstream::app : std::fstream::trunc); ++ } ++ ++ ~FileSink() ++ { ++ _stream.close(); ++ } ++ private: ++ std::string _filepath; ++ std::ofstream _stream; ++ }; ++ ++ class AuditFileSink : public OStreamSink ++ { ++ public: ++ AuditFileSink(const std::string& filepath) ++ : OStreamSink("auditfile", _stream) ++ { ++ _filepath = filepath; ++ const auto saved_umask = umask(0177); ++ try { ++ _stream.open(filepath, std::fstream::app); ++ } ++ catch(...) { ++ umask(saved_umask); ++ throw; ++ } ++ umask(saved_umask); ++ } ++ ++ void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) ++ { ++ /* ++ * AuditFileSink logs only Audit level messages. ++ */ ++ if (level == LogStream::Level::Audit) { ++ OStreamSink::write(source, level, message); ++ } ++ } ++ ++ ~AuditFileSink() ++ { ++ _stream.close(); ++ } ++ private: ++ std::string _filepath; ++ std::ofstream _stream; ++ }; ++ ++ Logger::Logger() ++ : _enabled(true), ++ _level(LogStream::Level::Warning) ++ { ++ const char * const envval = getenv("USBGUARD_DEBUG"); ++ /* ++ * If USBGUARD_DEBUG=1 is set in the current environment, ++ * set the debugging level to the highest level. ++ */ ++ if (envval != nullptr && strcmp(envval, "1") == 0) { ++ _level = LogStream::Level::Trace; ++ } ++ setOutputConsole(true); ++ } ++ ++ Logger::~Logger() ++ { ++ } ++ ++ std::unique_lock Logger::lock() const ++ { ++ return std::unique_lock(_mutex); ++ } ++ ++ void Logger::setEnabled(bool state, LogStream::Level level) ++ { ++ auto L = lock(); ++ _enabled = state; ++ _level = level; ++ } ++ ++ bool Logger::isEnabled(LogStream::Level level) const ++ { ++ auto L = lock(); ++ return (_enabled && _level >= level); ++ } ++ ++ void Logger::setOutputConsole(const bool state) ++ { ++ auto L = lock(); ++ if (state == true) { ++ std::unique_ptr sink(new ConsoleSink); ++ addOutputSink_nolock(sink); ++ } ++ else { ++ delOutputSink_nolock("console"); ++ } ++ } ++ ++ void Logger::setOutputFile(bool state, const std::string& filepath, bool append) ++ { ++ auto L = lock(); ++ if (state == true) { ++ std::unique_ptr sink(new FileSink(filepath, append)); ++ addOutputSink_nolock(sink); ++ } ++ else { ++ delOutputSink_nolock("file"); ++ } ++ } ++ ++ void Logger::setOutputSyslog(bool state, const std::string& ident) ++ { ++ auto L = lock(); ++ if (state == true) { ++ std::unique_ptr sink(new SyslogSink(ident)); ++ addOutputSink_nolock(sink); ++ } ++ else { ++ delOutputSink_nolock("syslog"); ++ } ++ } ++ ++ void Logger::setAuditFile(bool state, const std::string& filepath) ++ { ++ auto L = lock(); ++ if (state == true) { ++ std::unique_ptr sink(new AuditFileSink(filepath)); ++ addOutputSink_nolock(sink); ++ } ++ else { ++ delOutputSink_nolock("auditfile"); ++ } ++ } ++ ++ void Logger::addOutputSink(std::unique_ptr& sink) ++ { ++ auto L = lock(); ++ addOutputSink_nolock(sink); ++ } ++ ++ void Logger::addOutputSink_nolock(std::unique_ptr& sink) ++ { ++ _sinks.emplace(sink->name(), std::move(sink)); ++ } ++ ++ void Logger::delOutputSink(const std::string& name) ++ { ++ auto L = lock(); ++ delOutputSink_nolock(name); ++ } ++ ++ void Logger::delOutputSink_nolock(const std::string& name) ++ { ++ _sinks.erase(name); ++ } ++ ++ LogStream Logger::operator()(const std::string& file, const int line, const std::string& function, LogStream::Level level) ++ { ++ const LogStream::Source source = { ++ filenameFromPath(file, /*include_extension=*/true), line, function ++ }; ++ return LogStream(*this, source, level); ++ } ++ ++ void Logger::write(const LogStream::Source& source, const LogStream::Level level, const std::string& message) ++ { ++ auto L = lock(); ++ for (auto& kv_pair : _sinks) { ++ auto& sink = kv_pair.second; ++ try { ++ sink->write(source, level, message); ++ } ++ catch(const std::exception& ex) { ++ std::cerr << "Warning: sink->write failed for " << sink->name() << " sink: " << ex.what() << std::endl; ++ } ++ } ++ } ++ ++ /* ++ * Generate a timestamp string in the form: ++ * . ++ */ ++ const std::string Logger::timestamp() ++ { ++ struct timeval tv_now = { 0, 0 }; ++ ++ if (gettimeofday(&tv_now, nullptr) != 0) { ++ throw std::runtime_error("gettimeofday"); ++ } ++ ++ /* ++ * The following piece of code should work fine until ++ * Sat Nov 20 17:46:39 UTC 2286. ++ */ ++ char buffer[16]; ++ const int length = snprintf(buffer, sizeof buffer, "%.10" PRIu64 ".%03" PRIu64, ++ (uint64_t)tv_now.tv_sec, ++ (uint64_t)(tv_now.tv_usec / 1000)); ++ ++ if (length < 1 || static_cast(length) > (sizeof buffer - 1)) { ++ throw std::runtime_error("Failed to convert timestamp to string"); ++ } ++ ++ return std::string(buffer, (size_t)length); ++ } ++} /* namespace usbguard */ ++ +diff --git a/src/Library/public/usbguard/Logger.hpp b/src/Library/public/usbguard/Logger.hpp +new file mode 100644 +index 0000000..82fb341 +--- /dev/null ++++ b/src/Library/public/usbguard/Logger.hpp +@@ -0,0 +1,136 @@ ++// ++// Copyright (C) 2016 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++namespace usbguard ++{ ++ class Logger; ++ ++ class DLL_PUBLIC LogStream : public std::ostringstream ++ { ++ public: ++ struct Source { ++ std::string file; ++ int line; ++ std::string function; ++ }; ++ ++ static const std::string sourceToString(const Source& source); ++ ++ enum class Level : int { ++ Audit = -2, ++ Error = -1, ++ Warning = 0, ++ Info = 1, ++ Debug = 2, ++ Trace = 3 ++ }; ++ ++ static const std::string levelToString(Level level); ++ ++ LogStream(Logger& logger, const Source& source, Level level); ++ LogStream(const LogStream& rhs); ++ ++ ~LogStream(); ++ ++ private: ++ Logger& _logger; ++ Source _source; ++ Level _level; ++ }; ++ ++ class DLL_PUBLIC LogSink ++ { ++ public: ++ LogSink(const std::string& name); ++ virtual ~LogSink(); ++ ++ const std::string& name() const; ++ ++ virtual void write(const LogStream::Source& source, LogStream::Level level, const std::string& message) = 0; ++ ++ private: ++ std::string _name; ++ }; ++ ++ class DLL_PUBLIC Logger ++ { ++ public: ++ Logger(); ++ ~Logger(); ++ ++ void setEnabled(bool state, LogStream::Level level = LogStream::Level::Warning); ++ bool isEnabled(LogStream::Level level) const; ++ ++ void setOutputConsole(bool state); ++ void setOutputFile(bool state, const std::string& filepath = std::string(), bool append = true); ++ void setOutputSyslog(bool state, const std::string& ident = std::string()); ++ void setAuditFile(bool state, const std::string& filepath); ++ ++ void addOutputSink(std::unique_ptr& sink); ++ void delOutputSink(const std::string& name); ++ ++ LogStream operator()(const std::string& file, int line, const std::string& function, LogStream::Level level); ++ ++ void write(const LogStream::Source& source, LogStream::Level level, const std::string& message); ++ ++ /* ++ * Generate a timestamp string in the form: ++ * . ++ */ ++ static const std::string timestamp(); ++ ++ private: ++ void addOutputSink_nolock(std::unique_ptr& sink); ++ void delOutputSink_nolock(const std::string& name); ++ ++ std::unique_lock lock() const; ++ ++ mutable std::mutex _mutex; ++ bool _enabled; ++ LogStream::Level _level; ++ std::map> _sinks; ++ }; ++ ++ extern DLL_PUBLIC Logger G_logger; ++ ++#if defined(__GNUC__) ++# define USBGUARD_SOURCE_FILE __BASE_FILE__ ++#else ++# define USBGUARD_SOURCE_FILE __FILE__ ++#endif ++ ++#define USBGUARD_LOGGER usbguard::G_logger ++ ++#define USBGUARD_FUNCTION __func__ ++ ++#define USBGUARD_LOG(level) \ ++ if (USBGUARD_LOGGER.isEnabled(usbguard::LogStream::Level::level)) \ ++ USBGUARD_LOGGER(USBGUARD_SOURCE_FILE, __LINE__, USBGUARD_FUNCTION, usbguard::LogStream::Level::level) ++ ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Policy.cpp b/src/Library/public/usbguard/Policy.cpp +new file mode 100644 +index 0000000..9838239 +--- /dev/null ++++ b/src/Library/public/usbguard/Policy.cpp +@@ -0,0 +1,41 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/Policy.hpp" ++#include "usbguard/Exception.hpp" ++ ++namespace usbguard ++{ ++ std::string Policy::eventTypeToString(Policy::EventType event) ++ { ++ switch(event) { ++ case Policy::EventType::Insert: ++ return "Insert"; ++ case Policy::EventType::Update: ++ return "Update"; ++ case Policy::EventType::Remove: ++ return "Remove"; ++ default: ++ throw USBGUARD_BUG("unknown Policy::EventType value"); ++ } ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Policy.hpp b/src/Library/public/usbguard/Policy.hpp +new file mode 100644 +index 0000000..05a0c7e +--- /dev/null ++++ b/src/Library/public/usbguard/Policy.hpp +@@ -0,0 +1,39 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++ ++namespace usbguard ++{ ++ class DLL_PUBLIC Policy ++ { ++ public: ++ enum class EventType ++ { ++ Insert = 1, ++ Update = 2, ++ Remove = 3, ++ }; ++ ++ static std::string eventTypeToString(EventType event); ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Predicates.hpp b/src/Library/public/usbguard/Predicates.hpp +new file mode 100644 +index 0000000..541efc2 +--- /dev/null ++++ b/src/Library/public/usbguard/Predicates.hpp +@@ -0,0 +1,39 @@ ++// ++// Copyright (C) 2016 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Logger.hpp" ++#include "Typedefs.hpp" ++ ++namespace usbguard ++{ ++ namespace Predicates DLL_PUBLIC ++ { ++ /* ++ * Return true if the source set is a subset of the ++ * target set. Otherwise return false. ++ */ ++ template ++ bool isSubsetOf(const T& source, const T& target) ++ { ++ USBGUARD_LOG(Trace) << "generic isSubsetOf"; ++ return source == target; ++ } ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Rule.cpp b/src/Library/public/usbguard/Rule.cpp +new file mode 100644 +index 0000000..ba68257 +--- /dev/null ++++ b/src/Library/public/usbguard/Rule.cpp +@@ -0,0 +1,350 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "RulePrivate.hpp" ++#include "Utility.hpp" ++ ++namespace usbguard { ++ template<> ++ std::string toRuleString(const std::string& value) ++ { ++ return Utility::quoteEscapeString(value); ++ } ++ ++ const uint32_t Rule::RootID = std::numeric_limits::min(); ++ const uint32_t Rule::DefaultID = std::numeric_limits::max(); ++ const uint32_t Rule::LastID = std::numeric_limits::max() - 2; ++ const uint32_t Rule::ImplicitID = std::numeric_limits::max() - 1; ++ ++ Rule::Rule() ++ { ++ d_pointer = new RulePrivate(*this); ++ } ++ ++ Rule::~Rule() ++ { ++ delete d_pointer; ++ d_pointer = nullptr; ++ } ++ ++ Rule::Rule(const Rule& rhs) ++ { ++ d_pointer = new RulePrivate(*this, *rhs.d_pointer); ++ } ++ ++ const Rule& Rule::operator=(const Rule& rhs) ++ { ++ RulePrivate* n_pointer = new RulePrivate(*this, *rhs.d_pointer); ++ delete d_pointer; ++ d_pointer = n_pointer; ++ return *this; ++ } ++ ++ void Rule::setRuleID(uint32_t rule_id) ++ { ++ d_pointer->setRuleID(rule_id); ++ } ++ ++ uint32_t Rule::getRuleID() const ++ { ++ return d_pointer->getRuleID(); ++ } ++ ++ void Rule::setTarget(Rule::Target target) ++ { ++ d_pointer->setTarget(target); ++ } ++ ++ Rule::Target Rule::getTarget() const ++ { ++ return d_pointer->getTarget(); ++ } ++ ++ void Rule::setDeviceID(const USBDeviceID& value) ++ { ++ d_pointer->setDeviceID(value); ++ } ++ ++ const USBDeviceID& Rule::getDeviceID() const ++ { ++ return d_pointer->getDeviceID(); ++ } ++ ++ const Rule::Attribute& Rule::attributeDeviceID() const ++ { ++ return d_pointer->attributeDeviceID(); ++ } ++ ++ Rule::Attribute& Rule::attributeDeviceID() ++ { ++ return d_pointer->attributeDeviceID(); ++ } ++ ++ void Rule::setSerial(const std::string& value) ++ { ++ d_pointer->setSerial(value); ++ } ++ ++ const std::string& Rule::getSerial() const ++ { ++ return d_pointer->getSerial(); ++ } ++ ++ const Rule::Attribute& Rule::attributeSerial() const ++ { ++ return d_pointer->attributeSerial(); ++ } ++ ++ Rule::Attribute& Rule::attributeSerial() ++ { ++ return d_pointer->attributeSerial(); ++ } ++ ++ void Rule::setName(const std::string& value) ++ { ++ d_pointer->setName(value); ++ } ++ ++ const std::string& Rule::getName() const ++ { ++ return d_pointer->getName(); ++ } ++ ++ const Rule::Attribute& Rule::attributeName() const ++ { ++ return d_pointer->attributeName(); ++ } ++ ++ Rule::Attribute& Rule::attributeName() ++ { ++ return d_pointer->attributeName(); ++ } ++ ++ void Rule::setHash(const std::string& value) ++ { ++ d_pointer->setHash(value); ++ } ++ ++ const std::string& Rule::getHash() const ++ { ++ return d_pointer->getHash(); ++ } ++ ++ const Rule::Attribute& Rule::attributeHash() const ++ { ++ return d_pointer->attributeHash(); ++ } ++ ++ Rule::Attribute& Rule::attributeHash() ++ { ++ return d_pointer->attributeHash(); ++ } ++ ++ void Rule::setParentHash(const std::string& value) ++ { ++ d_pointer->setParentHash(value); ++ } ++ ++ const std::string& Rule::getParentHash() const ++ { ++ return d_pointer->getParentHash(); ++ } ++ ++ const Rule::Attribute& Rule::attributeParentHash() const ++ { ++ return d_pointer->attributeParentHash(); ++ } ++ ++ Rule::Attribute& Rule::attributeParentHash() ++ { ++ return d_pointer->attributeParentHash(); ++ } ++ ++ void Rule::setViaPort(const std::string& value) ++ { ++ d_pointer->setViaPort(value); ++ } ++ ++ const std::string& Rule::getViaPort() const ++ { ++ return d_pointer->getViaPort(); ++ } ++ ++ const Rule::Attribute& Rule::attributeViaPort() const ++ { ++ return d_pointer->attributeViaPort(); ++ } ++ ++ Rule::Attribute& Rule::attributeViaPort() ++ { ++ return d_pointer->attributeViaPort(); ++ } ++ ++ const Rule::Attribute& Rule::attributeWithInterface() const ++ { ++ return d_pointer->attributeWithInterface(); ++ } ++ ++ Rule::Attribute& Rule::attributeWithInterface() ++ { ++ return d_pointer->attributeWithInterface(); ++ } ++ ++ const Rule::Attribute& Rule::attributeConditions() const ++ { ++ return d_pointer->attributeConditions(); ++ } ++ ++ Rule::Attribute& Rule::attributeConditions() ++ { ++ return d_pointer->attributeConditions(); ++ } ++ ++ bool Rule::appliesTo(std::shared_ptr rhs) const ++ { ++ return appliesTo(*rhs); ++ } ++ ++ bool Rule::appliesTo(const Rule& rhs) const ++ { ++ return d_pointer->appliesTo(rhs); ++ } ++ ++ bool Rule::appliesTo(const Rule& rhs) ++ { ++ updateMetaDataCounters(/*applied=*/false, /*evaluated=*/true); ++ return d_pointer->appliesTo(rhs); ++ } ++ ++ bool Rule::isImplicit() const ++ { ++ return d_pointer->getRuleID() == Rule::DefaultID; ++ } ++ ++ Rule::operator bool() const ++ { ++ return !(getTarget() == Target::Unknown || ++ getTarget() == Target::Invalid); ++ } ++ ++ std::string Rule::toString(bool invalid) const ++ { ++ return d_pointer->toString(invalid); ++ } ++ ++ void Rule::updateMetaDataCounters(bool applied, bool evaluated) ++ { ++ d_pointer->updateMetaDataCounters(applied, evaluated); ++ } ++ ++ Rule Rule::fromString(const std::string& rule_string) ++ { ++ return RulePrivate::fromString(rule_string); ++ } ++ ++ RulePrivate* Rule::internal() ++ { ++ return d_pointer; ++ } ++ ++ const RulePrivate* Rule::internal() const ++ { ++ return d_pointer; ++ } ++ ++ static const std::vector > target_ttable = { ++ { "allow", Rule::Target::Allow }, ++ { "block", Rule::Target::Block }, ++ { "reject", Rule::Target::Reject }, ++ { "match", Rule::Target::Match }, ++ { "device", Rule::Target::Device } ++ }; ++ ++ const std::string Rule::targetToString(const Rule::Target target) ++ { ++ for (auto ttable_entry : target_ttable) { ++ if (ttable_entry.second == target) { ++ return ttable_entry.first; ++ } ++ } ++ throw std::runtime_error("Invalid rule target string"); ++ } ++ ++ Rule::Target Rule::targetFromString(const std::string& target_string) ++ { ++ for (auto ttable_entry : target_ttable) { ++ if (ttable_entry.first == target_string) { ++ return ttable_entry.second; ++ } ++ } ++ throw std::runtime_error("Invalid rule target string"); ++ } ++ ++ uint32_t Rule::targetToInteger(const Rule::Target target) ++ { ++ return static_cast(target); ++ } ++ ++ Rule::Target Rule::targetFromInteger(const uint32_t target_integer) ++ { ++ switch(target_integer) { ++ case static_cast(Rule::Target::Allow): ++ case static_cast(Rule::Target::Block): ++ case static_cast(Rule::Target::Reject): ++ case static_cast(Rule::Target::Match): ++ case static_cast(Rule::Target::Device): ++ break; ++ default: ++ throw std::runtime_error("Invalid rule target integer value"); ++ } ++ return static_cast(target_integer); ++ } ++ ++ static const std::vector > set_operator_ttable = { ++ { "all-of", Rule::SetOperator::AllOf }, ++ { "one-of", Rule::SetOperator::OneOf }, ++ { "none-of", Rule::SetOperator::NoneOf }, ++ { "equals", Rule::SetOperator::Equals }, ++ { "equals-ordered", Rule::SetOperator::EqualsOrdered }, ++ { "match", Rule::SetOperator::Match } ++ }; ++ ++ const std::string Rule::setOperatorToString(const Rule::SetOperator& op) ++ { ++ for (auto ttable_entry : set_operator_ttable) { ++ if (ttable_entry.second == op) { ++ return ttable_entry.first; ++ } ++ } ++ throw std::runtime_error("Invalid set operator string"); ++ } ++ ++ Rule::SetOperator Rule::setOperatorFromString(const std::string& set_operator_string) ++ { ++ for (auto ttable_entry : set_operator_ttable) { ++ if (ttable_entry.first == set_operator_string) { ++ return ttable_entry.second; ++ } ++ } ++ throw std::runtime_error("Invalid set operator string"); ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Rule.hpp b/src/Library/public/usbguard/Rule.hpp +new file mode 100644 +index 0000000..81f03f2 +--- /dev/null ++++ b/src/Library/public/usbguard/Rule.hpp +@@ -0,0 +1,479 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "RuleCondition.hpp" ++#include "Exception.hpp" ++#include "Logger.hpp" ++#include "Predicates.hpp" ++#include "Typedefs.hpp" ++#include "USB.hpp" ++ ++#include ++#include ++#include ++#include ++ ++namespace usbguard { ++ template ++ std::string toRuleString(T* const value) ++ { ++ return value->toRuleString(); ++ } ++ ++ template ++ std::string toRuleString(const T& value) ++ { ++ return value.toRuleString(); ++ } ++ ++ template<> ++ std::string DLL_PUBLIC toRuleString(const std::string& value); ++ ++ class RulePrivate; ++ class DLL_PUBLIC Rule ++ { ++ public: ++ /** ++ * Rule target enumeration. ++ */ ++ enum class Target { ++ Allow = 0, /**< Devices matching this rule will be authorized */ ++ Block = 1, /**< Devices matching this rule will not be authorized */ ++ Reject = 2, /**< Devices matching this rule will not be authorized and will be detached */ ++ Match = 3, /**< Special target which can be used to trigger actions. The rule wont affect the final decision. */ ++ Unknown = 4, /**< Unknown target. Used for default constructed rules. */ ++ Device = 5, /**< Special target which can only be used for a rule that represents a single device */ ++ Invalid = 6 ++ }; ++ ++ static const std::string targetToString(Target target); ++ static Target targetFromString(const std::string& target_string); ++ ++ static uint32_t targetToInteger(Target target); ++ static Target targetFromInteger(uint32_t target_integer); ++ ++ enum class SetOperator ++ { ++ AllOf, ++ OneOf, ++ NoneOf, ++ Equals, ++ EqualsOrdered, ++ Match /* Special operator: matches anything, cannot be used directly in a rule */ ++ }; ++ ++ static const std::string setOperatorToString(const Rule::SetOperator& op); ++ static SetOperator setOperatorFromString(const std::string& set_operator_string); ++ ++ /**< Sequence number of the (fake) root rule */ ++ static const uint32_t RootID; ++ /**< Sequence number assigned to default constructed rules. Cannot be used for searching. */ ++ static const uint32_t DefaultID; ++ /**< Sequence number for specifying that the last rule in the ruleset should be used in context of the operation */ ++ static const uint32_t LastID; ++ /**< Sequence number of the implicit target rule */ ++ static const uint32_t ImplicitID; ++ ++ template ++ class Attribute ++ { ++ public: ++ Attribute(const char * name) ++ { ++ _name = name; ++ _set_operator = SetOperator::Equals; ++ } ++ ++ Attribute(const Attribute& rhs) ++ { ++ _name = rhs._name; ++ _set_operator = rhs._set_operator; ++ _values = rhs._values; ++ } ++ ++ void setSetOperator(SetOperator op) ++ { ++ _set_operator = op; ++ } ++ ++ SetOperator setOperator() const ++ { ++ return _set_operator; ++ } ++ ++ void append(ValueType&& value) ++ { ++ _values.emplace_back(std::move(value)); ++ } ++ ++ void append(const ValueType& value) ++ { ++ _values.push_back(value); ++ } ++ ++ size_t count() const ++ { ++ return _values.size(); ++ } ++ ++ bool empty() const ++ { ++ return count() == 0; ++ } ++ ++ void clear() ++ { ++ _values.clear(); ++ _set_operator = SetOperator::Equals; ++ } ++ ++ const ValueType& get() const ++ { ++ if (count() == 1) { ++ return _values[0]; ++ } ++ else if (count() == 0) { ++ throw std::runtime_error("BUG: Accessing an empty attribute"); ++ } ++ else { ++ throw std::runtime_error("BUG: Accessing a multivalued attribute using get()"); ++ } ++ } ++ ++ const ValueType& get(size_t index) const ++ { ++ return _values.at(index); ++ } ++ ++ void set(ValueType&& value) ++ { ++ if (count() > 1) { ++ throw std::runtime_error("BUG: Setting single value for a multivalued attribute"); ++ } ++ if (count() == 0) { ++ append(value); ++ } ++ else { ++ _values[0] = std::move(value); ++ } ++ } ++ ++ void set(const ValueType& value) ++ { ++ if (count() > 1) { ++ throw std::runtime_error("BUG: Setting single value for a multivalued attribute"); ++ } ++ if (count() == 0) { ++ append(value); ++ } ++ else { ++ _values[0] = value; ++ } ++ } ++ ++ void set(const std::vector& values, SetOperator op) ++ { ++ _values = values; ++ _set_operator = op; ++ } ++ ++ bool appliesTo(const Attribute& target) const ++ { ++ USBGUARD_LOG(Trace) << "entry:" ++ << " source=" << this->toRuleString() ++ << " target=" << target.toRuleString(); ++ ++ bool applies = false; ++ ++ /* Nothing applies to anything */ ++ if (empty()) { ++ USBGUARD_LOG(Debug) << "empty source value, setting applies=true"; ++ applies = true; ++ } ++ else { ++ USBGUARD_LOG(Debug) << "set_operator=" << setOperatorToString(setOperator()); ++ switch(setOperator()) { ++ case SetOperator::Match: ++ applies = true; ++ break; ++ case SetOperator::AllOf: ++ applies = setSolveAllOf(_values, target._values); ++ break; ++ case SetOperator::OneOf: ++ applies = setSolveOneOf(_values, target._values); ++ break; ++ case SetOperator::NoneOf: ++ applies = setSolveNoneOf(_values, target._values); ++ break; ++ case SetOperator::Equals: ++ applies = setSolveEquals(_values, target._values); ++ break; ++ case SetOperator::EqualsOrdered: ++ applies = setSolveEqualsOrdered(_values, target._values); ++ break; ++ default: ++ throw USBGUARD_BUG("Invalid set operator value"); ++ } ++ } ++ ++ USBGUARD_LOG(Trace) << "return:" ++ << " applies=" << applies; ++ ++ return applies; ++ } ++ ++ std::string toRuleString() const ++ { ++ std::string result; ++ ++ result.append(_name); ++ result.append(" "); ++ ++ const bool nondefault_op = setOperator() != SetOperator::Equals; ++ const bool multiset_form = count() > 1 || nondefault_op; ++ ++ if (multiset_form) { ++ if (nondefault_op) { ++ result.append(setOperatorToString(setOperator())); ++ result.append(" "); ++ } ++ result.append("{ "); ++ } ++ ++ for(const auto& value : _values) { ++ result.append(usbguard::toRuleString(value)); ++ result.append(" "); ++ } ++ ++ if (multiset_form) { ++ result.append("}"); ++ } ++ else { ++ /* ++ * Remove the trailing space in case of a single ++ * valued attribute. ++ */ ++ result.erase(result.end() - 1); ++ } ++ ++ return result; ++ } ++ ++ const std::vector& values() const ++ { ++ return _values; ++ } ++ ++ std::vector& values() ++ { ++ return _values; ++ } ++ ++ private: ++ /* ++ * All of the items in source set must match an item in the target set ++ */ ++ bool setSolveAllOf(const std::vector& source_set, const std::vector& target_set) const ++ { ++ USBGUARD_LOG(Trace); ++ ++ for (auto const& source_item : source_set) { ++ bool match = false; ++ for (auto const& target_item : target_set) { ++ if (Predicates::isSubsetOf(source_item, target_item)) { ++ match = true; ++ break; ++ } ++ } ++ if (!match) { ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ /* ++ * At least one of the items in the source set must match an item in the target set ++ */ ++ bool setSolveOneOf(const std::vector& source_set, const std::vector& target_set) const ++ { ++ USBGUARD_LOG(Trace); ++ ++ for (auto const& source_item : source_set) { ++ for (auto const& target_item : target_set) { ++ if (Predicates::isSubsetOf(source_item, target_item)) { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ /* ++ * None of the the items in the rule set must match any item in the ++ * applies_to set ++ */ ++ bool setSolveNoneOf(const std::vector& source_set, const std::vector& target_set) const ++ { ++ USBGUARD_LOG(Trace); ++ ++ for (auto const& source_item : source_set) { ++ for (auto const& target_item : target_set) { ++ if (Predicates::isSubsetOf(source_item, target_item)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } ++ ++ /* ++ * Every item in the rule set must match one item in the ++ * applies_to set and the sets have to have the same number ++ * of items ++ */ ++ bool setSolveEquals(const std::vector& source_set, const std::vector& target_set) const ++ { ++ USBGUARD_LOG(Trace); ++ ++ if (source_set.size() != target_set.size()) { ++ return false; ++ } ++ else { ++ for (auto const& source_item : source_set) { ++ bool match = false; ++ for (auto const& target_item : target_set) { ++ if (Predicates::isSubsetOf(source_item, target_item)) { ++ match = true; ++ break; ++ } ++ } ++ if (!match) { ++ return false; ++ } ++ } ++ return true; ++ } ++ } ++ ++ /* ++ * The sets are treated as arrays and they have to me equal ++ * (same number of items at the same positions) ++ */ ++ bool setSolveEqualsOrdered(const std::vector& source_set, const std::vector& target_set) const ++ { ++ USBGUARD_LOG(Trace); ++ ++ if (source_set.size() != target_set.size()) { ++ return false; ++ } ++ for (size_t i = 0; i < source_set.size(); ++i) { ++ if (!Predicates::isSubsetOf(source_set[i], target_set[i])) { ++ return false; ++ } ++ } ++ return false; ++ } ++ ++ std::string _name; ++ SetOperator _set_operator; ++ std::vector _values; ++ }; ++ ++ /** ++ * Construct a default rule. ++ * This rule matches only a default rule and cannot be converted to a string ++ * representation. ++ */ ++ Rule(); ++ ~Rule(); ++ Rule(const Rule& rhs); ++ const Rule& operator=(const Rule& rhs); ++ ++ void setRuleID(uint32_t rule_id); ++ uint32_t getRuleID() const; ++ ++ void setTarget(Rule::Target target); ++ Target getTarget() const; ++ ++ void setDeviceID(const USBDeviceID& value); ++ const USBDeviceID& getDeviceID() const; ++ const Attribute& attributeDeviceID() const; ++ Attribute& attributeDeviceID(); ++ ++ void setSerial(const std::string& value); ++ const std::string& getSerial() const; ++ const Attribute& attributeSerial() const; ++ Attribute& attributeSerial(); ++ ++ void setName(const std::string& value); ++ const std::string& getName() const; ++ const Attribute& attributeName() const; ++ Attribute& attributeName(); ++ ++ void setHash(const std::string& value); ++ const std::string& getHash() const; ++ const Attribute& attributeHash() const; ++ Attribute& attributeHash(); ++ ++ void setParentHash(const std::string& value); ++ const std::string& getParentHash() const; ++ const Rule::Attribute& attributeParentHash() const; ++ ++ Rule::Attribute& attributeParentHash(); ++ ++ void setViaPort(const std::string& value); ++ const std::string& getViaPort() const; ++ const Attribute& attributeViaPort() const; ++ Attribute& attributeViaPort(); ++ ++ /* ++ * Set/get for a single value isn't useful for the ++ * with-interface attribute as it usualy contains ++ * multiple values. Therefore, we provide only the ++ * attribute accessors in this case. ++ */ ++ const Attribute& attributeWithInterface() const; ++ Attribute& attributeWithInterface(); ++ ++ const Attribute& attributeConditions() const; ++ Attribute& attributeConditions(); ++ ++ bool appliesTo(std::shared_ptr rhs) const; ++ bool appliesTo(const Rule& rhs) const; ++ bool appliesTo(const Rule& rhs); ++ bool isImplicit() const; ++ ++ ++ operator bool() const; ++ std::string toString(bool invalid = false) const; ++ ++ void updateMetaDataCounters(bool applied = true, bool evaluated = false); ++ ++ RulePrivate* internal(); ++ const RulePrivate* internal() const; ++ ++ /*** Static methods ***/ ++ static Rule fromString(const std::string& rule_string); ++ ++ private: ++ RulePrivate* d_pointer; ++ }; ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/RuleCondition.cpp b/src/Library/public/usbguard/RuleCondition.cpp +new file mode 100644 +index 0000000..c3515de +--- /dev/null ++++ b/src/Library/public/usbguard/RuleCondition.cpp +@@ -0,0 +1,245 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "usbguard/RuleCondition.hpp" ++ ++#include "usbguard/Rule.hpp" ++#include "usbguard/Logger.hpp" ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ RuleConditionBase::RuleConditionBase(const std::string& identifier, const std::string& parameter, bool negated) ++ : _identifier(identifier), ++ _parameter(parameter), ++ _negated(negated) ++ { ++ } ++ ++ RuleConditionBase::RuleConditionBase(const std::string& identifier, bool negated) ++ : _identifier(identifier), ++ _negated(negated) ++ { ++ } ++ ++ RuleConditionBase::RuleConditionBase(const RuleConditionBase& rhs) ++ : _identifier(rhs._identifier), ++ _parameter(rhs._parameter), ++ _negated(rhs._negated) ++ { ++ } ++ ++ RuleConditionBase::~RuleConditionBase() ++ { ++ fini(); ++ } ++ ++ void RuleConditionBase::init(Interface * const interface_ptr) ++ { ++ (void)interface_ptr; ++ } ++ ++ void RuleConditionBase::fini() ++ { ++ } ++ ++ bool RuleConditionBase::evaluate(const Rule& rule) ++ { ++ return isNegated() ? !update(rule) : update(rule); ++ } ++ ++ const std::string& RuleConditionBase::identifier() const ++ { ++ return _identifier; ++ } ++ ++ const std::string& RuleConditionBase::parameter() const ++ { ++ return _parameter; ++ } ++ ++ bool RuleConditionBase::hasParameter() const ++ { ++ return !_parameter.empty(); ++ } ++ ++ bool RuleConditionBase::isNegated() const ++ { ++ return _negated; ++ } ++ ++ const std::string RuleConditionBase::toString() const ++ { ++ std::string condition_string; ++ ++ if (isNegated()) { ++ condition_string.append("!"); ++ } ++ ++ condition_string.append(identifier()); ++ ++ if (hasParameter()) { ++ condition_string.append("("); ++ condition_string.append(parameter()); /* TODO: Escape parameter string */ ++ condition_string.append(")"); ++ } ++ ++ return condition_string; ++ } ++ ++ const std::string RuleConditionBase::toRuleString() const ++ { ++ return toString(); ++ } ++} /* namespace usbguard */ ++ ++#include "AllowedMatchesCondition.hpp" ++#include "LocaltimeCondition.hpp" ++#include "FixedStateCondition.hpp" ++#include "RandomStateCondition.hpp" ++#include "RuleAppliedCondition.hpp" ++#include "RuleEvaluatedCondition.hpp" ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ RuleConditionBase* RuleConditionBase::getImplementation(const std::string& condition_string) ++ { ++ if (condition_string.empty()) { ++ throw std::runtime_error("Empty condition"); ++ } ++ ++ const bool negated = condition_string[0] == '!'; ++ const size_t identifier_start = negated ? 1 : 0; ++ const size_t p_pos = condition_string.find_first_of('('); ++ ++ std::string identifier; ++ std::string parameter; ++ ++ if (p_pos == std::string::npos) { ++ /* ++ * The rest of the condition_string should be ++ * a condition identifier -- without a parameter. ++ */ ++ identifier = condition_string.substr(identifier_start); ++ ++ if (identifier.size() < 1) { ++ throw std::runtime_error("Invalid condition string. Missing identifier."); ++ } ++ } ++ else { ++ const size_t parameter_size = condition_string.size() - p_pos; ++ ++ if (parameter_size < 3 /* two parentheses + at least one character */) { ++ throw std::runtime_error("Invalid condition string. Invalid parameter."); ++ } ++ ++ const size_t identifier_size = p_pos - identifier_start; ++ identifier = condition_string.substr(identifier_start, identifier_size); ++ ++ if (condition_string[condition_string.size() - 1] != ')') { ++ throw std::runtime_error("Invalid condition string. Malformed parameter."); ++ } ++ ++ parameter = condition_string.substr(p_pos + 1, parameter_size - 2); ++ } ++ ++ return getImplementation(identifier, parameter, negated); ++ } ++ ++ RuleConditionBase* RuleConditionBase::getImplementation(const std::string& identifier, const std::string& parameter, bool negated) ++ { ++ if (identifier == "allowed-matches") { ++ return new AllowedMatchesCondition(parameter, negated); ++ } ++ if (identifier == "localtime") { ++ return new LocaltimeCondition(parameter, negated); ++ } ++ if (identifier == "true") { ++ return new FixedStateCondition(true, negated); ++ } ++ if (identifier == "false") { ++ return new FixedStateCondition(false, negated); ++ } ++ if (identifier == "random") { ++ return new RandomStateCondition(parameter, negated); ++ } ++ if (identifier == "rule-applied") { ++ return new RuleAppliedCondition(parameter, negated); ++ } ++ if (identifier == "rule-evaluated") { ++ return new RuleEvaluatedCondition(parameter, negated); ++ } ++ throw std::runtime_error("Unknown rule condition"); ++ } ++ ++ RuleCondition::RuleCondition() ++ { ++ } ++ ++ RuleCondition::RuleCondition(const std::string& condition_string) ++ : _condition(RuleConditionBase::getImplementation(condition_string)) ++ { ++ } ++ ++ RuleCondition::RuleCondition(const RuleCondition& rhs) ++ : _condition(rhs._condition->clone()) ++ { ++ } ++ ++ RuleCondition::RuleCondition(RuleCondition&& rhs) ++ : _condition(std::move(rhs._condition)) ++ { ++ } ++ ++ RuleCondition& RuleCondition::operator=(const RuleCondition& rhs) ++ { ++ _condition.reset(rhs._condition->clone()); ++ return *this; ++ } ++ ++ RuleCondition& RuleCondition::operator=(RuleCondition&& rhs) ++ { ++ _condition = std::move(rhs._condition); ++ return *this; ++ } ++ ++ RuleConditionBase* RuleCondition::operator->() ++ { ++ return _condition.get(); ++ } ++ ++ RuleConditionBase& RuleCondition::operator*() ++ { ++ return *_condition.get(); ++ } ++ ++ std::string RuleCondition::toRuleString() const ++ { ++ return _condition->toRuleString(); ++ } ++} /* namespace usbguard */ ++ +diff --git a/src/Library/public/usbguard/RuleCondition.hpp b/src/Library/public/usbguard/RuleCondition.hpp +new file mode 100644 +index 0000000..3a4d6a4 +--- /dev/null ++++ b/src/Library/public/usbguard/RuleCondition.hpp +@@ -0,0 +1,79 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++#include ++ ++namespace usbguard ++{ ++ class Interface; ++ class Rule; ++ class DLL_PUBLIC RuleConditionBase ++ { ++ public: ++ RuleConditionBase(const std::string& identifier, const std::string& parameter, bool negated = false); ++ RuleConditionBase(const std::string& identifier, bool negated = false); ++ RuleConditionBase(const RuleConditionBase& rhs); ++ virtual ~RuleConditionBase(); ++ ++ virtual void init(Interface * const interface_ptr); ++ virtual void fini(); ++ virtual bool update(const Rule& rule) = 0; ++ virtual RuleConditionBase* clone() const = 0; ++ ++ bool evaluate(const Rule& rule); ++ const std::string& identifier() const; ++ const std::string& parameter() const; ++ bool hasParameter() const; ++ bool isNegated() const; ++ const std::string toString() const; ++ const std::string toRuleString() const; ++ ++ static RuleConditionBase* getImplementation(const std::string& condition_string); ++ static RuleConditionBase* getImplementation(const std::string& identifier, const std::string& parameter, bool negated); ++ ++ private: ++ const std::string _identifier; ++ const std::string _parameter; ++ const bool _negated; ++ }; ++ ++ class DLL_PUBLIC RuleCondition ++ { ++ public: ++ RuleCondition(); ++ RuleCondition(const std::string& condition_string); ++ RuleCondition(const RuleCondition& rhs); ++ RuleCondition(RuleCondition&& rhs); ++ ++ RuleCondition& operator=(const RuleCondition& rhs); ++ RuleCondition& operator=(RuleCondition&& rhs); ++ ++ RuleConditionBase* operator->(); ++ RuleConditionBase& operator*(); ++ ++ std::string toRuleString() const; ++ private: ++ std::unique_ptr _condition; ++ }; ++} /*namespace usbguard */ ++ +diff --git a/src/Library/public/usbguard/RuleParser.cpp b/src/Library/public/usbguard/RuleParser.cpp +new file mode 100644 +index 0000000..89c9084 +--- /dev/null ++++ b/src/Library/public/usbguard/RuleParser.cpp +@@ -0,0 +1,83 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "RuleParser.hpp" ++#include "RuleParser/Grammar.hpp" ++#include "RuleParser/Actions.hpp" ++#include "RulePrivate.hpp" ++ ++#include "usbguard/Typedefs.hpp" ++#include "usbguard/USB.hpp" ++#include "usbguard/Logger.hpp" ++#include "Common/Utility.hpp" ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace usbguard ++{ ++ Rule parseRuleFromString(const std::string& rule_spec, const std::string& file, size_t line, bool trace) ++ { ++ try { ++ Rule rule; ++#if HAVE_PEGTL_LTE_1_3_1 ++ if (!trace) { ++ pegtl::parse(rule_spec, file, rule); ++ } ++ else { ++ pegtl::parse(rule_spec, file, rule); ++ } ++#else ++ if (!trace) { ++ pegtl::parse_string(rule_spec, file, rule); ++ } ++ else { ++ pegtl::parse_string(rule_spec, file, rule); ++ } ++#endif ++ return rule; ++ } ++ catch(const pegtl::parse_error& ex) { ++ RuleParserError error(rule_spec); ++ ++ error.setHint(ex.what()); ++#if HAVE_PEGTL_LTE_1_3_1 ++ error.setOffset(ex.positions[0].column); ++#else ++ error.setOffset(ex.positions[0].byte_in_line); ++#endif ++ ++ if (!file.empty() || line != 0) { ++ error.setFileInfo(file, line); ++ } ++ ++ throw error; ++ } ++ catch(const std::exception& ex) { ++ ++ throw; ++ } ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/RuleParser.hpp b/src/Library/public/usbguard/RuleParser.hpp +new file mode 100644 +index 0000000..0b5f53e +--- /dev/null ++++ b/src/Library/public/usbguard/RuleParser.hpp +@@ -0,0 +1,110 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++#include "Rule.hpp" ++ ++#include ++#include ++ ++#include ++ ++namespace usbguard ++{ ++ class RuleParserError : public std::exception ++ { ++ public: ++ RuleParserError(const std::string& rule_spec, const std::string& hint = "", ++ const std::string& file = "", size_t error_line = 0, unsigned int error_offset = 0) ++ : _rule_spec(rule_spec), ++ _hint(hint), ++ _offset(error_offset), ++ _file(file), ++ _line(error_line) ++ { ++ } ++ ++ void setHint(const std::string& hint) ++ { ++ _hint = hint; ++ } ++ ++ void setOffset(size_t offset) ++ { ++ _offset = offset; ++ } ++ ++ void setFileInfo(const std::string& file, size_t error_line, size_t error_offset = 0) ++ { ++ _file = file; ++ _line = error_line; ++ _offset = error_offset; ++ } ++ ++ const char *what() const noexcept ++ { ++ return "RuleParserError"; ++ } ++ ++ const std::string& rule() const ++ { ++ return _rule_spec; ++ } ++ ++ const std::string& hint() const ++ { ++ return _hint; ++ } ++ ++ bool hasFileInfo() const ++ { ++ return !_file.empty(); ++ } ++ ++ const std::string fileInfo() const ++ { ++ return _file + ": line=" + std::to_string(_line) + ": offset=" + std::to_string(_offset); ++ } ++ ++ const std::string& file() const ++ { ++ return _file; ++ } ++ ++ size_t line() const ++ { ++ return _line; ++ } ++ ++ size_t offset() const ++ { ++ return _offset; ++ } ++ ++ protected: ++ const std::string _rule_spec; ++ std::string _hint; ++ size_t _offset; ++ std::string _file; ++ size_t _line; ++ }; ++ ++ DLL_PUBLIC Rule parseRuleFromString(const std::string& rule_spec, const std::string& file = std::string(), size_t line = 0, bool trace = false); ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/RuleSet.cpp b/src/Library/public/usbguard/RuleSet.cpp +new file mode 100644 +index 0000000..1006269 +--- /dev/null ++++ b/src/Library/public/usbguard/RuleSet.cpp +@@ -0,0 +1,126 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Typedefs.hpp" ++#include "RuleSetPrivate.hpp" ++ ++namespace usbguard { ++ RuleSet::RuleSet(Interface * const interface_ptr) ++ { ++ d_pointer = new RuleSetPrivate(*this, interface_ptr); ++ } ++ ++ RuleSet::~RuleSet() ++ { ++ delete d_pointer; ++ d_pointer = nullptr; ++ } ++ ++ RuleSet::RuleSet(const RuleSet& rhs) ++ { ++ d_pointer = new RuleSetPrivate(*this, *rhs.d_pointer); ++ } ++ ++ const RuleSet& RuleSet::operator=(const RuleSet& rhs) ++ { ++ RuleSetPrivate * n_pointer = new RuleSetPrivate(*this, *rhs.d_pointer); ++ delete d_pointer; ++ d_pointer = n_pointer; ++ return *this; ++ } ++ ++ void RuleSet::load(const std::string& path) ++ { ++ d_pointer->load(path); ++ } ++ ++ void RuleSet::load(std::istream& stream) ++ { ++ d_pointer->load(stream); ++ } ++ ++ void RuleSet::save(const std::string& path) const ++ { ++ d_pointer->save(path); ++ } ++ ++ void RuleSet::save(std::ostream& stream) const ++ { ++ d_pointer->save(stream); ++ } ++ ++ void RuleSet::setDefaultTarget(Rule::Target target) ++ { ++ d_pointer->setDefaultTarget(target); ++ } ++ ++ Rule::Target RuleSet::getDefaultTarget() const ++ { ++ return d_pointer->getDefaultTarget(); ++ } ++ ++ void RuleSet::setDefaultAction(const std::string& action) ++ { ++ d_pointer->setDefaultAction(action); ++ } ++ ++ uint32_t RuleSet::appendRule(const Rule& rule, uint32_t parent_id) ++ { ++ return d_pointer->appendRule(rule, parent_id); ++ } ++ ++ uint32_t RuleSet::upsertRule(const Rule& match_rule, const Rule& new_rule, const bool parent_insensitive) ++ { ++ return d_pointer->upsertRule(match_rule, new_rule, parent_insensitive); ++ } ++ ++ std::shared_ptr RuleSet::getRule(uint32_t id) ++ { ++ return d_pointer->getRule(id); ++ } ++ ++ bool RuleSet::removeRule(uint32_t id) ++ { ++ return d_pointer->removeRule(id); ++ } ++ ++ std::shared_ptr RuleSet::getFirstMatchingRule(std::shared_ptr device_rule, uint32_t from_id) const ++ { ++ return d_pointer->getFirstMatchingRule(device_rule, from_id); ++ } ++ ++ std::vector> RuleSet::getRules() ++ { ++ return d_pointer->getRules(); ++ } ++ ++ uint32_t RuleSet::assignID(std::shared_ptr rule) ++ { ++ return d_pointer->assignID(rule); ++ } ++ ++ uint32_t RuleSet::assignID() ++ { ++ return d_pointer->assignID(); ++ } ++ ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/RuleSet.hpp b/src/Library/public/usbguard/RuleSet.hpp +new file mode 100644 +index 0000000..6893e38 +--- /dev/null ++++ b/src/Library/public/usbguard/RuleSet.hpp +@@ -0,0 +1,149 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Rule.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++namespace usbguard { ++ class RuleSetPrivate; ++ class Interface; ++ class DLL_PUBLIC RuleSet ++ { ++ public: ++ /** ++ * Construct an empty ruleset. ++ */ ++ RuleSet(Interface * const interface_ptr); ++ RuleSet(const RuleSet& rhs); ++ const RuleSet& operator=(const RuleSet& rhs); ++ ~RuleSet(); ++ ++ /** ++ * Load a ruleset from a file at `path'. ++ * Internally, this opens an input file stream and calls load(std::istream& stream). ++ */ ++ void load(const std::string& path); ++ ++ /** ++ * Load a ruleset from an input stream. ++ * The stream is read using std::getline() and each line is parsed as a separate rule. ++ * Empty lines are skipped. ++ */ ++ void load(std::istream& stream); ++ ++ /** ++ * Save the ruleset to a file at `path'. ++ * If a file exists at `path', it will be overwritten. Internally, this opens an output ++ * stream and calls save(std::ostream& stream). ++ */ ++ void save(const std::string& path) const; ++ ++ /** ++ * Write the ruleset to an output stream. ++ * Each rule is serialized to it's string representation and written line by line to ++ * the output stream. ++ */ ++ void save(std::ostream& stream) const; ++ ++ /** ++ * Set an implicit default target which will be used if there's no match for a device ++ * rule. ++ */ ++ void setDefaultTarget(Rule::Target target); ++ ++ /** ++ * Get the implicit target value. ++ */ ++ Rule::Target getDefaultTarget() const; ++ ++ /** ++ * Set an implicit default action which will be used if there's no match for a device ++ * rule. ++ */ ++ void setDefaultAction(const std::string& action); ++ ++ /** ++ * Assign a sequence number to a rule and append it to the rule set. ++ * If `parent_id' is not specified, the rule will be appended at the end od the ruleset. ++ * The method returns the sequence number assigned to the rule. ++ */ ++ uint32_t appendRule(const Rule& rule, uint32_t parent_id = Rule::LastID); ++ ++ /** ++ * Search for a rule that matches `match_rule' rule and update it with a rule specified ++ * by `new_rule'. Fail if multiple rules match. If there are no matching rules, append ++ * the `new_rule' rule to the rule set. ++ * ++ * Returns the id of the updated or new rule. ++ */ ++ uint32_t upsertRule(const Rule& match_rule, const Rule& new_rule, bool parent_insensitive = false); ++ ++ /** ++ * Get a rule pointer to a rule with the specified sequence number. ++ * Returns nullptr if no such rule exists. ++ */ ++ std::shared_ptr getRule(uint32_t id); ++ ++ /** ++ * Remove a rule from the ruleset. ++ * The method returns true if a rule was removed and false otherwise. ++ */ ++ bool removeRule(uint32_t id); ++ ++ /** ++ * Find first rule in the ruleset which matched the specified device rule. ++ * If `from_id' isn't specified, the method searches from the beginning of the ruleset. ++ * If no matching rule is found, nullptr is returned. ++ */ ++ std::shared_ptr getFirstMatchingRule(std::shared_ptr device_rule, uint32_t from_id = 1) const; ++ ++ /** ++ * Get all rules from the set. ++ */ ++ std::vector> getRules(); ++ ++ /** ++ * Get the oldest rule that timed out and should be removed from the ruleset. ++ * Returns nullptr if there are not timed out rules. ++ */ ++ std::shared_ptr getTimedOutRule(); ++ ++ /** ++ * Assign a unique sequence number to a rule. ++ * Return the assigned sequence number. ++ */ ++ uint32_t assignID(std::shared_ptr rule); ++ ++ /** ++ * Generate a unique sequence number. ++ */ ++ uint32_t assignID(); ++ ++ private: ++ RuleSetPrivate* d_pointer; ++ }; ++} +diff --git a/src/Library/public/usbguard/Typedefs.cpp b/src/Library/public/usbguard/Typedefs.cpp +new file mode 100644 +index 0000000..f15585f +--- /dev/null ++++ b/src/Library/public/usbguard/Typedefs.cpp +@@ -0,0 +1,32 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "Typedefs.hpp" ++ ++namespace usbguard ++{ ++ template<> ++ bool matches(const std::string& a, const std::string& b) ++ { ++ return a == b; ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/Typedefs.hpp b/src/Library/public/usbguard/Typedefs.hpp +new file mode 100644 +index 0000000..452860e +--- /dev/null ++++ b/src/Library/public/usbguard/Typedefs.hpp +@@ -0,0 +1,67 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include ++#include ++ ++namespace usbguard { ++ template ++ bool matches(const T& a, const T& b) ++ { ++ return a == b; ++ } ++ ++ template<> ++ bool matches(const std::string& a, const std::string& b); ++ ++ /* ++ * Atomic ++ */ ++ template ++ using Atomic = std::atomic; ++ ++ /* ++ * Symbol visibility ++ */ ++ #if defined _WIN32 || defined __CYGWIN__ ++ #ifdef BUILDING_DLL ++ #ifdef __GNUC__ ++ #define DLL_PUBLIC __attribute__ ((dllexport)) ++ #else ++ #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. ++ #endif ++ #else ++ #ifdef __GNUC__ ++ #define DLL_PUBLIC __attribute__ ((dllimport)) ++ #else ++ #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. ++ #endif ++ #endif ++ #define DLL_LOCAL ++ #else ++ #if __GNUC__ >= 4 ++ #define DLL_PUBLIC __attribute__ ((visibility ("default"))) ++ #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) ++ #else ++ #define DLL_PUBLIC ++ #define DLL_LOCAL ++ #endif ++ #endif ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/USB.cpp b/src/Library/public/usbguard/USB.cpp +new file mode 100644 +index 0000000..5e81a68 +--- /dev/null ++++ b/src/Library/public/usbguard/USB.cpp +@@ -0,0 +1,523 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "USB.hpp" ++#include "Common/ByteOrder.hpp" ++#include "Common/Utility.hpp" ++#include "Logger.hpp" ++#include ++#include ++#include ++ ++namespace usbguard { ++ USBDeviceID::USBDeviceID() ++ { ++ } ++ ++ USBDeviceID::USBDeviceID(const std::string& vendor_id, const std::string& product_id) ++ { ++ checkDeviceID(vendor_id, product_id); ++ setVendorID(vendor_id); ++ setProductID(product_id); ++ } ++ ++ USBDeviceID::USBDeviceID(const USBDeviceID& rhs) ++ { ++ _vendor_id = rhs._vendor_id; ++ _product_id = rhs._product_id; ++ } ++ ++ void USBDeviceID::checkDeviceID(const std::string& vendor_id, const std::string& product_id) ++ { ++ if (vendor_id.empty() || vendor_id == "*") { ++ /* product id must be empty or "*" */ ++ if (!product_id.empty() && product_id != "*") { ++ throw std::runtime_error("Invalid USB device id format"); ++ } ++ } ++ if (vendor_id.size() > USB_VID_STRING_MAX_LENGTH) { ++ throw std::runtime_error("Vendor ID string size out of range"); ++ } ++ if (product_id.size() > USB_PID_STRING_MAX_LENGTH) { ++ throw std::runtime_error("Product ID string size out of range"); ++ } ++ } ++ ++ void USBDeviceID::setVendorID(const std::string& vendor_id) ++ { ++ checkDeviceID(vendor_id, _product_id); ++ _vendor_id = vendor_id; ++ } ++ ++ void USBDeviceID::setProductID(const std::string& product_id) ++ { ++ checkDeviceID(_vendor_id, product_id); ++ _product_id = product_id; ++ } ++ ++ const std::string& USBDeviceID::getVendorID() const ++ { ++ return _vendor_id; ++ } ++ ++ const std::string& USBDeviceID::getProductID() const ++ { ++ return _product_id; ++ } ++ ++ std::string USBDeviceID::toRuleString() const ++ { ++ return _vendor_id + ":" + _product_id; ++ } ++ ++ std::string USBDeviceID::toString() const ++ { ++ return toRuleString(); ++ } ++ ++ bool USBDeviceID::isSubsetOf(const USBDeviceID& rhs) const ++ { ++ if (_vendor_id.empty() || _vendor_id == "*") { ++ return true; ++ } ++ else if (_vendor_id != rhs._vendor_id) { ++ return false; ++ } ++ ++ if (_product_id.empty() || _product_id == "*") { ++ return true; ++ } ++ else if (_product_id != rhs._product_id) { ++ return false; ++ } ++ ++ return true; ++ } ++ ++ template<> ++ bool Predicates::isSubsetOf(const USBDeviceID& source, const USBDeviceID& target) ++ { ++ USBGUARD_LOG(Trace) << "source=" << source.toString() << " target=" << target.toString(); ++ const bool result = source.isSubsetOf(target); ++ USBGUARD_LOG(Trace) << "result=" << result; ++ return result; ++ } ++ ++ USBInterfaceType::USBInterfaceType() ++ { ++ _bClass = 0; ++ _bSubClass = 0; ++ _bProtocol = 0; ++ _mask = 0; ++ } ++ ++ USBInterfaceType::USBInterfaceType(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask) ++ { ++ _bClass = bClass; ++ _bSubClass = bSubClass; ++ _bProtocol = bProtocol; ++ _mask = mask; ++ } ++ ++ USBInterfaceType::USBInterfaceType(const USBInterfaceDescriptor& descriptor, uint8_t mask) ++ { ++ _bClass = descriptor.bInterfaceClass; ++ _bSubClass = descriptor.bInterfaceSubClass; ++ _bProtocol = descriptor.bInterfaceProtocol; ++ _mask = mask; ++ } ++ ++ USBInterfaceType::USBInterfaceType(const std::string& type_string) ++ { ++ std::vector tokens; ++ tokenizeString(type_string, tokens, ":", /*trim_empty=*/false); ++ ++ _bClass = 0; ++ _bSubClass = 0; ++ _bProtocol = 0; ++ _mask = 0; ++ ++ if (tokens.size() != 3) { ++ throw std::runtime_error("Invalid type_string"); ++ } ++ ++ if (tokens[0].size() != 2) { ++ throw std::runtime_error("Invalid type_string"); ++ } ++ else { ++ _bClass = stringToNumber(tokens[0], 16); ++ _mask |= MatchClass; ++ } ++ ++ if (tokens[1] != "*") { ++ if (tokens[1].size() != 2) { ++ throw std::runtime_error("Invalid type_string"); ++ } ++ else { ++ _bSubClass = stringToNumber(tokens[1], 16); ++ _mask |= MatchSubClass; ++ } ++ } ++ ++ if (tokens[2] != "*") { ++ if (tokens[2].size() != 2) { ++ throw std::runtime_error("Invalid type_string"); ++ } ++ else { ++ _bProtocol = stringToNumber(tokens[2], 16); ++ _mask |= MatchProtocol; ++ } ++ } ++ ++ if (!(_mask == (MatchAll) || ++ _mask == (MatchClass|MatchSubClass) || ++ _mask == (MatchClass))) { ++ throw std::runtime_error("Invalid type_string"); ++ } ++ } ++ ++ bool USBInterfaceType::operator==(const USBInterfaceType& rhs) const ++ { ++ return (_bClass == rhs._bClass && ++ _bSubClass == rhs._bSubClass && ++ _bProtocol == rhs._bProtocol && ++ _mask == rhs._mask); ++ } ++ ++ bool USBInterfaceType::appliesTo(const USBInterfaceType& rhs) const ++ { ++ if (_mask & MatchClass) { ++ if (_bClass != rhs._bClass) { ++ return false; ++ } ++ } ++ if (_mask & MatchSubClass) { ++ if (_bSubClass != rhs._bSubClass) { ++ return false; ++ } ++ } ++ if (_mask & MatchProtocol) { ++ if (_bProtocol != rhs._bProtocol) { ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ template<> ++ bool Predicates::isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target) ++ { ++ return source.appliesTo(target); ++ } ++ ++ const std::string USBInterfaceType::typeString() const ++ { ++ return USBInterfaceType::typeString(_bClass, _bSubClass, _bProtocol, _mask); ++ } ++ ++ const std::string USBInterfaceType::toRuleString() const ++ { ++ return typeString(); ++ } ++ ++ const std::string USBInterfaceType::typeString(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask) ++ { ++ std::string type_string(""); ++ ++ if (mask & MatchClass) { ++ type_string.append(numberToString(bClass, "", 16, 2, '0') + ":"); ++ ++ if (mask & MatchSubClass) { ++ type_string.append(numberToString(bSubClass, "", 16, 2, '0') + ":"); ++ ++ if (mask & MatchProtocol) { ++ type_string.append(numberToString(bProtocol, "", 16, 2, '0')); ++ } ++ else { ++ type_string.append("*"); ++ } ++ } ++ else { ++ type_string.append("*:*"); ++ } ++ } ++ else { ++ throw std::runtime_error("BUG: cannot create type string, invalid mask"); ++ } ++ ++ return type_string; ++ } ++ ++ void USBParseDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ const USBDeviceDescriptor* device_raw = reinterpret_cast(descriptor_raw); ++ USBDeviceDescriptor* device_out = reinterpret_cast(descriptor_out); ++ ++ /* Copy 1:1 */ ++ *device_out = *device_raw; ++ ++ /* Convert multibyte field to host endianness */ ++ device_out->bcdUSB = busEndianToHost(device_raw->bcdUSB); ++ device_out->idVendor = busEndianToHost(device_raw->idVendor); ++ device_out->idProduct = busEndianToHost(device_raw->idProduct); ++ device_out->bcdDevice = busEndianToHost(device_raw->bcdDevice); ++ } ++ ++ void USBParseConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ const USBConfigurationDescriptor* configuration_raw = reinterpret_cast(descriptor_raw); ++ USBConfigurationDescriptor* configuration_out = reinterpret_cast(descriptor_out); ++ ++ /* Copy 1:1 */ ++ *configuration_out = *configuration_raw; ++ ++ /* Convert multibyte field to host endianness */ ++ configuration_out->wTotalLength = busEndianToHost(configuration_raw->wTotalLength); ++ } ++ ++ void USBParseInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ const USBInterfaceDescriptor* interface_raw = reinterpret_cast(descriptor_raw); ++ USBInterfaceDescriptor* interface_out = reinterpret_cast(descriptor_out); ++ ++ /* Copy 1:1 */ ++ *interface_out = *interface_raw; ++ } ++ ++ void USBParseEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ const USBEndpointDescriptor* endpoint_raw = reinterpret_cast(descriptor_raw); ++ USBEndpointDescriptor* endpoint_out = reinterpret_cast(descriptor_out); ++ ++ *endpoint_out = *endpoint_raw; ++ endpoint_out->wMaxPacketSize = busEndianToHost(endpoint_raw->wMaxPacketSize); ++ } ++ ++ void USBParseAudioEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ const USBAudioEndpointDescriptor* endpoint_raw = reinterpret_cast(descriptor_raw); ++ USBAudioEndpointDescriptor* endpoint_out = reinterpret_cast(descriptor_out); ++ ++ *endpoint_out = *endpoint_raw; ++ endpoint_out->wMaxPacketSize = busEndianToHost(endpoint_raw->wMaxPacketSize); ++ } ++ ++ void USBParseUnknownDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ (void)parser; ++ *descriptor_out = *descriptor_raw; ++ } ++ ++ void USBDescriptorParserHooks::parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out) ++ { ++ USBGUARD_LOG(Trace); ++ ++ const auto type = static_cast(descriptor_raw->bHeader.bDescriptorType); ++ const auto size = descriptor_raw->bHeader.bLength; ++ ++ switch(type) { ++ case USBDescriptorType::Device: ++ switch (size) { ++ case sizeof(USBDeviceDescriptor): ++ USBParseDeviceDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ default: ++ throw Exception("USB descriptor parser", "device descriptor", "unexpected descriptor size"); ++ } ++ break; ++ case USBDescriptorType::Configuration: ++ switch (size) { ++ case sizeof(USBConfigurationDescriptor): ++ USBParseConfigurationDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ default: ++ throw Exception("USB descriptor parser", "configuration descriptor", "unexpected descriptor size"); ++ } ++ break; ++ case USBDescriptorType::Interface: ++ switch (size) { ++ case sizeof(USBInterfaceDescriptor): ++ USBParseInterfaceDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ default: ++ throw Exception("USB descriptor parser", "interface descriptor", "unexpected descriptor size"); ++ } ++ break; ++ case USBDescriptorType::Endpoint: ++ switch (size) { ++ case sizeof(USBEndpointDescriptor): ++ USBParseEndpointDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ case sizeof(USBAudioEndpointDescriptor): ++ USBParseAudioEndpointDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ default: ++ throw Exception("USB descriptor parser", "endpoint descriptor", "unexpected descriptor size"); ++ } ++ break; ++ case USBDescriptorType::String: ++ case USBDescriptorType::AssociationInterface: ++ case USBDescriptorType::Unknown: ++ default: ++ USBParseUnknownDescriptor(parser, descriptor_raw, descriptor_out); ++ return; ++ } ++ /* UNREACHABLE */ ++ } ++ ++ void USBDescriptorParserHooks::loadUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor) ++ { ++ (void)parser; ++ (void)descriptor; ++ USBGUARD_LOG(Trace); ++ } ++ ++ USBDescriptorParser::USBDescriptorParser(USBDescriptorParserHooks& hooks) ++ : _hooks(hooks) ++ { ++ } ++ ++ size_t USBDescriptorParser::parse(std::istream& stream) ++ { ++ size_t size_processed = 0; ++ ++ while (stream.good()) { ++ USBDescriptorHeader header; ++ stream.read(reinterpret_cast(&header), sizeof header); ++ ++ if (stream.gcount() != sizeof header) { ++ /* ++ * If we read nothing and the stream if at EOF, just break ++ * the loop and return normally. Checking the sanity of the ++ * parsed descriptor data is up to the higher layers. ++ */ ++ if (stream.gcount() == 0 && stream.eof()) { ++ break; ++ } ++ /* ++ * Otherwise throw an exception because there's unknown garbage ++ * in the stream which cannot be a valid USB descriptor. ++ */ ++ else { ++ throw std::runtime_error("Cannot parse descriptor data: partial read while reading header data"); ++ } ++ } ++ ++ /* ++ * The bLength value has to be at least 2, because that is the size of the USB ++ * descriptor header. ++ */ ++ if (header.bLength < sizeof(USBDescriptorHeader)) { ++ throw std::runtime_error("Invalid descriptor data: bLength is less than the size of the header"); ++ } ++ ++ /* ++ * Let's try to read the rest of the descriptor data before we start looking ++ * for the descriptor type handler. If there's not enough data in the stream, ++ * then there's no point for searching for the handler. ++ */ ++ USBDescriptor descriptor; ++ ++ descriptor.bHeader = header; ++ memset(&descriptor.bDescriptorData, 0, sizeof descriptor.bDescriptorData); ++ ++ /* ++ * We read (bLength - header_size) amount of data here because the bLength value ++ * counts in the size of the header too and we already read it from the stream. ++ */ ++ stream.read(reinterpret_cast(&descriptor.bDescriptorData), header.bLength - sizeof(USBDescriptorHeader)); ++ ++ if (stream.gcount() != (std::streamsize)(header.bLength - sizeof(USBDescriptorHeader))) { ++ throw std::runtime_error("Invalid descriptor data: bLength value larger than the amount of available data"); ++ } ++ ++ USBDescriptor descriptor_parsed; ++ descriptor_parsed.bHeader = header; ++ memset(&descriptor_parsed.bDescriptorData, 0, sizeof descriptor_parsed.bDescriptorData); ++ ++ _hooks.parseUSBDescriptor(this, &descriptor, &descriptor_parsed); ++ _hooks.loadUSBDescriptor(this, &descriptor_parsed); ++ ++ setDescriptor(header.bDescriptorType, descriptor_parsed); ++ size_processed += header.bLength; ++ } ++ ++ return size_processed; ++ } ++ ++ const std::vector* USBDescriptorParser::getDescriptor(uint8_t bDescriptorType) const ++ { ++ auto const& it = _dstate_map.find(bDescriptorType); ++ if (it == _dstate_map.end()) { ++ return nullptr; ++ } ++ return &it->second; ++ } ++ ++ void USBDescriptorParser::setDescriptor(uint8_t bDescriptorType, const USBDescriptor& descriptor) ++ { ++ auto& descriptors = _dstate_map[bDescriptorType]; ++ bool set = false; ++ for (auto& stored_descriptor : descriptors) { ++ if (stored_descriptor.bHeader.bLength == descriptor.bHeader.bLength) { ++ stored_descriptor = descriptor; ++ set = true; ++ } ++ } ++ if (!set) { ++ descriptors.push_back(descriptor); ++ } ++ /* ++ * Count in the descriptor no matter if we overwrote one or not. ++ * We are counting all occurences of a descriptor type. ++ */ ++ ++_count_map[bDescriptorType]; ++ } ++ ++ void USBDescriptorParser::delDescriptor(uint8_t bDescriptorType) ++ { ++ _dstate_map.erase(bDescriptorType); ++ } ++ ++ bool USBDescriptorParser::haveDescriptor(uint8_t bDescriptorType) const ++ { ++ return _dstate_map.count(bDescriptorType) > 0; ++ } ++ ++ const std::vector> USBDescriptorParser::getDescriptorCounts() const ++ { ++ std::vector> counts; ++ ++ for (auto const& kv : _count_map) { ++ counts.push_back(std::make_pair(kv.first, kv.second)); ++ } ++ ++ std::sort(counts.begin(), counts.end()); ++ ++ return counts; ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/USB.hpp b/src/Library/public/usbguard/USB.hpp +new file mode 100644 +index 0000000..58be335 +--- /dev/null ++++ b/src/Library/public/usbguard/USB.hpp +@@ -0,0 +1,276 @@ ++// ++// Copyright (C) 2015 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Predicates.hpp" ++#include "Typedefs.hpp" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++namespace usbguard { ++ /* ++ * Maximum lenght of a string that is read from a USB descriptor ++ * Since the string descriptors have an 8-bit length field, the ++ * maximum lenght of a string stored in a string descriptor is ++ * UINT8_MAX minus the size of the length field (1 byte) and the ++ * size of the type field (1 byte). ++ */ ++ const size_t USB_GENERIC_STRING_MAX_LENGTH = UINT8_MAX - 2; ++ ++ /* Maximum lenght of the vendor id in string form */ ++ const size_t USB_VID_STRING_MAX_LENGTH = 4; ++ ++ /* Maximum lenght of the product id in string form */ ++ const size_t USB_PID_STRING_MAX_LENGTH = 4; ++ ++ /* Maximum lenght of the port in string form */ ++ const size_t USB_PORT_STRING_MAX_LENGTH = PATH_MAX; ++ ++ /* ++ * NOTE: The USB specification dictates that all multibyte data fields ++ * are in little-endian form. The structures defined bellow are ++ * used for platform-independed passing of the USB descriptor ++ * data to the Device class. The Device class assumes that the ++ * values are in host-specific endianness. ++ */ ++ const uint8_t USB_DESCRIPTOR_TYPE_UNKNOWN = 0x00; ++ const uint8_t USB_DESCRIPTOR_TYPE_DEVICE = 0x01; ++ const uint8_t USB_DESCRIPTOR_TYPE_CONFIGURATION = 0x02; ++ const uint8_t USB_DESCRIPTOR_TYPE_STRING = 0x03; ++ const uint8_t USB_DESCRIPTOR_TYPE_INTERFACE = 0x04; ++ const uint8_t USB_DESCRIPTOR_TYPE_ENDPOINT = 0x05; ++ const uint8_t USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE = 0x0b; ++ ++ enum class USBDescriptorType : uint8_t { ++ Unknown = USB_DESCRIPTOR_TYPE_UNKNOWN, ++ Device = USB_DESCRIPTOR_TYPE_DEVICE, ++ Configuration = USB_DESCRIPTOR_TYPE_CONFIGURATION, ++ String = USB_DESCRIPTOR_TYPE_STRING, ++ Interface = USB_DESCRIPTOR_TYPE_INTERFACE, ++ Endpoint = USB_DESCRIPTOR_TYPE_ENDPOINT, ++ AssociationInterface = USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE ++ }; ++ ++ struct DLL_PUBLIC USBDescriptorHeader ++ { ++ uint8_t bLength; ++ uint8_t bDescriptorType; ++ } __attribute__((packed)); ++ ++ struct DLL_PUBLIC USBDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint8_t bDescriptorData[256-sizeof(USBDescriptorHeader)]; ++ } __attribute__((packed)); ++ ++ struct DLL_PUBLIC USBDeviceDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint16_t bcdUSB; ++ uint8_t bDeviceClass; ++ uint8_t bDeviceSubClass; ++ uint8_t bDeviceProtocol; ++ uint8_t bMaxPacketSize; ++ uint16_t idVendor; ++ uint16_t idProduct; ++ uint16_t bcdDevice; ++ uint8_t iManufacturer; ++ uint8_t iProduct; ++ uint8_t iSerialNumber; ++ uint8_t bNumConfigurations; ++ } __attribute__((packed)); ++ ++ struct DLL_PUBLIC USBConfigurationDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint16_t wTotalLength; ++ uint8_t bNumInterfaces; ++ uint8_t bConfigurationValue; ++ uint8_t iConfiguration; ++ uint8_t bmAttributes; ++ uint8_t bMaxPower; ++ } __attribute__((packed)); ++ ++ struct DLL_PUBLIC USBInterfaceDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint8_t bInterfaceNumber; ++ uint8_t bAlternateSetting; ++ uint8_t bNumEndpoints; ++ uint8_t bInterfaceClass; ++ uint8_t bInterfaceSubClass; ++ uint8_t bInterfaceProtocol; ++ uint8_t iInterface; ++ } __attribute__((packed)); ++ ++ struct USBEndpointDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint8_t bEndpointAddress; ++ uint8_t bmAttributes; ++ uint16_t wMaxPacketSize; ++ uint8_t bInterval; ++ } __attribute__((packed)); ++ ++ struct USBAudioEndpointDescriptor ++ { ++ struct USBDescriptorHeader bHeader; ++ uint8_t bEndpointAddress; ++ uint8_t bmAttributes; ++ uint16_t wMaxPacketSize; ++ uint8_t bInterval; ++ uint8_t bRefresh; ++ uint8_t bSynchAddress; ++ } __attribute__((packed)); ++ ++ class DLL_PUBLIC USBDeviceID ++ { ++ public: ++ USBDeviceID(); ++ USBDeviceID(const std::string& vendor_id, const std::string& product_id = std::string()); ++ USBDeviceID(const USBDeviceID& rhs); ++ ++ static void checkDeviceID(const std::string& vendor_id, const std::string& product_id); ++ ++ void setVendorID(const std::string& vendor_id); ++ void setProductID(const std::string& product_id); ++ ++ const std::string& getVendorID() const; ++ const std::string& getProductID() const; ++ ++ std::string toRuleString() const; ++ std::string toString() const; ++ bool isSubsetOf(const USBDeviceID& rhs) const; ++ ++ private: ++ std::string _vendor_id; ++ std::string _product_id; ++ }; ++ ++ namespace Predicates DLL_PUBLIC ++ { ++ template<> ++ bool isSubsetOf(const USBDeviceID& source, const USBDeviceID& target); ++ } ++ ++ class DLL_PUBLIC USBInterfaceType ++ { ++ public: ++ static const uint8_t MatchClass = 1<<0; ++ static const uint8_t MatchSubClass = 1<<1; ++ static const uint8_t MatchProtocol = 1<<2; ++ static const uint8_t MatchAll = MatchClass|MatchSubClass|MatchProtocol; ++ ++ USBInterfaceType(); ++ USBInterfaceType(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll); ++ USBInterfaceType(const USBInterfaceDescriptor& descriptor, uint8_t mask = MatchAll); ++ USBInterfaceType(const std::string& type_string); ++ ++ bool operator==(const USBInterfaceType& rhs) const; ++ bool appliesTo(const USBInterfaceType& rhs) const; ++ ++ const std::string typeString() const; ++ const std::string toRuleString() const; ++ static const std::string typeString(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll); ++ ++ private: ++ uint8_t _bClass; ++ uint8_t _bSubClass; ++ uint8_t _bProtocol; ++ uint8_t _mask; ++ }; ++ ++ namespace Predicates DLL_PUBLIC ++ { ++ template<> ++ bool isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target); ++ } ++ ++ class USBDescriptorParser; ++ ++ class DLL_PUBLIC USBDescriptorParserHooks ++ { ++ public: ++ virtual void parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_in, USBDescriptor* descriptor_out); ++ virtual void loadUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor); ++ }; ++ ++ class DLL_PUBLIC USBDescriptorParser ++ { ++ public: ++ USBDescriptorParser(USBDescriptorParserHooks& hooks); ++ ++ /** ++ * Initiate parsing of USB descriptors from an input stream. ++ * ++ * Returns number of bytes succesfully parsed/processed from ++ * the stream. ++ */ ++ size_t parse(std::istream& stream); ++ ++ /** ++ * Return a pointer to a USBDescriptor of type bDescriptorType that ++ * is stored in the USB descriptor state. If there's no such descriptor, ++ * then nullptr is returned. ++ */ ++ const std::vector* getDescriptor(uint8_t bDescriptorType) const; ++ ++ /** ++ * Set the active instance of an USB descriptor of bDescriptorType type. ++ */ ++ void setDescriptor(uint8_t bDescriptorType, const USBDescriptor& descriptor); ++ ++ /** ++ * Delete the active instance of an USB descriptor of bDescriptorType type. ++ */ ++ void delDescriptor(uint8_t bDescriptorType); ++ ++ /** ++ * Returns true if the descriptor state contains a USB descriptor of type bDescriptorType. ++ */ ++ bool haveDescriptor(uint8_t bDescriptorType) const; ++ ++ /** ++ * Returns a vector of (bDescriptorType, count) pairs. ++ */ ++ const std::vector> getDescriptorCounts() const; ++ ++ private: ++ USBDescriptorParserHooks& _hooks; ++ ++ std::unordered_map> _dstate_map; /**< Descriptor State Map */ ++ std::unordered_map _count_map; ++ }; ++ ++ void DLL_PUBLIC USBParseDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ void DLL_PUBLIC USBParseConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ void DLL_PUBLIC USBParseInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ void DLL_PUBLIC USBParseEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ void DLL_PUBLIC USBParseAudioEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ void DLL_PUBLIC USBParseUnknownDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw, USBDescriptor* descriptor_out); ++ ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/USBGuard.cpp b/src/Library/public/usbguard/USBGuard.cpp +new file mode 100644 +index 0000000..212db63 +--- /dev/null ++++ b/src/Library/public/usbguard/USBGuard.cpp +@@ -0,0 +1,77 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#ifdef HAVE_BUILD_CONFIG_H ++#include ++#endif ++ ++#include "USBGuard.hpp" ++#include "ConfigFile.hpp" ++#include "Exception.hpp" ++#include "Logger.hpp" ++ ++#include ++#include ++ ++#ifndef USBGUARD_DAEMON_CONF_PATH ++# warning "Using hard-coded USBGUARD_DAEMON_CONF_PATH value" ++# define USBGUARD_DAEMON_CONF_PATH "/etc/usbguard/usbguard-daemon.conf" ++#endif ++ ++namespace usbguard ++{ ++ std::string getDaemonConfigPath() ++ { ++ USBGUARD_LOG(Trace); ++ const char * const envval = getenv("USBGUARD_DAEMON_CONF"); ++ ++ if (envval != nullptr) { ++ USBGUARD_LOG(Debug) << "Returning environment variable path: " << envval; ++ return std::string(envval); ++ } ++ else { ++ USBGUARD_LOG(Debug) << "Returning build-time path: " << USBGUARD_DAEMON_CONF_PATH; ++ return std::string(USBGUARD_DAEMON_CONF_PATH); ++ } ++ } ++ ++ std::string getIPCAccessControlFilesPath() ++ { ++ USBGUARD_LOG(Trace); ++ const std::string daemon_conf_path = getDaemonConfigPath(); ++ ConfigFile daemon_conf; ++ daemon_conf.open(daemon_conf_path); ++ ++ if (daemon_conf.hasSettingValue("IPCAccessControlFiles")) { ++ return daemon_conf.getSettingValue("IPCAccessControlFiles"); ++ } ++ ++ throw Exception("getIPCAccessControlFilesPath", daemon_conf_path, "IPCAccessControlFiles not set"); ++ } ++ ++ std::string getIPCAccessControlFileBasename(const std::string& name, bool is_group) ++ { ++ USBGUARD_LOG(Trace) << "name=" << name << " is_group=" << is_group; ++ std::string basename; ++ if (is_group) { ++ basename.append(":"); ++ } ++ basename.append(name); ++ return basename; ++ } ++} /* namespace usbguard */ +diff --git a/src/Library/public/usbguard/USBGuard.hpp b/src/Library/public/usbguard/USBGuard.hpp +new file mode 100644 +index 0000000..fff4082 +--- /dev/null ++++ b/src/Library/public/usbguard/USBGuard.hpp +@@ -0,0 +1,30 @@ ++// ++// Copyright (C) 2017 Red Hat, Inc. ++// ++// 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 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 General Public License ++// along with this program. If not, see . ++// ++// Authors: Daniel Kopecek ++// ++#pragma once ++ ++#include "Typedefs.hpp" ++ ++#include ++ ++namespace usbguard ++{ ++ DLL_PUBLIC std::string getDaemonConfigPath(); ++ DLL_PUBLIC std::string getIPCAccessControlFilesPath(); ++ DLL_PUBLIC std::string getIPCAccessControlFileBasename(const std::string& name, bool is_group); ++} /* namespace usbguard */ +diff --git a/src/Tests/Makefile.am b/src/Tests/Makefile.am +index 06ecd08..7d93474 100644 +--- a/src/Tests/Makefile.am ++++ b/src/Tests/Makefile.am +@@ -17,8 +17,9 @@ + ## Authors: Daniel Kopecek + ## + AM_CPPFLAGS=\ +- -I$(top_srcdir)/src\ +- -I$(top_srcdir)/src/Library\ ++ -I$(top_srcdir)/src \ ++ -I$(top_srcdir)/src/Library \ ++ -I$(top_srcdir)/src/Library/public \ + @catch_CFLAGS@ + + EXTRA_DIST=\ +diff --git a/src/Tests/Regression/test_Rule_ghi113.cpp b/src/Tests/Regression/test_Rule_ghi113.cpp +index 9e5e36a..52e590b 100644 +--- a/src/Tests/Regression/test_Rule_ghi113.cpp ++++ b/src/Tests/Regression/test_Rule_ghi113.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + using namespace usbguard; + +diff --git a/src/Tests/Regression/test_Rule_ghi37.cpp b/src/Tests/Regression/test_Rule_ghi37.cpp +index 89fa492..5c45050 100644 +--- a/src/Tests/Regression/test_Rule_ghi37.cpp ++++ b/src/Tests/Regression/test_Rule_ghi37.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + using namespace usbguard; + +diff --git a/src/Tests/Unit/test_IPCServer_AccessControl.cpp b/src/Tests/Unit/test_IPCServer_AccessControl.cpp +index ea708db..4ddd48a 100644 +--- a/src/Tests/Unit/test_IPCServer_AccessControl.cpp ++++ b/src/Tests/Unit/test_IPCServer_AccessControl.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/IPCServer.hpp" ++ + #include +-#include + #include + + using namespace usbguard; +diff --git a/src/Tests/Unit/test_Rule.cpp b/src/Tests/Unit/test_Rule.cpp +index 71f7fb0..22c7855 100644 +--- a/src/Tests/Unit/test_Rule.cpp ++++ b/src/Tests/Unit/test_Rule.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + using namespace usbguard; + +@@ -43,7 +44,6 @@ TEST_CASE("Default constructed rule", "[Rule]") { + REQUIRE(rule.attributeHash().empty()); + REQUIRE(rule.attributeViaPort().empty()); + REQUIRE(rule.attributeWithInterface().empty()); +- REQUIRE(rule.getTimeoutSeconds() == 0); + } + + SECTION("is not valid") { +diff --git a/src/Tests/Unit/test_RuleAttribute_id.cpp b/src/Tests/Unit/test_RuleAttribute_id.cpp +index 9e76cdd..8216f96 100644 +--- a/src/Tests/Unit/test_RuleAttribute_id.cpp ++++ b/src/Tests/Unit/test_RuleAttribute_id.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + using namespace usbguard; + +diff --git a/src/Tests/Unit/test_RuleParser.cpp b/src/Tests/Unit/test_RuleParser.cpp +index 106997c..e4d3410 100644 +--- a/src/Tests/Unit/test_RuleParser.cpp ++++ b/src/Tests/Unit/test_RuleParser.cpp +@@ -16,8 +16,9 @@ + // + // Authors: Daniel Kopecek + // ++#include "usbguard/Rule.hpp" ++ + #include +-#include + + using namespace usbguard; + +@@ -72,7 +73,7 @@ TEST_CASE("Non-printable characters in a rule string", "[RuleParser]") { + } + + SECTION("to/from string: allow via-port \"\"") { +- const std::vector one_non_printable_string = { non_printable_string }; ++ const std::vector one_non_printable_string = { non_printable_string }; + rule.setTarget(Rule::Target::Allow); + rule.attributeViaPort().set(one_non_printable_string, Rule::SetOperator::Equals); + +@@ -87,7 +88,7 @@ TEST_CASE("Non-printable characters in a rule string", "[RuleParser]") { + } + + SECTION("to/from string: allow via-port { \"\" \"\" }") { +- const std::vector two_non_printable_strings = \ ++ const std::vector two_non_printable_strings = \ + { non_printable_string, non_printable_string }; + rule.setTarget(Rule::Target::Allow); + rule.attributeViaPort().set(two_non_printable_strings, Rule::SetOperator::OneOf); +@@ -153,7 +154,7 @@ TEST_CASE("Double quote and backslash characters in a rule string", "[RuleParser + } + + SECTION("to/from string: allow via-port \"\"") { +- const std::vector one_dqb_string = { dqb_string }; ++ const std::vector one_dqb_string = { dqb_string }; + rule.setTarget(Rule::Target::Allow); + rule.attributeViaPort().set(one_dqb_string, Rule::SetOperator::Equals); + +@@ -168,7 +169,7 @@ TEST_CASE("Double quote and backslash characters in a rule string", "[RuleParser + } + + SECTION("to/from string: allow via-port { \"\" \"\" }") { +- const std::vector two_dqb_strings = { dqb_string, dqb_string }; ++ const std::vector two_dqb_strings = { dqb_string, dqb_string }; + rule.setTarget(Rule::Target::Allow); + rule.attributeViaPort().set(two_dqb_strings, Rule::SetOperator::OneOf); + +diff --git a/src/Tests/Unit/test_UEvent.cpp b/src/Tests/Unit/test_UEvent.cpp +index 59b5460..4d7e593 100644 +--- a/src/Tests/Unit/test_UEvent.cpp ++++ b/src/Tests/Unit/test_UEvent.cpp +@@ -26,7 +26,7 @@ TEST_CASE("Default constructed UEvent", "[UEvent]") { + + SECTION("empty") { + REQUIRE_NOTHROW(uevent.getAttribute("KEY1")); +- REQUIRE(uevent.getAttribute("KEY1") == String()); ++ REQUIRE(uevent.getAttribute("KEY1") == std::string()); + REQUIRE_FALSE(uevent.hasAttribute("KEY1")); + REQUIRE_FALSE(uevent.hasRequiredAttributes()); + REQUIRE_NOTHROW(uevent.clear()); +@@ -55,7 +55,7 @@ TEST_CASE("UEvent with required attributes", "[UEvent]") { + + SECTION("non-existing attribute") { + REQUIRE_NOTHROW(uevent.getAttribute("KEY1")); +- REQUIRE(uevent.getAttribute("KEY1") == String()); ++ REQUIRE(uevent.getAttribute("KEY1") == std::string()); + REQUIRE_FALSE(uevent.hasAttribute("KEY1")); + } + +diff --git a/src/Tests/Unit/test_UEventParser.cpp b/src/Tests/Unit/test_UEventParser.cpp +index 8bd4358..5bb2384 100644 +--- a/src/Tests/Unit/test_UEventParser.cpp ++++ b/src/Tests/Unit/test_UEventParser.cpp +@@ -58,7 +58,7 @@ TEST_CASE("UEvent parsing", "[UEventParser]") { + const size_t uevent_strlen = sizeof uevent_string; + UEvent uevent; + +- REQUIRE_NOTHROW(uevent = UEvent::fromString(String(uevent_string, uevent_strlen), ++ REQUIRE_NOTHROW(uevent = UEvent::fromString(std::string(uevent_string, uevent_strlen), + /*attributes_only=*/false, + /*trace=*/true)); + REQUIRE(uevent.hasRequiredAttributes()); +diff --git a/src/Tests/Unit/test_Utility.cpp b/src/Tests/Unit/test_Utility.cpp +index 640d712..c6fcc73 100644 +--- a/src/Tests/Unit/test_Utility.cpp ++++ b/src/Tests/Unit/test_Utility.cpp +@@ -30,14 +30,14 @@ TEST_CASE("parentPath", "[Utility]") { + REQUIRE(parentPath("/foo/bar") == "/foo"); + REQUIRE(parentPath("/foo/bar/") == "/foo"); + REQUIRE(parentPath("/foo/bar//") == "/foo"); +- REQUIRE(parentPath("/foo") == String()); +- REQUIRE(parentPath("/foo/") == String()); +- REQUIRE(parentPath("/") == String()); +- REQUIRE(parentPath("//") == String()); +- REQUIRE(parentPath("///") == String()); +- REQUIRE(parentPath("//foo") == String()); +- REQUIRE(parentPath("//foo//") == String()); +- REQUIRE(parentPath("") == String()); +- REQUIRE(parentPath(String()) == String()); ++ REQUIRE(parentPath("/foo") == std::string()); ++ REQUIRE(parentPath("/foo/") == std::string()); ++ REQUIRE(parentPath("/") == std::string()); ++ REQUIRE(parentPath("//") == std::string()); ++ REQUIRE(parentPath("///") == std::string()); ++ REQUIRE(parentPath("//foo") == std::string()); ++ REQUIRE(parentPath("//foo//") == std::string()); ++ REQUIRE(parentPath("") == std::string()); ++ REQUIRE(parentPath(std::string()) == std::string()); + } + diff --git a/SOURCES/usbguard-daemon.conf b/SOURCES/usbguard-daemon.conf new file mode 100644 index 00000000..a3a7e150 --- /dev/null +++ b/SOURCES/usbguard-daemon.conf @@ -0,0 +1,173 @@ +# +# Rule set file path. +# +# The USBGuard daemon will use this file to load the policy +# rule set from it and to write new rules received via the +# IPC interface. +# +# RuleFile=/path/to/rules.conf +# +RuleFile=/etc/usbguard/rules.conf + +# +# Implicit policy target. +# +# How to treat devices that don't match any rule in the +# policy. One of: +# +# * allow - authorize the device +# * block - block the device +# * reject - remove the device +# +ImplicitPolicyTarget=block + +# +# Present device policy. +# +# How to treat devices that are already connected when the +# daemon starts. One of: +# +# * allow - authorize every present device +# * block - deauthorize every present device +# * reject - remove every present device +# * keep - just sync the internal state and leave it +# * apply-policy - evaluate the ruleset for every present +# device +# +PresentDevicePolicy=apply-policy + +# +# Present controller policy. +# +# How to treat USB controllers that are already connected +# when the daemon starts. One of: +# +# * allow - authorize every present device +# * block - deauthorize every present device +# * reject - remove every present device +# * keep - just sync the internal state and leave it +# * apply-policy - evaluate the ruleset for every present +# device +# +PresentControllerPolicy=keep + +# +# Inserted device policy. +# +# How to treat USB devices that are already connected +# *after* the daemon starts. One of: +# +# * block - deauthorize every present device +# * reject - remove every present device +# * apply-policy - evaluate the ruleset for every present +# device +# +InsertedDevicePolicy=apply-policy + +# +# Restore controller device state. +# +# The USBGuard daemon modifies some attributes of controller +# devices like the default authorization state of new child device +# instances. Using this setting, you can controll whether the +# daemon will try to restore the attribute values to the state +# before modificaton on shutdown. +# +# SECURITY CONSIDERATIONS: If set to true, the USB authorization +# policy could be bypassed by performing some sort of attack on the +# daemon (via a local exploit or via a USB device) to make it shutdown +# and restore to the operating-system default state (known to be permissive). +# +RestoreControllerDeviceState=false + +# +# Device manager backend +# +# Which device manager backend implementation to use. One of: +# +# * uevent - Netlink based implementation which uses sysfs to scan for present +# devices and an uevent netlink socket for receiving USB device +# related events. +# * dummy - A dummy device manager which simulates several devices and device +# events. Useful for testing. +# +DeviceManagerBackend=uevent + +#!!! WARNING: It's good practice to set at least one of the !!! +#!!! two options bellow. If none of them are set, !!! +#!!! the daemon will accept IPC connections from !!! +#!!! anyone, thus allowing anyone to modify the !!! +#!!! rule set and (de)authorize USB devices. !!! + +# +# Users allowed to use the IPC interface. +# +# A space delimited list of usernames that the daemon will +# accept IPC connections from. +# +# IPCAllowedUsers=username1 username2 ... +# +IPCAllowedUsers=root + +# +# Groups allowed to use the IPC interface. +# +# A space delimited list of groupnames that the daemon will +# accept IPC connections from. +# +# IPCAllowedGroups=groupname1 groupname2 ... +# +IPCAllowedGroups= + +# +# IPC access control definition files path. +# +# The files at this location will be interpreted by the daemon +# as access control definition files. The (base)name of a file +# should be in the form: +# +# [user][:] +# +# and should contain lines in the form: +# +#
=[privilege] ... +# +# This way each file defines who is able to connect to the IPC +# bus and what privileges he has. +# +IPCAccessControlFiles=/etc/usbguard/IPCAccessControl.d/ + +# +# Generate device specific rules including the "via-port" +# attribute. +# +# This option modifies the behavior of the allowDevice +# action. When instructed to generate a permanent rule, +# the action can generate a port specific rule. Because +# some systems have unstable port numbering, the generated +# rule might not match the device after rebooting the system. +# +# If set to false, the generated rule will still contain +# the "parent-hash" attribute which also defines an association +# to the parent device. See usbguard-rules.conf(5) for more +# details. +# +DeviceRulesWithPort=false + +# +# USBGuard Audit events log backend +# +# One of: +# +# * FileAudit - Log audit events into a file specified by +# AuditFilePath setting (see below) +# * LinuxAudit - Log audit events using the Linux Audit +# subsystem (using audit_log_user_message) +# +AuditBackend=FileAudit + +# +# USBGuard audit events log file path. +# +AuditFilePath=/var/log/usbguard/usbguard-audit.log + diff --git a/SPECS/usbguard.spec b/SPECS/usbguard.spec new file mode 100644 index 00000000..505f7e4b --- /dev/null +++ b/SPECS/usbguard.spec @@ -0,0 +1,301 @@ +%global _hardened_build 1 + +%define with_gui_qt5 0 +%define with_dbus 0 + +Name: usbguard +Version: 0.7.0 +Release: 8%{?dist} +Summary: A tool for implementing USB device usage policy +Group: System Environment/Daemons +License: GPLv2+ +## Not installed +# src/ThirdParty/Catch: Boost Software License - Version 1.0 +URL: https://dkopecek.github.io/usbguard +Source0: https://github.com/dkopecek/usbguard/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz +Source1: usbguard-daemon.conf + +Requires: systemd +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +BuildRequires: libqb-devel +BuildRequires: libgcrypt-devel +BuildRequires: libstdc++-devel +BuildRequires: protobuf-devel protobuf-compiler +BuildRequires: PEGTL-static +BuildRequires: catch-devel +BuildRequires: autoconf automake libtool +BuildRequires: bash-completion +BuildRequires: audit-libs-devel +# For `pkg-config systemd` only +BuildRequires: systemd + +%if 0%{with_gui_qt5} +BuildRequires: qt5-qtbase-devel qt5-qtsvg-devel qt5-linguist +%endif + +%if 0%{with_dbus} +BuildRequires: dbus-glib-devel +BuildRequires: dbus-devel +BuildRequires: glib2-devel +BuildRequires: polkit-devel +BuildRequires: libxslt +BuildRequires: libxml2 +%endif + +%if 0%{?fedora} +BuildRequires: pandoc +%endif + +%ifarch ppc +# +# We need atomic instruction emulation on the 32bit PPC arch +# +BuildRequires: libatomic +%endif + +# 1444084 - New defects found in usbguard-0.7.0-1.el7 +Patch0: usbguard-0.7.0-covscan-uninit-ctor.patch +# 1449344 - usbguard-daemon.conf(5) documentation issues in usbguard-0.7.0-2.el7 +Patch1: usbguard-0.7.0-fixed-usbguard-daemon-conf-man-page.patch +Patch2: usbguard-0.7.0-fixed-usbguard-daemon-man-page.patch +# +# Apply upstream cleanup/refactoring changes to the 0.7.0 source +# code to make it compatible with future upstream patches. +# +Patch3: usbguard-0.7.0-upstream-compat.patch +# 1469399 - RFE: Use Type=forking instead of Type=simple in usbguard.service unit +Patch4: usbguard-0.7.0-daemonization.patch +# +# Disable some tests that require a controlled environment or are not required to +# be executed while building binary RPMs. +# +Patch5: usbguard-0.7.0-make-full-testsuite-conditional.patch +# 1487230 - unknown usbguard-daemon.conf directives don't trigger an error +Patch6: usbguard-0.7.0-strict-configuration-parsing.patch +# 1491313 - [RFE] Integrate USBGuard with Linux Audit subsystem +Patch7: usbguard-0.7.0-linux-audit-integration.patch +# 1516930 - usbguard fails to start on aarch64 (RHEL-ALT) +Patch8: usbguard-0.7.0-kernel-4.13-fix.patch +# 1491313 - [RFE] Integrate USBGuard with Linux Audit subsystem +Patch9: usbguard-0.7.0-libaudit-version.patch + +%description +The USBGuard software framework helps to protect your computer against rogue USB +devices by implementing basic whitelisting/blacklisting capabilities based on +USB device attributes. + +%package devel +Summary: Development files for %{name} +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig +Requires: libstdc++-devel + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + +%package tools +Summary: USBGuard Tools +Group: Applications/System +Requires: %{name} = %{version}-%{release} + +%description tools +The %{name}-tools package contains optional tools from the USBGuard +software framework. + +%if 0%{with_gui_qt5} +### +%package applet-qt +Summary: USBGuard Qt 5.x Applet +Group: Applications/System +Requires: %{name} = %{version}-%{release} + +%description applet-qt +The %{name}-applet-qt package contains an optional Qt 5.x desktop applet +for interacting with the USBGuard daemon component. +### +%endif + +%if 0%{with_dbus} +### +%package dbus +Summary: USBGuard D-Bus Service +Group: Applications/System +Requires: %{name} = %{version}-%{release} +Requires: dbus +Requires: polkit + +%description dbus +The %{name}-dbus package contains an optional component that provides +a D-Bus interface to the USBGuard daemon component. +### +%endif + +%prep +%setup -q +# Remove bundled library sources before build +rm -rf src/ThirdParty/{Catch,PEGTL} + +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 + +%build +mkdir -p ./m4 +autoreconf -i -v --no-recursive ./ +%configure \ + --disable-silent-rules \ + --without-bundled-catch \ + --without-bundled-pegtl \ + --enable-systemd \ +%if 0%{with_gui_qt5} + --with-gui-qt=qt5 \ +%endif +%if 0%{with_dbus} + --with-dbus \ + --with-polkit \ +%else + --without-dbus \ + --without-polkit \ +%endif + --with-crypto-library=gcrypt + +make %{?_smp_mflags} + +%check +make check + +%install +make install INSTALL='install -p' DESTDIR=%{buildroot} + +# Overwrite configuration with distribution defaults +mkdir -p %{buildroot}%{_sysconfdir}/usbguard +install -p -m 600 %{SOURCE1} %{buildroot}%{_sysconfdir}/usbguard/usbguard-daemon.conf + +# Cleanup +find %{buildroot} \( -name '*.la' -o -name '*.a' \) -exec rm -f {} ';' + +%preun +%systemd_preun usbguard.service + +%post +/sbin/ldconfig +%systemd_post usbguard.service + +%postun +/sbin/ldconfig +%systemd_postun usbguard.service + +%files +%defattr(-,root,root,-) +%doc README.md CHANGELOG.md +%license LICENSE +%{_libdir}/*.so.* +%{_sbindir}/usbguard-daemon +%{_bindir}/usbguard +%dir %{_localstatedir}/log/usbguard +%dir %{_sysconfdir}/usbguard +%dir %{_sysconfdir}/usbguard/IPCAccessControl.d +%config(noreplace) %attr(0600,-,-) %{_sysconfdir}/usbguard/usbguard-daemon.conf +%config(noreplace) %attr(0600,-,-) %{_sysconfdir}/usbguard/rules.conf +%{_unitdir}/usbguard.service +%{_datadir}/man/man8/usbguard-daemon.8.gz +%{_datadir}/man/man5/usbguard-daemon.conf.5.gz +%{_datadir}/man/man5/usbguard-rules.conf.5.gz +%{_datadir}/man/man1/usbguard.1.gz +%{_datadir}/bash-completion/completions/usbguard + +%files devel +%defattr(-,root,root,-) +%{_includedir}/* +%{_libdir}/*.so +%{_libdir}/pkgconfig/*.pc + +%files tools +%defattr(-,root,root,-) +%{_bindir}/usbguard-rule-parser + +%if 0%{with_gui_qt5} +### +%files applet-qt +%defattr(-,root,root,-) +%{_bindir}/usbguard-applet-qt +%{_mandir}/man1/usbguard-applet-qt.1.gz +%{_datadir}/applications/usbguard-applet-qt.desktop +%{_datadir}/icons/hicolor/scalable/apps/usbguard-icon.svg +### +%endif + +%if 0%{with_dbus} +### +%files dbus +%defattr(-,root,root,-) +%{_sbindir}/usbguard-dbus +%{_datadir}/dbus-1/system-services/org.usbguard.service +%{_datadir}/dbus-1/system.d/org.usbguard.conf +%{_datadir}/polkit-1/actions/org.usbguard.policy +%{_unitdir}/usbguard-dbus.service +%{_mandir}/man8/usbguard-dbus.8.gz + +%preun dbus +%systemd_preun usbguard-dbus.service + +%post dbus +%systemd_post usbguard-dbus.service + +%postun dbus +%systemd_postun_with_restart usbguard-dbus.service +### +%endif + +%changelog +* Wed Dec 13 2017 Daniel Kopeček 0.7.0-8 +- RHEL 7.5 erratum + - Require a lower version of libaudit during build-time + Resolves: rhbz#1491313 + +* Mon Nov 27 2017 Daniel Kopeček 0.7.0-7 +- RHEL 7.5 erratum + - Fixed usbguard-daemon on systems with kernel >= 4.13 + - Use distribution specific usbguard-daemon.conf instead + of the upstream version + Resolves: rhbz#1516930 + +* Fri Nov 3 2017 Daniel Kopeček 0.7.0-6 +- RHEL 7.5 erratum + - Add Linux Audit integration + Resolves: rhbz#1491313 + +* Thu Nov 2 2017 Daniel Kopeček 0.7.0-5 +- RHEL 7.5 erratum + - Make parsing of configuration file strict + Resolves: rhbz#1487230 + +* Tue Oct 17 2017 Daniel Kopeček 0.7.0-4 +- RHEL 7.5 erratum + - Implemented double-fork daemonization support + Resolves: rhbz#1469399 + +* Fri May 12 2017 Daniel Kopeček 0.7.0-3 +- Fixed usbguard-daemon and usbguard-daemon.conf man-pages + Resolves: rhbz#1449344 + +* Thu Apr 20 2017 Daniel Kopeček 0.7.0-2 +- Fixed UNINIT_CTOR issues found by coverity scan + Resolves: rhbz#1444084 + +* Fri Apr 14 2017 Daniel Kopeček 0.7.0-1 +- Import