Repository: dkopecek/usbguard Branch: main Commit: 90f0b502538e Files: 468 Total size: 6.8 MB Directory structure: gitextract__08spewc/ ├── .gitattributes ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── build.yml │ ├── docker.yml │ └── polkit.yml ├── .gitignore ├── .gitmodules ├── .lgtm.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile.am ├── README.adoc ├── RELEASE_PROCESS.md ├── VERSION ├── abi-ref/ │ └── libusbguard.so.abi ├── autogen.sh ├── configure.ac ├── doc/ │ └── man/ │ ├── .gitignore │ ├── example-allow-device.adoc │ ├── example-initial-policy.adoc │ ├── footer.adoc │ ├── usbguard-daemon.8.adoc │ ├── usbguard-daemon.conf.5.adoc │ ├── usbguard-dbus.8.adoc │ ├── usbguard-ldap.conf.5.adoc │ ├── usbguard-rules.conf.5.adoc │ └── usbguard.1.adoc ├── libusbguard.pc.in ├── m4/ │ ├── ax_check_compile_flag.m4 │ ├── ax_pthread.m4 │ └── libgcrypt.m4 ├── scripts/ │ ├── astyle.sh │ ├── bash_completion/ │ │ └── usbguard │ ├── copr-build-srpm.sh │ ├── docker/ │ │ ├── build_on_alpine_linux_3_21.Dockerfile │ │ ├── build_on_centos_8_2.Dockerfile │ │ ├── build_on_debian_buster_with_gcc_9_2.Dockerfile │ │ ├── build_on_ubuntu_22_04.Dockerfile │ │ └── build_on_ubuntu_25_04.Dockerfile │ ├── ldap/ │ │ ├── ldap.sh │ │ ├── schema2ldif.pl │ │ ├── setup.ldif │ │ ├── usbguard-policy.ldif │ │ ├── usbguard.ldif │ │ └── usbguard.schema │ ├── modeline.vim │ ├── reformat-sources.sh │ ├── rule-generator.sh │ ├── usb-descriptor-collect.sh │ └── usbguard-zsh-completion ├── src/ │ ├── .gitignore │ ├── CLI/ │ │ ├── IPCSignalWatcher.cpp │ │ ├── IPCSignalWatcher.hpp │ │ ├── PolicyGenerator.cpp │ │ ├── PolicyGenerator.hpp │ │ ├── usbguard-add-user.cpp │ │ ├── usbguard-add-user.hpp │ │ ├── usbguard-allow-device.cpp │ │ ├── usbguard-allow-device.hpp │ │ ├── usbguard-append-rule.cpp │ │ ├── usbguard-append-rule.hpp │ │ ├── usbguard-apply-device-policy.cpp │ │ ├── usbguard-apply-device-policy.hpp │ │ ├── usbguard-block-device.cpp │ │ ├── usbguard-block-device.hpp │ │ ├── usbguard-generate-policy.cpp │ │ ├── usbguard-generate-policy.hpp │ │ ├── usbguard-get-parameter.cpp │ │ ├── usbguard-get-parameter.hpp │ │ ├── usbguard-list-devices.cpp │ │ ├── usbguard-list-devices.hpp │ │ ├── usbguard-list-rules.cpp │ │ ├── usbguard-list-rules.hpp │ │ ├── usbguard-print-version.cpp │ │ ├── usbguard-print-version.hpp │ │ ├── usbguard-read-descriptor.cpp │ │ ├── usbguard-read-descriptor.hpp │ │ ├── usbguard-reject-device.cpp │ │ ├── usbguard-reject-device.hpp │ │ ├── usbguard-remove-rule.cpp │ │ ├── usbguard-remove-rule.hpp │ │ ├── usbguard-remove-user.cpp │ │ ├── usbguard-remove-user.hpp │ │ ├── usbguard-rule-parser.cpp │ │ ├── usbguard-set-parameter.cpp │ │ ├── usbguard-set-parameter.hpp │ │ ├── usbguard-watch.cpp │ │ ├── usbguard-watch.hpp │ │ ├── usbguard.cpp │ │ └── usbguard.hpp │ ├── Common/ │ │ ├── ByteOrder.hpp │ │ ├── FDInputStream.hpp │ │ ├── LDAPUtil.cpp │ │ ├── LDAPUtil.hpp │ │ ├── Thread.hpp │ │ ├── Utility.cpp │ │ └── Utility.hpp │ ├── DBus/ │ │ ├── .gitignore │ │ ├── DBusBridge.cpp │ │ ├── DBusBridge.hpp │ │ ├── DBusInterface.xml │ │ ├── README.adoc │ │ ├── gdbus-server.cpp │ │ ├── generate-documentation.sh │ │ ├── org.usbguard1.conf │ │ ├── org.usbguard1.policy │ │ ├── org.usbguard1.service.in │ │ └── usbguard-dbus.service.in │ ├── Daemon/ │ │ ├── Daemon.cpp │ │ ├── Daemon.hpp │ │ ├── FileAuditBackend.cpp │ │ ├── FileAuditBackend.hpp │ │ ├── FileRuleSet.cpp │ │ ├── FileRuleSet.hpp │ │ ├── LDAPHandler.cpp │ │ ├── LDAPHandler.hpp │ │ ├── LDAPRuleSet.cpp │ │ ├── LDAPRuleSet.hpp │ │ ├── LinuxAuditBackend.cpp │ │ ├── LinuxAuditBackend.hpp │ │ ├── NSHandler.cpp │ │ ├── NSHandler.hpp │ │ ├── RuleSetFactory.cpp │ │ ├── RuleSetFactory.hpp │ │ ├── Seccomp.c │ │ ├── Seccomp.h │ │ └── main.cpp │ ├── Library/ │ │ ├── AllowedMatchesCondition.cpp │ │ ├── AllowedMatchesCondition.hpp │ │ ├── Base64.cpp │ │ ├── Base64.hpp │ │ ├── ConfigFilePrivate.cpp │ │ ├── ConfigFilePrivate.hpp │ │ ├── DeviceBase.cpp │ │ ├── DeviceBase.hpp │ │ ├── DeviceManagerBase.cpp │ │ ├── DeviceManagerBase.hpp │ │ ├── DeviceManagerPrivate.cpp │ │ ├── DeviceManagerPrivate.hpp │ │ ├── DevicePrivate.cpp │ │ ├── DevicePrivate.hpp │ │ ├── FixedStateCondition.cpp │ │ ├── FixedStateCondition.hpp │ │ ├── Hash.cpp │ │ ├── Hash.hpp │ │ ├── IPC/ │ │ │ ├── .gitignore │ │ │ ├── Devices.proto │ │ │ ├── Exception.proto │ │ │ ├── Message.proto │ │ │ ├── Parameter.proto │ │ │ ├── Policy.proto │ │ │ └── Rule.proto │ │ ├── IPCClientPrivate.cpp │ │ ├── IPCClientPrivate.hpp │ │ ├── IPCPrivate.cpp │ │ ├── IPCPrivate.hpp │ │ ├── IPCServerPrivate.cpp │ │ ├── IPCServerPrivate.hpp │ │ ├── Init.cpp │ │ ├── KeyValueParserPrivate.cpp │ │ ├── KeyValueParserPrivate.hpp │ │ ├── LocaltimeCondition.cpp │ │ ├── LocaltimeCondition.hpp │ │ ├── RandomStateCondition.cpp │ │ ├── RandomStateCondition.hpp │ │ ├── RuleAppliedCondition.cpp │ │ ├── RuleAppliedCondition.hpp │ │ ├── RuleEvaluatedCondition.cpp │ │ ├── RuleEvaluatedCondition.hpp │ │ ├── RuleParser/ │ │ │ ├── Actions.hpp │ │ │ └── Grammar.hpp │ │ ├── RulePrivate.cpp │ │ ├── RulePrivate.hpp │ │ ├── SysFSDevice.cpp │ │ ├── SysFSDevice.hpp │ │ ├── UEvent.cpp │ │ ├── UEvent.hpp │ │ ├── UEventDeviceManager.cpp │ │ ├── UEventDeviceManager.hpp │ │ ├── UEventParser.cpp │ │ ├── UEventParser.hpp │ │ ├── UMockdevDeviceDefinition.cpp │ │ ├── UMockdevDeviceDefinition.hpp │ │ ├── UMockdevDeviceManager.cpp │ │ ├── UMockdevDeviceManager.hpp │ │ ├── Utility.cpp │ │ ├── Utility.hpp │ │ └── public/ │ │ └── usbguard/ │ │ ├── Audit.cpp │ │ ├── Audit.hpp │ │ ├── ConfigFile.cpp │ │ ├── ConfigFile.hpp │ │ ├── Device.cpp │ │ ├── Device.hpp │ │ ├── DeviceManager.cpp │ │ ├── DeviceManager.hpp │ │ ├── DeviceManagerHooks.cpp │ │ ├── DeviceManagerHooks.hpp │ │ ├── Exception.hpp │ │ ├── IPCClient.cpp │ │ ├── IPCClient.hpp │ │ ├── IPCServer.cpp │ │ ├── IPCServer.hpp │ │ ├── Interface.hpp │ │ ├── KeyValueParser.cpp │ │ ├── KeyValueParser.hpp │ │ ├── Logger.cpp │ │ ├── Logger.hpp │ │ ├── MemoryRuleSet.cpp │ │ ├── MemoryRuleSet.hpp │ │ ├── Policy.cpp │ │ ├── Policy.hpp │ │ ├── Predicates.hpp │ │ ├── Rule.cpp │ │ ├── Rule.hpp │ │ ├── RuleCondition.cpp │ │ ├── RuleCondition.hpp │ │ ├── RuleParser.cpp │ │ ├── RuleParser.hpp │ │ ├── RuleSet.cpp │ │ ├── RuleSet.hpp │ │ ├── Typedefs.cpp │ │ ├── Typedefs.hpp │ │ ├── USB.cpp │ │ ├── USB.hpp │ │ ├── USBGuard.cpp │ │ └── USBGuard.hpp │ ├── Tests/ │ │ ├── .gitignore │ │ ├── Fuzzers/ │ │ │ ├── Makefile.am │ │ │ ├── fuzzer-rules.cpp │ │ │ ├── fuzzer-uevent.cpp │ │ │ └── fuzzer-usb-descriptor.cpp │ │ ├── LDAP/ │ │ │ ├── Sanity/ │ │ │ │ └── ldap-nsswitch.sh │ │ │ ├── UseCase/ │ │ │ │ ├── ldap-test-1.sh │ │ │ │ ├── ldap-test-2.sh │ │ │ │ ├── ldap-test-3.sh │ │ │ │ ├── ldap-test-4.sh │ │ │ │ └── ldap-test-5.sh │ │ │ ├── ansible/ │ │ │ │ ├── hosts │ │ │ │ ├── playbook.yml │ │ │ │ └── roles/ │ │ │ │ └── bennojoy.openldap_server/ │ │ │ │ ├── README.md │ │ │ │ ├── defaults/ │ │ │ │ │ └── main.yml │ │ │ │ ├── files/ │ │ │ │ │ ├── ldap │ │ │ │ │ ├── slapd │ │ │ │ │ └── slapd_fedora │ │ │ │ ├── handlers/ │ │ │ │ │ └── main.yml │ │ │ │ ├── meta/ │ │ │ │ │ └── main.yml │ │ │ │ ├── tasks/ │ │ │ │ │ ├── configure_ldap.yml │ │ │ │ │ ├── install_ldap.yml │ │ │ │ │ └── main.yml │ │ │ │ ├── templates/ │ │ │ │ │ ├── domain.ldif │ │ │ │ │ ├── ldap.conf.j2 │ │ │ │ │ ├── slapd.conf.j2 │ │ │ │ │ ├── slapd.conf_ubuntu.j2 │ │ │ │ │ ├── slapd.fedora.ldif.j2 │ │ │ │ │ └── slapd.ubuntu.ldif.j2 │ │ │ │ └── vars/ │ │ │ │ ├── Debian.yml │ │ │ │ ├── RedHat.yml │ │ │ │ └── main.yml │ │ │ ├── ldap.sh │ │ │ ├── nsswitch.sh │ │ │ ├── setup.ldif │ │ │ ├── usbguard-policy.ldif │ │ │ ├── usbguard.ldif │ │ │ └── usbguard.schema │ │ ├── Makefile.am │ │ ├── Regression/ │ │ │ ├── github-PR209-config-parser.cpp │ │ │ ├── test_Rule_ghi113.cpp │ │ │ ├── test_Rule_ghi247.cpp │ │ │ └── test_Rule_ghi37.cpp │ │ ├── Rules/ │ │ │ ├── test-rules.bad │ │ │ ├── test-rules.file │ │ │ ├── test-rules.good │ │ │ └── test-rules.sh │ │ ├── Source/ │ │ │ ├── CheckScripts/ │ │ │ │ ├── code-style.sh │ │ │ │ ├── copyright.sh │ │ │ │ ├── private-with-build-config.sh │ │ │ │ ├── public-without-build-config.sh │ │ │ │ ├── spell-check.rws │ │ │ │ ├── spell-check.sh │ │ │ │ └── vim-modeline.sh │ │ │ └── check-driver.sh │ │ ├── USB/ │ │ │ ├── data/ │ │ │ │ └── 0001.out │ │ │ └── test-descriptor-parser.sh │ │ ├── Unit/ │ │ │ ├── test_Base64.cpp │ │ │ ├── test_IPCServer_AccessControl.cpp │ │ │ ├── test_Rule.cpp │ │ │ ├── test_RuleAttribute_id.cpp │ │ │ ├── test_RuleParser.cpp │ │ │ ├── test_UEvent.cpp │ │ │ ├── test_UEventParser.cpp │ │ │ ├── test_UMockdevDeviceDefinition.cpp │ │ │ ├── test_UMockdevDeviceDefinition.data.hpp │ │ │ └── test_Utility.cpp │ │ ├── UseCase/ │ │ │ ├── 000_executable.sh │ │ │ ├── 001_cli_policy.sh │ │ │ ├── 002_cli_devices.sh │ │ │ ├── 003_cli_devices_umockdev.sh │ │ │ ├── 004_daemonize.sh │ │ │ ├── 005_cli_devices_advanced.sh │ │ │ └── devices.umockdev │ │ ├── bash-testlib.sh │ │ ├── custom.supp │ │ └── main.cpp │ ├── ThirdParty/ │ │ └── xsl-stylesheets/ │ │ ├── VERSION.xsl │ │ ├── common/ │ │ │ ├── af.xml │ │ │ ├── am.xml │ │ │ ├── ar.xml │ │ │ ├── as.xml │ │ │ ├── ast.xml │ │ │ ├── autoidx-kimber.xsl │ │ │ ├── autoidx-kosek.xsl │ │ │ ├── az.xml │ │ │ ├── bg.xml │ │ │ ├── bn.xml │ │ │ ├── bn_in.xml │ │ │ ├── bs.xml │ │ │ ├── ca.xml │ │ │ ├── charmap.xml │ │ │ ├── charmap.xsl │ │ │ ├── common.xml │ │ │ ├── common.xsl │ │ │ ├── cs.xml │ │ │ ├── cy.xml │ │ │ ├── da.xml │ │ │ ├── de.xml │ │ │ ├── el.xml │ │ │ ├── en.xml │ │ │ ├── entities.ent │ │ │ ├── eo.xml │ │ │ ├── es.xml │ │ │ ├── et.xml │ │ │ ├── eu.xml │ │ │ ├── fa.xml │ │ │ ├── fi.xml │ │ │ ├── fr.xml │ │ │ ├── ga.xml │ │ │ ├── gentext.xsl │ │ │ ├── gl.xml │ │ │ ├── gu.xml │ │ │ ├── he.xml │ │ │ ├── hi.xml │ │ │ ├── hr.xml │ │ │ ├── hu.xml │ │ │ ├── id.xml │ │ │ ├── insertfile.xsl │ │ │ ├── is.xml │ │ │ ├── it.xml │ │ │ ├── ja.xml │ │ │ ├── ka.xml │ │ │ ├── kn.xml │ │ │ ├── ko.xml │ │ │ ├── ky.xml │ │ │ ├── l10n.dtd │ │ │ ├── l10n.xml │ │ │ ├── l10n.xsl │ │ │ ├── la.xml │ │ │ ├── labels.xsl │ │ │ ├── lt.xml │ │ │ ├── lv.xml │ │ │ ├── ml.xml │ │ │ ├── mn.xml │ │ │ ├── mr.xml │ │ │ ├── nb.xml │ │ │ ├── nds.xml │ │ │ ├── nl.xml │ │ │ ├── nn.xml │ │ │ ├── olink.xsl │ │ │ ├── or.xml │ │ │ ├── pa.xml │ │ │ ├── pi.xml │ │ │ ├── pi.xsl │ │ │ ├── pl.xml │ │ │ ├── pt.xml │ │ │ ├── pt_br.xml │ │ │ ├── refentry.xml │ │ │ ├── refentry.xsl │ │ │ ├── ro.xml │ │ │ ├── ru.xml │ │ │ ├── sk.xml │ │ │ ├── sl.xml │ │ │ ├── sq.xml │ │ │ ├── sr.xml │ │ │ ├── sr_Latn.xml │ │ │ ├── stripns.xsl │ │ │ ├── subtitles.xsl │ │ │ ├── sv.xml │ │ │ ├── ta.xml │ │ │ ├── table.xsl │ │ │ ├── targetdatabase.dtd │ │ │ ├── targets.xsl │ │ │ ├── te.xml │ │ │ ├── th.xml │ │ │ ├── titles.xsl │ │ │ ├── tl.xml │ │ │ ├── tr.xml │ │ │ ├── uk.xml │ │ │ ├── utility.xml │ │ │ ├── utility.xsl │ │ │ ├── vi.xml │ │ │ ├── xh.xml │ │ │ ├── zh.xml │ │ │ ├── zh_cn.xml │ │ │ └── zh_tw.xml │ │ ├── lib/ │ │ │ ├── dumpfragment.xsl │ │ │ └── lib.xsl │ │ └── xhtml-1_1/ │ │ ├── admon.xsl │ │ ├── annotations.xsl │ │ ├── autoidx-kimber.xsl │ │ ├── autoidx-kosek.xsl │ │ ├── autoidx-ng.xsl │ │ ├── autoidx.xsl │ │ ├── autotoc.xsl │ │ ├── biblio-iso690.xsl │ │ ├── biblio.xsl │ │ ├── block.xsl │ │ ├── callout.xsl │ │ ├── changebars.xsl │ │ ├── chunk-changebars.xsl │ │ ├── chunk-code.xsl │ │ ├── chunk-common.xsl │ │ ├── chunk.xsl │ │ ├── chunker.xsl │ │ ├── chunkfast.xsl │ │ ├── chunktoc.xsl │ │ ├── component.xsl │ │ ├── division.xsl │ │ ├── docbook.xsl │ │ ├── ebnf.xsl │ │ ├── footnote.xsl │ │ ├── formal.xsl │ │ ├── glossary.xsl │ │ ├── graphics.xsl │ │ ├── highlight.xsl │ │ ├── html-rtf.xsl │ │ ├── html.xsl │ │ ├── htmltbl.xsl │ │ ├── index.xsl │ │ ├── info.xsl │ │ ├── inline.xsl │ │ ├── keywords.xsl │ │ ├── lists.xsl │ │ ├── maketoc.xsl │ │ ├── manifest.xsl │ │ ├── math.xsl │ │ ├── oldchunker.xsl │ │ ├── onechunk.xsl │ │ ├── param.xsl │ │ ├── pi.xsl │ │ ├── profile-chunk-code.xsl │ │ ├── profile-chunk.xsl │ │ ├── profile-docbook.xsl │ │ ├── profile-onechunk.xsl │ │ ├── qandaset.xsl │ │ ├── refentry.xsl │ │ ├── sections.xsl │ │ ├── synop.xsl │ │ ├── table.xsl │ │ ├── task.xsl │ │ ├── titlepage.templates.xsl │ │ ├── titlepage.xsl │ │ ├── toc.xsl │ │ ├── verbatim.xsl │ │ └── xref.xsl │ ├── astylerc │ └── test_filesystem.cpp ├── usbguard-daemon.conf.in ├── usbguard-tmpfiles.conf └── usbguard.service.in ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ src/ThirdParty/* linguist-vendored ================================================ FILE: .github/dependabot.yml ================================================ ## ## Copyright (c) 2023 Sebastian Pipping ## ## 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 . version: 2 updates: - package-ecosystem: "github-actions" commit-message: include: "scope" prefix: "Actions" directory: "/" labels: - "enhancement" schedule: interval: "weekly" ================================================ FILE: .github/workflows/build.yml ================================================ name: C/C++ CI on: push: pull_request: schedule: - cron: '0 4 * * 5' # Every Friday at 4am # Drop permissions to minimum for security permissions: contents: read jobs: build: runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: config: - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libgcrypt-dev" } - { name: "Ubuntu_CLANG", os: ubuntu-22.04, cc: "clang", cxx: "clang++", crypto: "libgcrypt-dev", configure_args: "--enable-asan" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libgcrypt-dev", configure_args: "--without-ldap" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libgcrypt-dev", configure_args: "--enable-debug-build" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libgcrypt-dev", configure_args: "--enable-asan" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libgcrypt-dev", configure_args: "--with-crypto-library=gcrypt" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libsodium-dev", configure_args: "--with-crypto-library=sodium" } - { name: "Ubuntu_GCC", os: ubuntu-22.04, cc: "gcc", cxx: "g++", crypto: "libssl-dev", configure_args: "--with-crypto-library=openssl" } steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: installing dependencies run: | sudo apt-get -qq update sudo apt-get install -y ansible sudo apt-get install -y libudev-dev libsodium-dev libqb-dev libcap-ng-dev libseccomp-dev sudo apt-get install -y libglib2.0-dev libdbus-glib-1-dev libxml2-utils libpolkit-gobject-1-dev xsltproc sudo apt-get install -y lcov sudo apt-get install -y aspell aspell-en sudo apt-get install -y libprotobuf-dev protobuf-compiler sudo apt-get install -y libldap-dev sudo apt-get install -y valgrind sudo apt-get install -y asciidoc docbook-xml docbook-xsl sudo apt-get install -y umockdev libumockdev-dev sudo gem install coveralls-lcov sudo apt-get install -y ${{ matrix.config.cc }} sudo apt-get install -y ${{ matrix.config.cxx }} || true sudo apt-get install -y ${{ matrix.config.crypto }} sudo apt-get install -y astyle - name: setup environment run: | cd src/Tests/LDAP/ansible ansible-playbook -i ./hosts -u root --connection=local playbook.yml - name: build run: | ./autogen.sh mkdir build && cd build ${{ matrix.config.cc }} --version ${{ matrix.config.cxx }} --version CC=${{ matrix.config.cc }} CXX=${{ matrix.config.cxx }} ../configure --enable-werror --disable-silent-rules --with-bundled-catch --with-bundled-pegtl --with-ldap --enable-full-test-suite ${{ matrix.config.configure_args }} make "-j$(nproc)" - name: install (off-system, for coverage) run: |- set -x -o pipefail make -C build DESTDIR="${PWD}"/ROOT install find ROOT/ -not -type d | sort | xargs ls -l rm -Rf find ROOT/ # to not interfere with check-driver.sh - name: check run: sudo make -C build check -j1 || { find -name test-suite.log -print -exec cat {} \; ; false ; } - name: distcheck run: sudo make -C build distcheck -j1 || { find -name test-suite.log -print -exec cat {} \; ; false ; } ================================================ FILE: .github/workflows/docker.yml ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . name: Build on non-Ubuntu Linux using Docker on: push: pull_request: schedule: - cron: '0 4 * * 5' # Every Friday at 4am # Drop permissions to minimum for security permissions: contents: read jobs: build_docker: strategy: fail-fast: false matrix: linux_distro: - Alpine Linux 3.21 # with musl - CentOS 8.2 # with GCC 8.5.0 # - Debian Buster with GCC 9.2 # stock buster has GCC 8.3 - temporarily disabled - Ubuntu 22.04 # because super popular - Ubuntu 25.04 # because GCC 15+ name: Build on ${{ matrix.linux_distro }} using Docker runs-on: ubuntu-22.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build on ${{ matrix.linux_distro }} using Docker run: | set -x # Create tarballs used by Dockerfile git submodule update --init git archive -o usbguard.tar HEAD ( cd src/ThirdParty/PEGTL/ && git archive -o ../../../pegtl.tar HEAD ) ( cd src/ThirdParty/Catch/ && git archive -o ../../../catch.tar HEAD ) # Build using Docker linux_distro="$(tr '[:upper:]' '[:lower:]' <<<"${{ matrix.linux_distro }}" | sed 's,[ .],_,g')" docker build -f scripts/docker/build_on_"${linux_distro}".Dockerfile . ================================================ FILE: .github/workflows/polkit.yml ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . name: Check for Polkit policy parse errors on: push: pull_request: schedule: - cron: '0 4 * * 5' # Every Friday at 4am # Drop permissions to minimum for security permissions: contents: read jobs: polkit_policies: name: Check for Polkit policy parse errors runs-on: ubuntu-22.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install runtime dependencies run: | set -x sudo apt-get update sudo apt-get install --no-install-recommends --yes -V expat - name: Check for Polkit policy parse errors run: | # This will work around pkaction exiting with unjustified(?) # code 1 on Ubuntu 20.04 check_polkit_action() { pkaction -v -a "$1" | tee /dev/stderr | fgrep -q 'implicit any' ; } set -x actions=( org.usbguard.Devices1.listDevices org.usbguard.Devices1.applyDevicePolicy org.usbguard.Policy1.appendRule org.usbguard.Policy1.listRules org.usbguard.Policy1.removeRule org.usbguard1.getParameter org.usbguard1.setParameter ) # Self-test: Assert that prior to installation, our Polkit "actions" # are unknown to PolKit. ! check_polkit_action "${actions[0]}" # Install the policy so that polkin can find it xmlwf src/DBus/org.usbguard1.policy sudo cp -v src/DBus/org.usbguard1.policy /usr/share/polkit-1/actions/ # Assert that after installation, all of our Polkit "actions" are known. # This detects parse error regressions. for action in "${actions[@]}"; do check_polkit_action "${action}" done ================================================ FILE: .gitignore ================================================ /libusbguard.pc /usbguard /usbguard-daemon /usbguard-daemon.conf /usbguard-dbus /usbguard-rule-parser Makefile Makefile.in .deps .libs libtool configure config/ config.log config.status build/ .dirstamp .ycm_extra_conf.py stamp-h1 test-driver *~ *.sw[po] *.l[oa] *.o aclocal.m4 autom4te.cache/ m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 src/build-config.h.in.in ================================================ FILE: .gitmodules ================================================ [submodule "src/ThirdParty/Catch"] path = src/ThirdParty/Catch url = https://github.com/philsquared/Catch [submodule "src/ThirdParty/PEGTL"] path = src/ThirdParty/PEGTL url = https://github.com/ColinH/PEGTL ================================================ FILE: .lgtm.yml ================================================ # lgtm.yml configuration file for C/C++ analysis # of USBGuard on lgtm.com: # https://lgtm.com/projects/g/USBGuard/usbguard extraction: cpp: prepare: # Most Debian/Ubuntu package dependencies # are automatically detected, but this one # is not. The team at lgtm.com are looking # into it. packages: - libdbus-glib-1-dev after_prepare: - ./autogen.sh configure: command: |- ${CC:-cc} --version ${CXX:-c++} --version ./configure --with-bundled-pegtl || { cat config.log ; false ; } ================================================ FILE: CHANGELOG.md ================================================ # Change Log ## 1.1.4 - 2025-07-15 ### Fixed - Add tmpfiles.d file for /var/log/usbguard - Ignore errors from rmdir during uninstallation - Fix regression when specifying IPC privileges using UID - Fix support for loongarch - Adapt for protobuf 3.0 API changes - Add support for Catch2 v3 - new configure option --enable/disable-catch - add FDStreamBuf destructor to stop fd leak ## 1.1.3 - 2024-06-06 ### Fixed - Addressed several cases where either RuleFile or RuleFolder was not set. - Resolved a race condition during fork where the parent process did not wait until everything was initialized in the child process. - Included missing documentation in the tarball. - Fixed compatibility issues with GCC 13+. ### Added - Implemented detection of integer overflow for device IDs to ensure that each device can be uniquely identified by a single ID. - Enhanced the service file to disable the Linux kernel's Out-Of-Memory (OOM) killing of processes for this unit. - D-bus: check if the client requested interactive authentication, as some clients do not prompt for passwords. - Made minor adjustments to the documentation. - RuleFolder is enabled by default. At startup, the path to folder must exist and be accessible by the daemon. ## 1.1.2 - 2022-09-02 ### Fixed - Polkit: Always allow getParameter/listDevices/listRules in active sessions - D-Bus: Send reply on auth failure - Polkit: Unreference PolkitAuthorizationResult and PolkitAuthority structs if needed ## 1.1.1 - 2022-03-15 ### Fixed - Restore support for access control filenames without a group ## 1.1.0 - 2022-02-24 ### Added - Started building with C++17 - Tree-like list-devices output - Added CAP_AUDIT_WRITE capability to service file - Added support for lower OpenSSL versions prior to 1.1.0 - Added a new signal: DevicePolicyApplied ### Fixed/Changed - Moved PIDFile from /var/run to /run - Fixed linker isssues with disable-static - Enhanced bash-completion script - Make username/group checking consistent with useradd manual page definition (with addition of capital letters) - Fixed multiple IPC related bugs - Fixed race condition when accessing port/connect_type for USB devices - Using bundled catch v2.13.8 - Using bundled PEGTL v3.2.5 - Fixed usbguard-rule-parser file opening - Fix unauthorized access via D-Bus [CVE-2019-25058] ## 1.0.0 - 2021-01-13 ### Added - Added openssl support - Starting with libtool versioning - Added interface for IPC permission query - Introduced partial rule concept fo CLI - Added WithConnectType for ldap rule ### Fixed/Changed - Daemon does not apply the policy when "change" action event appears anymore - IPCClientPrivate@disconnect is thread safe - Enforced loading of files from .d/ directory in alphabetical order - Improved CLI behaviour to be consistent - Clarified rule's label documentation ## 0.7.8 - 2020-05-20 ### Fixed - Fixed segfaults with rules.d feature ## 0.7.7 - 2020-05-19 ### Added - Added readwritepath to service file - Added match-all keyword to rules language - Added rules.d feature - daemon can load multiple rule files from rules.d/ - Included with-connect-type in dbus signal ### Fixed/Changed - Fixed sigwaitinfo handling - Fixed possible data corruption on stack with appendRule via dbus - Fixed ENOBUFS errno handling on netlink socket - daemon can survive and wait until socket is readable again ### Removed - Dropped unused PIDFile from service file - Dropped deprecated dbus-glib dependency ## 0.7.6 - 2019-11-08 ### Added - Added missing options in manpage usbguard-daemon(8) - Extended the functionality of allow/block/reject commands - the command can handle rule as a param and not only its ID - e.g. in case of allow, command will allow each device that matches provided rule - Added debug info for malformed descriptors ### Fixed/Changed - Changed default backend to uevent - Fixed handling of add uevents during scanning - now we are sure that the enumeration is completed before processing any uevent - we are trying to avoid a race where the kernel is still enumerating the devices - and send the uevent while the parent is being authorised - Silenced 'bind' and 'unbind' uevents ## 0.7.5 - 2019-07-02 ### Added - Added daemon configuration option HidePII - Added check to avoid conflict between ASAN and TSAN - Added daemon configuration option for authorized_default - Added devpath option to generate-policy - Added # line comments to the rule grammar - Added ImplicitPolicyTarget to get/set parameter methods - Added option to filter rules by label when listing - Added the label attribute to rule - Added PropertyParameterChanged signal - Added support for portX/connect_type attribute - Added temporary option to append-rule - Added versioning to DBus service - Added optional LDAP support ### Fixed/Changed - Fixed invalid return value in Rule::Attribute::setSolveEqualsOrdered - Fixed KeyValueParser to validate keys only when known names are set - Fixed uninitialized variables found by coverity - Fixes and cleanups based on LGTM.com report - Hardened systemd service - Rename ListRules parameter 'query' to 'label' - Skip empty lines in usbguard-rule-parser ### Removed - The proof-of-concept Qt applet was removed. It is going to be maintained in a simplified form as a separate project. ## 0.7.4 - 2018-07-12 ### Fixed/Changed - Fixed conditional manual page generation & installation - Replaced Boost library based ext/stdio_filebuf.h implementation with a custom FDStreamBuf implementation ## 0.7.3 - 2018-07-11 ### Changed - usbguard-daemon will now exit with an error if it fails to open a logging file or audit event file. - Updated PEGTL submodule and dropped support for older PEGTL API - Modified the present device enumeration algorithm to be more reliable. Enumeration timeouts won't cause usbguard-daemon process to exit anymore. - Manual pages are now generated using asciidoc (a2x) instead of asciidoctor. - Generation and installation of manual pages is now optional. - Fixed several bugs D-Bus interface XML specification ### Added - umockdev based device manager capable of simulating devices based on umockdev-record files. - Boost libraries can be used as ext/stdio_filebuf.h header file source. ### Removed - Removed DummyDevices.tar.xz tarball that was supposed to be used for testing. ## 0.7.2 - 2018-01-22 ### Fixed/Changed - Fixed memory leaks in usbguard::Hash class. - Fixed file descriptor leaks in usbguard::SysFSDevice class. - Skip audit backend logging when no backend was set. ### Added - Added zsh completion & other scripts to the distribution tarball. ## 0.7.1 - 2017-11-30 ### Added - CLI: usbguard watch command now includes an -e option to run an executable for every received event. Event data are passed to the executable via environment variables. - usbguard-daemon: added "-K" option which can disable logging to console. - Added zsh autocompletion support. - usbguard-daemon: added "-f" option which enabled double-fork daemonization procedure. - Added AuditBackend usbguard-daemon configuration option for selecting audit log backend. - Linux Audit support via new LinuxAudit backend. - Added missing RuleCondition.hpp header file to the public API headers. - Code Style specification via AStyle configuration file. ### Removed - Removed Utility.hpp header file from public API headers - Reduced usage of raw C pointers throughout the code ### Changed - Qt Applet: disabled session management - usbguard-daemon console logging output is enabled by default now. Previously, the -k option had to be passed to enable the output. - Replaced --enable-maintainer-mode configure option with --enable-full-test-suite option. When the new option is not used during the configure phase, only a basic set of test is run during the make check phase. - usbguard-daemon now opens configuration in read-only mode - Fixed UEventDeviceManager to work with Linux Kernel >= 4.13 - Refactored audit logging to support different audit log backends - Reformatted source code to conform to the code style. - Made the configuration parser strict. Unknown directives and wrong syntax will cause an error. - Reformatted documentation from markdown to asciidoc format. ## 0.7.0 - 2017-04-12 ### Added - Added InsertedDevicePolicy configuration option to control the policy method for inserted devices. - Added RestoreControllerDeviceState configuration option. - Added DeviceManagerBackend configuration option. This option can be used to select from several device manager backend implementations. - Implemented an uevent based device manager backend. - Added setParameter, getParameter IPC (incl. D-Bus) methods. - Added set-parameter, get-parameter CLI subcommands. - Qt Applet: Added Spanish (es_AR) translation. - Create empty rules.conf file at install time (make install). - Support for numeric UID/GID values in IPCAllowedUsers and IPCAllowedGroups settings. - If bash completion support is detected at configure time, install the bash completion script during make install. - Added new configuration setting: IPCAccessControlFiles. - IPC access is now configurable down to a section and privilege level per user and/or group. - Added add-user, remove-user usbuard CLI subcommands for creating, removing IPC access control files. - Added AuditFilePath configuration option for setting the location of the USBGuard audit events log file path. If set, the usbguard-daemon will log policy and device related actions and whether they succeeded or not. ### Removed - Removed UDev based device manager backend and UDev related dependencies. - Removed UDev development files/API dependency ### Changed - Reset Linux root hub bcdDevice value before updating device hash. This is a backwards incompatible change because it changes how the device hash is computed for Linux root hub devices. - Refactored low-level USB device handling into SysFSDevice class which represents a device in the /sys filesystem (sysfs). - Removed usage of `readdir_r` because it's obsolete. Replaced with readdir with the assumption that its usage is thread-safe if the directory handle passed to it is not shared between threads. - Extended test suite with use case tests. - Install the usbguard-daemon configuration and policy file with strict file permissions to prevent policy leaks. - Fixed several memory leaks. - Don't pre-resolve user and group names in IPCAllowedUsers and IPCAllowedGroups settings. Instead, resolve the name during the IPC authentication phase. - Changed default values of PresentDevicePolicy (to apply-policy) and IPCAllowedGroups (removed wheel group entry) settings in the shipped usbguard-daemon.conf configuration file. ## 0.6.2 - 2016-09-18 ### Changed - Wait for disconnect in IPCClient dtor if needed - Qt Applet: Fixed loading of decision method and default decision settings ## 0.6.1 - 2016-09-16 ### Changed - Refactored logging subsystem - Fixed handling of IPC disconnect in the IPCClient class - Qt Applet: Fixed handling of main window minimization and maximization - Fixed building on architectures that don't provide required atomic operations. The libatomic emulation library will be used in such cases. - Fixed several typos in the documentation ### Added - Implemented a simple internal logger - Access to the logger via public API - Improved logging coverage. Logging output can be enabled either via CLI options or by setting the `USBGUARD_DEBUG` environment variable to 1. - Qt Applet: UI translation support. - Qt Applet: Czech (cs_CZ) translation ### Removed - Removed spdlog dependency ## 0.6.0 - 2016-09-04 ### Changed - Fixed the daemon to use the match target when matching device rules. This fixes matching devices against the rules in the policy. - Switched to protobuf based IPC - Simplified the IPC and D-Bus interfaces - Refactored custom exceptions ### Added - Added DevicePresenceChanged signal for notifying about device insertions, updates and removals - Added DevicePolicyChanged signal for notifying about device policy changes. - Added ExceptionMessage signal for sending asynchronous exceptions to the IPC/D-Bus clients. - Extended the usbguard CLI watch subcommand with the ability to wait for the IPC connection to become available. See the new `-w` and `-o` options for details. ### Removed - Removed nlohmann/json submodule - Removed allowDevice, blockDevice and rejectDevice methods from the IPC and D-Bus interface. - Removed DeviceAllowed, DeviceBlocked and DeviceRejected signals from the IPC and D-Bus interface (replaced by single signal) - Removed DeviceInserted, DevicePresent and DeviceRemoved signals from the IPC and D-Bus interface (replaced by single signal) ## 0.5.14 - 2016-08-18 ### Changed - Fixed unknown descriptor type handling ## 0.5.13 - 2016-08-16 ### Changed - refactored USB parser to support multiple handlers per USB descriptor type - Qt Applet: device list should be always expanded ### Added - added support for an audio device related endpoint descriptor ## 0.5.12 - 2016-08-14 ### Changed - Fixed a bug in matching USB interface types with wildcards - usbguard-daemon will now abort at startup if the rule file contains syntax error instead of continuing with an empty rule set ## 0.5.11 - 2016-08-13 ### Added - Maintainer script for spellchecking source archive files - Rule::Attribute class for representing the rule attributes - USBDeviceID class for representing the USB device ID - configure script option to control the bundling of PEGTL source files - id attribute to the rule language for specifying the USB device ID - Added a parent device ID field (and methods) to the Device class which tracks the ID of the parent device - Implemented "parent-hash" attribute for associating a device with its parent device. - The QtSvg module/library is now needed to compile the Qt applet - Qt Applet: Device Dialog settings work now - Qt Applet: The settings state is now remembered (via Qt's QSettings class) - Qt Applet: Implemented serial number masking - Qt Applet: Initial implementation of DeviceDialog window position randomization - Qt Applet: IPC exceptions are shown in the message log - Qt Applet: added an initial implementation of the device list with the ability to change authorization target for each device - Qt Applet: show a grey version of the USBGuard icon in IPC disconnected state - usbguard-daemon.conf: added DeviceRulesWithPort setting (set to false by default) - Added support for selecting crypto backend library at compile time using the --with-crypto-library configure script switch ### Changed - **IMPORTANT**: The device hash value computation was changed to include the USB descriptor data. Additionally, the algorithm was changed to SHA-256 and the hash value representation to base64. These changes are backwards incompatible and existing policies that use the hash attribute need to be updated. - Reimplemented the rule parser using PEGTL - Changed public API of the Rule and Device classes because of the new Rule::Attribute class rule attribute representation - Extended the public IPCClient::IPCDisconnected method to include exception related information - All rule attributes now support both the single and multivalued form - A rule attribute can now be specified only once - The default usbguard-daemon.conf and usbguard.service files now respect the paths set by the configure script - New Qt applet icons with - Fixed Qt applet so that it doesn't show an empty window when starting - Qt Applet: Reject button is hidden by default. - Updated usbguard-daemon manual page - Permanent device specific rules managed by allowDevice, blockDevice and rejectDevice actions are now handled properly. Existing device rules are updated instead of just appending new rules to the policy. - usbguard-daemon.conf: changed the default configuration value of PresentControllerPolicy to keep - Changed the device hashing algorithm to SHA-256 - Switched hash value representation from hex to base64 ### Removed - Removed Quex related files - The "from Rule" Device class constructor was removed because it's use case is unclear and it wasn't used anywhere ## 0.5.10 - 2016-07-08 ### Changed - Changed versioning scheme to include a release number. Releases will be rolled out more often during a milestone (x.y -- currently 0.5) development. - Enhancements of the usbguard command-line interface. - Manual pages are now generated from their source (markdown) during the build process. - A default usbguard-daemon configuration file is now installed. ### Added - Merged usbguard-applet-qt (sub)project into usbguard. - Added a D-Bus bridge component which exposes a D-Bus interface to usbguard. ### Fixed - Fixed USB descriptor data parsing. Previously, many real-world cases of descriptors weren't parsed correctly because of a naive implementation of the parser. - Fixed systemd integration. - Fixed issues: #84, #83, #80, #79, #78, #77, #76, #75, #74, #73, #72, #71, #70, #69, #68, #56, #54, #53, #51, #50, #44. ## 0.4 - 2016-02-07 ### Changed - The daemon is now capable of dropping process capabilities and uses a seccomp based syscall allowlist. Options to enable these features were added to the usbguard-daemon command. - Devices connected at the start of the daemon are now recognized and the DevicePresent signal is sent for each of them. - The library API was extended with the Device and DeviceManager classes. - Implemented the usbguard CLI, see usbguard(1) for available commands. - Initial authorization policies can be now easily generated using the usbguard generate-policy command. - Extended the rule language with rule conditions. See usbguard-rules.conf(5) for details. - Moved logging code into the shared library. You can use static methods of the Logger class to configure logging behaviour. - Removed the bundled libsodium and libqb libraries. ### Added - New configuration options for setting the implicit policy target and how to handle the present devices are now available. ### Fixed - String values read from the device are now properly escaped and length limits on these values are enforced. - Fixed several bugs. - Resolved issues: #46, #45, #41, #40, #37, #32, #31, #28, #25, #24, #21, #16, #13, #9, #4 ### Removed - The device hashing procedure was altered and generates different hash values. If you are using the hash attribute in your rules, you'll have to update the values. - The bundled libsodium and libqb were removed. You'll have to compile and install them separately if your distribution doesn't provide them as packages. ## 0.3p3 - 2015-04-14 ### Changed - use AC_CHECK_HEADER instead of a pkg-config based check for json and spdlog - make check target available ## 0.3p2 - 2015-04-02 ### Changed - SHM permissions are set to uid of the client process and gid of the daemon with rw-rw---- mode (0660). - added --with-bundled-json and --with-bundled-spdlog configure options to enable/disable the usage of the bundled libraries ## 0.3p1 - 2015-04-10 ### Removed - removed bundled cppformat copylib ## 0.3 - 2015-04-09 ### Changed - Implemented a DAC based IPC access control ## Added - Ship man pages for usbguard-daemon, usbguard-daemon.conf and usbguard-rules.conf - Ship the LICENSE file ### Fixed - Fixed appending of permanent rules - Fixed distribution RPM spec file. Thanks to Petr Lautrbach and Ralf Corsepius for review. - Resolved issues: #18 #19 #13 ## 0.2 - 2015-04-03 ### Changed - Reworked device hashing. - Rule language changes - set operators - renamed "port" to "via-port" - added "with-interface" matching attribute - removed the "class" attribute - The IPCClient, ConfigFile, Rule and RuleSet classes are now shipped in a shared library. - Created abstract interface for OS specific USB device handling. - Changed default daemon config path to /etc/usbguard/usbguard-daemon.conf. - Implemented basic USB descriptor structure parsing and improved interface type handling - The IPC API was changed: - added new signal, DevicePresent, which signals that a device was already present at the start of the IPC session - the DeviceInserted and DevicePresent signals pass interface types that the device supports - the explicit string arguments of the signals are now passed as a map ### Added - Support for modifying permanent rules over the IPC interface. ### Fixed - Resolved issues: #1 #2 #5 #6 #10 #11 ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: Makefile.am ================================================ ## ## 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 ## Jiri Vymazal ## Attila Lakatos ## SUBDIRS=src/Tests/ ACLOCAL_AMFLAGS= -I m4 EXTRA_DIST =\ LICENSE \ usbguard-daemon.conf.in \ usbguard.service.in \ VERSION \ CHANGELOG.md \ src/astylerc \ src/test_filesystem.cpp \ scripts/usbguard-zsh-completion \ scripts/modeline.vim \ scripts/astyle.sh \ scripts/reformat-sources.sh \ scripts/usb-descriptor-collect.sh BUILT_SOURCES=\ src/build-config.h $(top_builddir)/src/build-config.h: $(top_builddir)/src/build-config.h.in $(SED) \ -e "s|[$$]{localstatedir}|${localstatedir}|g" \ -e "s|[$$]{exec_prefix}|${prefix}|g" \ -e "s|[$$]{datarootdir}|${datarootdir}|g" \ -e "s|[$$]{datadir}|${pkgdatadir}|g" \ -e "s|[$$]{sysconfdir}|${sysconfdir}|g" \ -e "s|[$$]{prefix}|${prefix}|g" \ -e "s|[$$]{PACKAGE_TARNAME}|${PACKAGE_TARNAME}|g" \ $^ > $@ || rm -f $@ DISTCLEANFILES=\ $(BUILT_SOURCES) AM_DISTCHECK_CONFIGURE_FLAGS=\ --enable-full-test-suite \ --with-bundled-catch \ --with-bundled-pegtl CLEANFILES= man_ADOC_FILES=\ doc/man/usbguard.1.adoc \ doc/man/usbguard-dbus.8.adoc \ doc/man/usbguard-daemon.8.adoc \ doc/man/usbguard-daemon.conf.5.adoc \ doc/man/usbguard-ldap.conf.5.adoc \ doc/man/usbguard-rules.conf.5.adoc man_ROFF_FILES=\ $(man_ADOC_FILES:.adoc=.roff) EXTRA_DIST+=\ $(man_ADOC_FILES) \ doc/man/example-allow-device.adoc \ doc/man/example-initial-policy.adoc \ doc/man/footer.adoc CLEANFILES+=\ $(man_ROFF_FILES) \ $(man_ROFF_FILES:.roff=) if DOCS_ENABLED BUILT_SOURCES+=\ $(man_ROFF_FILES) $(top_builddir)/%.roff: %.adoc $(MKDIR_P) $$(dirname $@) $(A2X) -v -f manpage $^ -D $(top_builddir)/$$(dirname $@) $(INSTALL) -m 644 $(top_builddir)/$(@:.roff=) $(top_builddir)/$@ endif install-data-hook: install-daemon-conf install-systemd-service install-data-dbus install-tmpfiles uninstall-hook: uninstall-daemon-conf uninstall-systemd-service uninstall-data-dbus uninstall-tmpfiles CLEANFILES+=\ $(top_builddir)/usbguard-daemon.conf usbguard-daemon.conf: $(top_builddir)/usbguard-daemon.conf.in $(SED) \ -e "s|%sysconfdir%|${sysconfdir}|g" \ -e "s|%localstatedir%|${localstatedir}|g" \ $^ > $@ || rm -f $@ usbguard_confdir= $(sysconfdir)/usbguard distuninstallcheck_listfiles= find . -type f ! -name rules.conf -print EXTRA_DIST+=usbguard-tmpfiles.conf install-tmpfiles: mkdir -p ${DESTDIR}$(prefix)/lib/tmpfiles.d/ $(INSTALL_DATA) -m 640 ${srcdir}/usbguard-tmpfiles.conf ${DESTDIR}$(prefix)/lib/tmpfiles.d/usbguard.conf uninstall-tmpfiles: rm ${DESTDIR}$(prefix)/lib/tmpfiles.d/usbguard.conf install-daemon-conf: $(top_builddir)/usbguard-daemon.conf $(MKDIR_P) $(DESTDIR)/$(usbguard_confdir) $(MKDIR_P) $(DESTDIR)/$(usbguard_confdir)/IPCAccessControl.d $(MKDIR_P) $(DESTDIR)/${localstatedir}/log/usbguard chmod 0700 $(DESTDIR)/${localstatedir}/log/usbguard $(INSTALL) -m 600 $(top_builddir)/usbguard-daemon.conf \ $(DESTDIR)/$(usbguard_confdir)/usbguard-daemon.conf if ! test -f "$(DESTDIR)/$(usbguard_confdir)/rules.conf"; then \ touch $(DESTDIR)/$(usbguard_confdir)/rules.conf && \ chmod 600 $(DESTDIR)/$(usbguard_confdir)/rules.conf; \ fi uninstall-daemon-conf: rm -f $(DESTDIR)/$(usbguard_confdir)/usbguard-daemon.conf if SYSTEMD_SUPPORT_ENABLED CLEANFILES+=\ $(top_builddir)/usbguard.service usbguard.service: $(top_srcdir)/usbguard.service.in $(SED) \ -e "s|%sbindir%|${sbindir}|" \ -e "s|%sysconfdir%|${sysconfdir}|" \ -e "s|%localstatedir%|${localstatedir}|" \ $^ > $@ || rm -f $@ install-systemd-service: $(top_builddir)/usbguard.service $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR) $(INSTALL) -m 644 $(top_builddir)/usbguard.service \ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/usbguard.service uninstall-systemd-service: rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/usbguard.service else install-systemd-service: uninstall-systemd-service: endif if DOCS_ENABLED man8_MANS=\ $(top_builddir)/doc/man/usbguard-daemon.8 man5_MANS=\ $(top_builddir)/doc/man/usbguard-daemon.conf.5 \ $(top_builddir)/doc/man/usbguard-rules.conf.5 man1_MANS=\ $(top_builddir)/doc/man/usbguard.1 else man8_MANS= man5_MANS= man1_MANS= endif AM_CPPFLAGS=\ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/Library/public pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libusbguard.pc lib_LTLIBRARIES=\ libusbguard.la 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 \ ${BOOST_CPPFLAGS} \ ${PTHREAD_CPPFLAGS} \ @qb_CFLAGS@ \ @protobuf_CFLAGS@ \ @crypto_CFLAGS@ \ @pegtl_CFLAGS@ \ @umockdev_CFLAGS@ libusbguard_la_LDFLAGS=\ -no-undefined \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ ${BOOST_LDFLAGS} libusbguard_la_LIBADD=\ @qb_LIBS@ \ @protobuf_LIBS@ \ @crypto_LIBS@ \ @pegtl_LIBS@ \ @atomic_LIBS@ \ @umockdev_LIBS@ \ ${BOOST_IOSTREAMS_LIB} \ ${PTHREAD_CFLAGS} \ ${PTHREAD_LIBS} EXTRA_DIST+=\ src/Library/IPC/Devices.proto \ src/Library/IPC/Exception.proto \ src/Library/IPC/Message.proto \ src/Library/IPC/Policy.proto \ src/Library/IPC/Rule.proto \ src/Library/IPC/Parameter.proto nodist_libusbguard_la_SOURCES=\ src/Library/IPC/Message.pb.cc \ src/Library/IPC/Message.pb.h \ src/Library/IPC/Rule.pb.cc \ src/Library/IPC/Rule.pb.h \ src/Library/IPC/Devices.pb.cc \ src/Library/IPC/Devices.pb.h \ src/Library/IPC/Exception.pb.cc \ src/Library/IPC/Exception.pb.h \ src/Library/IPC/Policy.pb.cc \ src/Library/IPC/Policy.pb.h \ src/Library/IPC/Parameter.pb.cc \ src/Library/IPC/Parameter.pb.h BUILT_SOURCES+=\ $(nodist_libusbguard_la_SOURCES) CLEANFILES+=\ $(nodist_libusbguard_la_SOURCES) libusbguard_la_SOURCES=\ src/Common/ByteOrder.hpp \ src/Common/FDInputStream.hpp \ src/Common/Thread.hpp \ src/Common/Utility.cpp \ src/Common/Utility.hpp \ src/Common/LDAPUtil.cpp \ src/Common/LDAPUtil.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/DeviceBase.cpp \ src/Library/DeviceBase.hpp \ src/Library/DeviceManagerBase.cpp \ src/Library/DeviceManagerBase.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/IPCClientPrivate.hpp \ src/Library/IPCPrivate.cpp \ src/Library/IPCPrivate.hpp \ src/Library/IPCServerPrivate.cpp \ src/Library/IPCServerPrivate.hpp \ src/Library/Init.cpp \ src/Library/KeyValueParserPrivate.cpp \ src/Library/KeyValueParserPrivate.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/RuleParser/Actions.hpp \ src/Library/RuleParser/Grammar.hpp \ src/Library/RulePrivate.cpp \ src/Library/RulePrivate.hpp \ src/Library/SysFSDevice.cpp \ src/Library/SysFSDevice.hpp \ src/Library/UEvent.cpp \ src/Library/UEvent.hpp \ src/Library/UEventDeviceManager.cpp \ src/Library/UEventDeviceManager.hpp \ src/Library/UEventParser.cpp \ src/Library/UEventParser.hpp \ src/Library/UMockdevDeviceManager.cpp \ src/Library/UMockdevDeviceManager.hpp \ src/Library/UMockdevDeviceDefinition.cpp \ src/Library/UMockdevDeviceDefinition.hpp \ src/Library/Utility.cpp \ src/Library/Utility.hpp \ src/Library/public/usbguard/Audit.cpp \ 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/KeyValueParser.cpp \ src/Library/public/usbguard/Logger.cpp \ src/Library/public/usbguard/MemoryRuleSet.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/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/KeyValueParser.hpp \ src/Library/public/usbguard/Logger.hpp \ src/Library/public/usbguard/MemoryRuleSet.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 #``` # error: no previous declaration for 'void usbguard::IPC::protobuf_Message_2eproto::AddDescriptorImpl()' [-Werror=missing-declarations] # void AddDescriptorImpl() { # ^~~~~~~~~~~~~~~~~ #``` %.pb.lo : CXXFLAGS += -Wno-missing-declarations %.pb.cc %.pb.h: %.proto $(MKDIR_P) $(top_builddir)/src/Library/IPC @PROTOC@ --cpp_out=$(top_builddir)/src/Library/IPC --proto_path=$(top_srcdir)/src/Library/IPC "$<" sed -i -e '1i#ifndef __clang_analyzer__' -e '$$a#endif' "$@" sbin_PROGRAMS=\ usbguard-daemon usbguard_daemon_SOURCES=\ src/Daemon/Daemon.cpp \ src/Daemon/Daemon.hpp \ src/Daemon/main.cpp \ src/Daemon/FileRuleSet.cpp \ src/Daemon/FileRuleSet.hpp \ src/Daemon/LDAPHandler.cpp \ src/Daemon/LDAPHandler.hpp \ src/Daemon/LDAPRuleSet.cpp \ src/Daemon/LDAPRuleSet.hpp \ src/Daemon/NSHandler.cpp \ src/Daemon/NSHandler.hpp \ src/Daemon/RuleSetFactory.cpp \ src/Daemon/RuleSetFactory.hpp \ src/Daemon/Seccomp.c \ src/Daemon/Seccomp.h \ src/Common/Utility.hpp \ src/Common/Utility.cpp \ src/Daemon/FileAuditBackend.hpp \ src/Daemon/FileAuditBackend.cpp \ src/Daemon/LinuxAuditBackend.hpp \ src/Daemon/LinuxAuditBackend.cpp usbguard_daemon_CXXFLAGS=\ $(PTHREAD_CFLAGS) usbguard_daemon_CPPFLAGS=\ -fPIE \ $(AM_CPPFLAGS) \ @ldap_CFLAGS@ \ @seccomp_CFLAGS@ \ @libcapng_CFLAGS@ \ @audit_CFLAGS@ usbguard_daemon_LDADD=\ $(top_builddir)/libusbguard.la \ @ldap_LIBS@ \ @seccomp_LIBS@ \ @libcapng_LIBS@ \ @audit_LIBS@ \ $(PTHREAD_LIBS) EXTRA_DIST +=\ README.adoc \ src/ThirdParty/Catch \ src/ThirdParty/PEGTL bin_PROGRAMS=\ usbguard \ usbguard-rule-parser usbguard_SOURCES=\ src/CLI/usbguard.cpp \ src/CLI/usbguard.hpp \ src/CLI/usbguard-list-devices.hpp \ src/CLI/usbguard-list-devices.cpp \ src/CLI/usbguard-allow-device.hpp \ src/CLI/usbguard-allow-device.cpp \ src/CLI/usbguard-block-device.hpp \ src/CLI/usbguard-block-device.cpp \ src/CLI/usbguard-reject-device.hpp \ src/CLI/usbguard-reject-device.cpp \ src/CLI/usbguard-apply-device-policy.hpp \ src/CLI/usbguard-apply-device-policy.cpp \ src/CLI/usbguard-list-rules.hpp \ src/CLI/usbguard-list-rules.cpp \ src/CLI/usbguard-append-rule.hpp \ src/CLI/usbguard-append-rule.cpp \ src/CLI/usbguard-remove-rule.hpp \ src/CLI/usbguard-remove-rule.cpp \ src/CLI/usbguard-generate-policy.cpp \ src/CLI/usbguard-generate-policy.hpp \ src/CLI/usbguard-watch.hpp \ src/CLI/usbguard-watch.cpp \ src/CLI/IPCSignalWatcher.hpp \ src/CLI/IPCSignalWatcher.cpp \ src/CLI/PolicyGenerator.hpp \ src/CLI/PolicyGenerator.cpp \ src/CLI/usbguard-read-descriptor.hpp \ src/CLI/usbguard-read-descriptor.cpp \ src/CLI/usbguard-set-parameter.hpp \ src/CLI/usbguard-set-parameter.cpp \ src/CLI/usbguard-get-parameter.hpp \ src/CLI/usbguard-get-parameter.cpp \ src/CLI/usbguard-add-user.cpp \ src/CLI/usbguard-add-user.hpp \ src/CLI/usbguard-remove-user.cpp \ src/CLI/usbguard-remove-user.hpp \ src/CLI/usbguard-print-version.cpp \ src/CLI/usbguard-print-version.hpp usbguard_CXXFLAGS=\ $(PTHREAD_CFLAGS) usbguard_CPPFLAGS=\ -fPIE \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/CLI usbguard_LDADD=\ $(top_builddir)/libusbguard.la \ ${PTHREAD_LIBS} if ENABLE_BASH_COMPLETION bashcompletiondir = $(BASH_COMPLETION_DIR) dist_bashcompletion_DATA = $(top_srcdir)/scripts/bash_completion/usbguard endif usbguard_rule_parser_SOURCES=\ src/CLI/usbguard-rule-parser.cpp usbguard_rule_parser_CPPFLAGS=\ -fPIE \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/CLI usbguard_rule_parser_LDADD=\ $(top_builddir)/libusbguard.la # # DBus Bridge # if DBUS_ENABLED sbin_PROGRAMS+= usbguard-dbus if DOCS_ENABLED man8_MANS+=\ $(top_builddir)/doc/man/usbguard-dbus.8 endif BUILT_SOURCES+=\ src/DBus/DBusInterface.xml.cstr \ src/DBus/org.usbguard1.service \ src/DBus/usbguard-dbus.service EXTRA_DIST+=\ src/DBus/org.usbguard1.conf \ src/DBus/org.usbguard1.service.in \ src/DBus/usbguard-dbus.service.in \ src/DBus/org.usbguard1.policy \ src/DBus/DBusInterface.xml CLEANFILES+=\ $(top_builddir)/src/DBus/org.usbguard1.service \ $(top_builddir)/src/DBus/usbguard-dbus.service \ $(top_builddir)/src/DBus/DBusInterface.xml.cstr usbguard_dbus_SOURCES=\ src/DBus/gdbus-server.cpp \ src/DBus/DBusBridge.cpp \ src/DBus/DBusBridge.hpp usbguard_dbus_CPPFLAGS=\ -fPIE \ $(AM_CPPFLAGS) \ -I$(top_builddir)/src/DBus \ @dbus_CFLAGS@ usbguard_dbus_LDADD=\ $(top_builddir)/libusbguard.la \ @dbus_LIBS@ %.xml: xmllint "$(top_srcdir)/$@" > /dev/null %.xml.cstr: %.xml XMLLINT_INDENT="" xmllint --noblanks --format "$<" |\ sed -n -e '// d; s|\"|\\"|g; s|.*|"&"|; p' > "$(top_builddir)/$@" %.service: %.service.in sed -e "s|%{sbindir}%|$(sbindir)|" "$<" > "$(top_builddir)/$@" install-data-dbus: $(top_builddir)/src/DBus/org.usbguard1.service install-polkit-policy install-systemd-dbus-service $(MKDIR_P) $(DESTDIR)$(DBUS_SERVICES_DIR) && \ $(INSTALL_DATA) $(top_builddir)/src/DBus/org.usbguard1.service $(DESTDIR)$(DBUS_SERVICES_DIR) $(MKDIR_P) $(DESTDIR)$(DBUS_BUSCONFIG_DIR) && \ $(INSTALL_DATA) $(top_srcdir)/src/DBus/org.usbguard1.conf $(DESTDIR)$(DBUS_BUSCONFIG_DIR) uninstall-data-dbus: uninstall-polkit-policy uninstall-systemd-dbus-service rm -f $(DESTDIR)$(DBUS_SERVICES_DIR)/org.usbguard1.service -rmdir $(DESTDIR)$(DBUS_SERVICES_DIR) rm -f $(DESTDIR)$(DBUS_BUSCONFIG_DIR)/org.usbguard1.conf -rmdir $(DESTDIR)$(DBUS_BUSCONFIG_DIR) dbus-docs: $(top_srcdir)/src/DBus/DBusInterface.xml # # Copy the input files to builddir because gdbus-codegen # doesn't provide an option to store the output files somewhere # else than in the directory where the input files are. And we # don't want to create files in the srcdir when building. # $(MKDIR_P) "$(top_builddir)/src/DBus" cp "$<" "$(top_builddir)/src/DBus/" $(GDBUS_CODEGEN) --interface-prefix org.usbguard --generate-docbook=docbook \ "$(top_builddir)/src/DBus/DBusInterface.xml" for docbook in $(top_builddir)/docbook-org.usbguard.*.xml; do \ $(XSLTPROC) -o "$$(basename -s .xml $$docbook).html" \ "$(top_srcdir)/src/ThirdParty/xsl-stylesheets/xhtml-1_1/docbook.xsl" \ "$(top_builddir)/$$docbook"; \ done if POLICYKIT_ENABLED install-polkit-policy: $(MKDIR_P) $(DESTDIR)$(POLKIT_POLICY_DIR) && \ $(INSTALL_DATA) $(top_srcdir)/src/DBus/org.usbguard1.policy $(DESTDIR)$(POLKIT_POLICY_DIR) uninstall-polkit-policy: rm -f $(DESTDIR)$(POLKIT_POLICY_DIR)/org.usbguard1.policy -rmdir $(DESTDIR)$(POLKIT_POLICY_DIR) else install-polkit-policy: uninstall-polkit-policy: endif if SYSTEMD_SUPPORT_ENABLED install-systemd-dbus-service: $(top_builddir)/src/DBus/usbguard-dbus.service $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR) && \ $(INSTALL_DATA) $(top_builddir)/src/DBus/usbguard-dbus.service $(DESTDIR)$(SYSTEMD_UNIT_DIR) uninstall-systemd-dbus-service: rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/usbguard-dbus.service -rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) else install-systemd-dbus-service: uninstall-systemd-dbus-service: endif else install-data-dbus: uninstall-data-dbus: endif #DBUS_ENABLED $(DIST_ARCHIVES): test -f "$@" || $(MAKE) dist release-files: $(DIST_ARCHIVES) $(eval RELEASE_DIR:="release.$(PACKAGE)-$(VERSION)") $(eval GPG:=$(shell test -n "$$QUBES_GPG_DOMAIN" && echo qubes-gpg-client-wrapper || echo gpg2)) $(MKDIR_P) $(RELEASE_DIR) cp $(DIST_ARCHIVES) $(RELEASE_DIR) cd $(RELEASE_DIR) && $(GPG) -b -a -o - $(DIST_ARCHIVES) > $(DIST_ARCHIVES).sig cd $(RELEASE_DIR) && openssl sha256 $(DIST_ARCHIVES) > $(DIST_ARCHIVES).sum analyze-clang: $(eval ANALYSIS_ROOT:=$(shell mktemp -d -t usbguard-analyze-clang.XXXXXX)) $(eval JOBS:=$(shell grep -c '^processor' /proc/cpuinfo 2> /dev/null || echo 1)) cd "$(ANALYSIS_ROOT)" && scan-build $(abs_top_srcdir)/configure $(ANALYZE_CONFIGURE_ARGS) cd "$(ANALYSIS_ROOT)" && scan-build \ --status-bugs -maxloop 8 -disable-checker deadcode.DeadStores -o "$(abs_top_builddir)" \ make -j$(JOBS) rm -rf "$(ANALYSIS_ROOT)" # # overriding 'check' target to enable "make check" to perform build as well # check: all $(MAKE) $(AM_MAKEFLAGS) check-recursive ================================================ FILE: README.adoc ================================================ USBGuard ======== :toc: [.clearfix] -- [.left] image::https://travis-ci.com/USBGuard/usbguard.svg?branch=master[Travis CI, link=https://travis-ci.com/USBGuard/usbguard] [.left] image::https://coveralls.io/repos/github/USBGuard/usbguard/badge.svg[Coverage, link=https://coveralls.io/github/USBGuard/usbguard] [.left] image::https://img.shields.io/github/license/USBGuard/usbguard.svg[License, link=https://github.com/USBGuard/usbguard/#license] -- == About USBGuard is a software framework for implementing USB device authorization policies (what kind of USB devices are authorized) as well as method of use policies (how a USB device may interact with the system). Simply put, it is a USB device allowlisting tool. == Documentation * User Guide (TBA) * Manual Pages ** <> ** <> ** <> ** <> ** <> == Compilation & Installation WARNING: *Prior to starting the USBGuard daemon (or service) for the first time* (but after installation) we need to generate a rules file for USBGuard so that the currently attached USB devices (in particular mouse and keyboard) keep working so that you will not **get locked out of your system**. More on that below at <>. To compile the source code, you will require at least C{plus}{plus}17. + If you are compiling sources from a release tarball, you'll need the development files for: * https://github.com/ClusterLabs/libqb[libqb] - used for local UNIX socket based IPC * https://github.com/google/protobuf[protobuf] - used for IPC message (de)serialization * https://download.libsodium.org[libsodium] or https://www.gnupg.org/software/libgcrypt[libgcrypt] - used for hashing * https://asciidoc.org[asciidoc (a2x)] - needed to generate documentation Optionally, you may want to install: * https://github.com/seccomp/libseccomp[libseccomp] - used to implement a syscall allowlist * https://people.redhat.com/sgrubb/libcap-ng/[libcap-ng] - used to drop process capabilities If you are on a Debian based GNU/Linux distribution like Ubuntu 21.10, installation of all build dependencies would be something like this: $ sudo apt update && \ sudo apt install --no-install-recommends -V \ asciidoc autoconf automake bash-completion build-essential catch2 \ docbook-xml docbook-xsl git ldap-utils libaudit-dev libcap-ng-dev \ libdbus-glib-1-dev libldap-dev libpolkit-gobject-1-dev libprotobuf-dev \ libqb-dev libseccomp-dev libsodium-dev libtool libxml2-utils \ libumockdev-dev pkg-config protobuf-compiler sudo tao-pegtl-dev xsltproc And then do: $ ./configure # for arguments of interest see below $ make $ make check # if you would like to run the test suite $ sudo make install Configure arguments that deserve explicit mentioning (quoting `./configure --help` output): --enable-systemd install the systemd service unit file (default=no) --with-crypto-library Select crypto backend library. Supported values: sodium, gcrypt, openssl. --with-bundled-catch Build using the bundled Catch library --with-bundled-pegtl Build using the bundled PEGTL library --with-ldap Build USBGuard with ldap support If you want to compile the sources in a cloned repository, you'll have to run the `./autogen.sh` script. It will fetch the sources (via git submodules) of https://github.com/taocpp/PEGTL/[PEGTL] and https://github.com/philsquared/Catch[Catch]. The script will then initialize the autotools based build system, e.g. generate the `./configure` script. == Before the First Start *Prior to starting the USBGuard daemon (or service) for the first time* (but after installation) we need to generate a rules file for USBGuard so that the currently attached USB devices (in particular mouse and keyboard) keep working so that you will not **get locked out of your system**. A rules file can be generated like this: $ sudo sh -c 'usbguard generate-policy > /etc/usbguard/rules.conf' After that, you can safely start service `usbguard`: $ sudo systemctl start usbguard.service And you can make systemd start the service every time your boot your machine: $ sudo systemctl enable usbguard.service == License Copyright (C) 2015-2019 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 . ================================================ FILE: RELEASE_PROCESS.md ================================================ # USBGuard Release Process 1. Clean up any artifacts from your local repository. ``` $ git clean -xfd ``` 2. Setup build directory. ``` $ ./autogen.sh $ mkdir build && cd build $ ../configure --enable-full-test-suite --with-crypto-library=gcrypt --with-ldap $ make ``` 3. Run the test suite. All the tests must pass. ``` $ sudo make check ``` 4. Compare previous lib version with current. ``` $ abidiff --stat ../abi-ref/libusbguard.so.abi .libs/libusbguard.so $ cd .. ``` 5. Update the lib version (CURRENT, REVISION, AGE) in `configure.ac` according to comments. 6. Update ABI reference. ``` $ abidw --out-file abi-ref/libusbguard.so.abi build/.libs/libusbguard.so $ sudo rm -rf build ``` 7. Update the `VERSION` file and `CHANGELOG.md`. Commit your changes. 8. Build the final release tarball. ``` $ ./autogen.sh $ mkdir build; cd build $ ../configure --with-crypto-library=gcrypt $ make dist ``` 9. Tag the release with a signed tag. ``` $ git tag -s -m "usbguard-0.x.y" usbguard-0.x.y $ git push origin usbguard-0.x.x ``` 10. Hash and sign the release. ``` $ sha256sum usbguard-0.x.y.tar.gz > usbguard-0.x.y.tar.gz.sum $ gpg --armor --detach-sign usbguard-0.x.y.tar.gz $ gpg --clearsign usbguard-0.x.y.tar.gz.sum ``` 11. Create a new GitHub release using the associated tag; add the relevant section from CHANGELOG.md. Upload: * usbguard-0.x.y.tar.gz * usbguard-0.x.y.tar.gz.asc * usbguard-0.x.y.tar.gz.sum * usbguard-0.x.y.tar.gz.sum.asc ================================================ FILE: VERSION ================================================ 1.1.4 ================================================ FILE: abi-ref/libusbguard.so.abi ================================================ ================================================ FILE: autogen.sh ================================================ #!/bin/sh ## ## 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 ## set -x -e git submodule update --init mkdir -p ./m4 autoreconf -i -s --no-recursive ./ ================================================ FILE: configure.ac ================================================ AC_PREREQ([2.69]) AC_INIT([usbguard], m4_esyscmd_s([cat VERSION]), [usbguard@usbguard.org]) AC_CONFIG_SRCDIR([src/]) AC_CONFIG_HEADERS([src/build-config.h.in]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([config]) AM_INIT_AUTOMAKE([subdir-objects foreign tar-pax]) # If automake supports "silent rules", enable them by default m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # # Compiler flags # EXTERNAL_CXXFLAGS="$CXXFLAGS" EXTERNAL_CFLAGS="$CFLAGS" EXTERNAL_CPPFLAGS="$CPPFLAGS" COMMON_WARNING_FLAGS=" -pedantic" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wno-unknown-pragmas" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wall" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wextra" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wformat=2" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wredundant-decls" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wcast-align" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wmissing-declarations" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wmissing-include-dirs" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wmissing-format-attribute" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wswitch-enum" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wswitch-default" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Winvalid-pch" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wformat-nonliteral" COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wno-deprecated-register" #COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -flto -Wodr" # # Workaround for older compilers warning about { } # not initializing all struct fields. # COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wno-missing-field-initializers" # # Don't warn about implicit fallthrough # # TODO: Use [[fallthrough]] C++ attribute specifier with # newer compiler versions. # AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], [COMMON_WARNING_FLAGS="${COMMON_WARNING_FLAGS} -Wno-implicit-fallthrough"], [], []) # # Final project CXXFLAGS are set after configure checks. # CXXFLAGS="-std=c++17 $EXTERNAL_CXXFLAGS" CFLAGS="-std=c99 $EXTERNAL_CFLAGS" CPPFLAGS="-DHAVE_BUILD_CONFIG_H $EXTERNAL_CPPFLAGS" # # Additional CXXFLAGS used when --enable-debug-build is used # CXXFLAGS_DEBUG_ENABLED="-g -O0" # # Additional CXXFLAGS used when --disable-debug-build is used # and when --enable-debug-build is # # Don't add -DNDEBUG here. It's added to the generated config.h # header file. # CXXFLAGS_DEBUG_DISABLED="" # Libtool Versioning # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details # # The most recent interface number. # # Increment if the interface has additions, changes or removals. # LT_CURRENT=1 # # The implementation number of the current interface. # # Increment if library source code changed at all. # Set to 0 if you increment CURRENT. # LT_REVISION=1 # # The difference between the newest and oldest interfaces # that the library implements. # # Increment if any interfaces have been added. # Set to 0 if any interfaces have been changed or removed. # Removal has precedence over adding, so set to 0 if both happened. # LT_AGE=0 AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) AC_ARG_ENABLE([coverage], [AS_HELP_STRING([--enable-coverage], [enable instrumented compilation for code coverage testing (default=no)])], [case "${enableval}" in yes) coverage=yes ;; no) coverage=no ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-coverage]) ;; esac], [coverage=no]) if test "x$coverage" = xyes; then CXXFLAGS="$CXXFLAGS --coverage" CFLAGS="$CFLAGS --coverage" fi AC_ARG_ENABLE([werror], [AS_HELP_STRING([--enable-werror], [treat compiler warnings as errors (default=no)])], [case "${enableval}" in yes) werror=yes ;; no) werror=no ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-werror]) ;; esac], [werror=no]) if test "x$werror" = xyes; then COMMON_WARNING_FLAGS=" -Werror $COMMON_WARNING_FLAGS" fi # # Checks for programs. # AC_PROG_CXX AC_PROG_CC_C99 AC_PROG_INSTALL AC_PROG_MAKE_SET LT_INIT # Check if libatomic is available, might be required for emulating # atomic intrinsics on some platforms. # AC_CHECK_LIB([atomic], [__atomic_add_fetch_8], [ __saved_LIBS="$LIBS" LIBS="$LIBS -Wl,--push-state,--as-needed,-latomic,--pop-state" AC_LINK_IFELSE([AC_LANG_PROGRAM()], [atomic_LIBS="-Wl,--push-state,--as-needed,-latomic,--pop-state"], [atomic_LIBS="-latomic"] ) LIBS="$__saved_LIBS" ], [atomic_LIBS=""]) AC_SUBST([atomic_LIBS]) # GNU (or just POSIX) basename(3) function? AC_MSG_CHECKING([for basename function]) AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #define _GNU_SOURCE #include int main(int argc, char ** argv) { ::basename(*argv); return 0; } ])], [ have_gnu_basename=yes AC_MSG_RESULT([GNU]) ], [ have_gnu_basename=no AC_MSG_RESULT([POSIX]) ]) AC_LANG_POP() AS_IF([test "x${have_gnu_basename}" = xyes], [ AC_DEFINE([HAVE_GNU_BASENAME], [1], [Wether the GNU version of function basename(3) is available (or just the POSIX one).]) ], []) # GNU or XSI strerror_r(3) function? AC_MSG_CHECKING([for strerror_r function]) AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #undef _POSIX_C_SOURCE #define _GNU_SOURCE #include int main(int argc, char ** argv) { char * res = ::strerror_r(0, 0, 0); return 0; } ])], [ have_gnu_strerror_r=yes AC_MSG_RESULT([GNU]) ], [ have_gnu_strerror_r=no AC_MSG_RESULT([XSI]) ]) AC_LANG_POP() AS_IF([test "x${have_gnu_strerror_r}" = xyes], [ AC_DEFINE([HAVE_GNU_STRERROR_R], [1], [Wether the GNU version of function strerror_r(3) is available (or just the XSI one).]) ], []) # # Checks for required libraries. # AX_PTHREAD AC_MSG_CHECKING([for NETLINK_KOBJECT_UEVENT definition]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #include int main(void) { return NETLINK_KOBJECT_UEVENT; } ]])], [have_uevent=yes], [have_uevent=no]) if test "x$have_uevent" = xyes; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_UEVENT], [1], [UEVENT netlink socket support]) else AC_MSG_RESULT([no]) fi # # qb library # PKG_CHECK_MODULES([qb], [libqb >= 0.16.0], [AC_DEFINE([HAVE_LIBQB], [1], [libqb API available]) libqb_summary="system-wide; $qb_CFLAGS $qb_LIBS"], [AC_MSG_FAILURE([libqb development files not found!])] ) # # sodium library # PKG_CHECK_MODULES([sodium], [libsodium >= 0.4.5], [AC_DEFINE([HAVE_LIBSODIUM], [1], [libsodium API available]) libsodium_summary="system-wide; $sodium_CFLAGS $sodium_LIBS"] libsodium_available=yes, [] ) # # libcrypto library (OpenSSL) # PKG_CHECK_MODULES([libcrypto], [libcrypto >= 1.0.0], [AC_DEFINE([HAVE_LIBCRYPTO], [1], [libcrypto API available]) libcrypto_summary="system-wide; $libcrypto_CFLAGS $libcrypto_LIBS"] libcrypto_available=yes, [] ) # # gcrypt library # AM_PATH_LIBGCRYPT([1.5.0], [AC_DEFINE([HAVE_LIBGCRYPT], [1], [libgcrypt API available]) gcrypt_CFLAGS="$LIBGCRYPT_CFLAGS" gcrypt_LIBS="$LIBGCRYPT_LIBS" libgcrypt_summary="system-wide; $gcrypt_CFLAGS $gcrypt_LIBS" libgcrypt_available=yes], [] ) # # --with-crypto-library= # # Supported selectors: # # sodium ... libsodium # gcrypt ... libgcrypt # openssl ... libcrypto # AC_ARG_WITH([crypto-library], AS_HELP_STRING([--with-crypto-library], [Select crypto backend library. Supported values: sodium, gcrypt, openssl.]), [with_crypto_library=$withval], [with_crypto_library=sodium]) case "$with_crypto_library" in openssl) if test "x$libcrypto_available" = xyes; then crypto_CFLAGS="$libcrypto_CFLAGS" crypto_LIBS="$libcrypto_LIBS" crypto_summary="$libcrypto_summary" AC_DEFINE([USBGUARD_USE_OPENSSL], [1], [Use openssl as crypto backend]) else AC_MSG_ERROR([The selected crypto backend library is not available.]) fi ;; sodium) if test "x$libsodium_available" = xyes; then crypto_CFLAGS="$sodium_CFLAGS" crypto_LIBS="$sodium_LIBS" crypto_summary="$libsodium_summary" AC_DEFINE([USBGUARD_USE_LIBSODIUM], [1], [Use libsodium as crypto backend]) else AC_MSG_ERROR([The selected crypto backend library is not available.]) fi ;; gcrypt) if test "x$libgcrypt_available" = xyes; then crypto_CFLAGS="$gcrypt_CFLAGS" crypto_LIBS="$gcrypt_LIBS" crypto_summary="$libgcrypt_summary" AC_DEFINE([USBGUARD_USE_LIBGCRYPT], [1], [Use libsodium as crypto backend]) else AC_MSG_ERROR([The selected crypto backend library is not available.]) fi ;; *) AC_MSG_FAILURE([Invalid crypto library selector. Supported selectors: sodium, gcrypt, openssl]) esac AC_SUBST([crypto_CFLAGS]) AC_SUBST([crypto_LIBS]) # # Check for optional libraries # AC_ARG_ENABLE([audit], [AS_HELP_STRING([--enable-audit], [Enables Linux Audit support if available (default=yes)])], [use_audit=$enableval], [use_audit=yes]) if test "x$use_audit" = xyes; then 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"] ) else libaudit_summary="not enabled" fi AC_ARG_ENABLE([seccomp], [AS_HELP_STRING([--enable-seccomp], [Enables Seccomp support if available (default=yes)])], [use_seccomp=$enableval], [use_seccomp=yes]) if test "x$use_seccomp" = xyes; then PKG_CHECK_MODULES([seccomp], [libseccomp >= 2.0.0], [AC_DEFINE([HAVE_SECCOMP], [1], [seccomp API usable]) libseccomp_summary="system-wide; $seccomp_LIBS"], [AC_MSG_NOTICE([libseccomp development files not found! Seccomp support will be turned OFF]) libseccomp_summary="not found"] ) else libseccomp_summary="not enabled" fi AC_ARG_ENABLE([libcapng], [AS_HELP_STRING([--enable-libcapng], [Enables POSIX 1003.1e capability support if available (default=yes)])], [use_libcapng=$enableval], [use_libcapng=yes]) if test "x$use_libcapng" = xyes; then PKG_CHECK_MODULES([libcapng], [libcap-ng >= 0.7.0], [AC_DEFINE([HAVE_LIBCAPNG], [1], [cap-ng API usable]) libcap_ng_summary="system-wide; $libcapng_LIBS"], [AC_MSG_NOTICE([libcap-ng development files not found! Support for POSIX 1003.1e capabilities will be turned OFF]) libcap_ng_summary="not found"] ) else libcap_ng_summary="not enabled" fi AC_ARG_ENABLE([umockdev], [AS_HELP_STRING([--enable-umockdev], [Enables umockdev support if available (default=yes)])], [use_umockdev=$enableval], [use_umockdev=yes]) if test "x$use_umockdev" = xyes; then PKG_CHECK_MODULES([umockdev], [umockdev-1.0 >= 0.8.0], [AC_DEFINE([HAVE_UMOCKDEV], [1], [umockdev API usable]) umockdev_summary="system-wide; $umockdev_LIBS" umockdev_available=yes], [AC_MSG_NOTICE([umockdev development files not found! umockdev device manager won't be available]) umockdev_summary="not found"] ) else umockdev_summary="not enabled" fi PKG_CHECK_MODULES([protobuf], [protobuf >= 2.5.0], [protobuf_summary="system-wide; $protobuf_CFLAGS $protobuf_LIBS"], [AC_MSG_ERROR([Required protobuf development files not found!])] ) AC_CHECK_PROGS(PROTOC, [protoc]) if test -z "$PROTOC"; then AC_MSG_ERROR(["Required protobuf compiler not found!"]) fi # # Catch C++ library # AC_ARG_ENABLE([catch], [AS_HELP_STRING([--enable-catch], [Enable Catch testing framework support (default=yes)])], [enable_catch=$enableval], [enable_catch=yes]) AC_ARG_WITH([bundled-catch], AS_HELP_STRING([--with-bundled-catch], [Build using the bundled Catch library]), [with_bundled_catch=$withval], [with_bundled_catch=no]) if test "x$enable_catch" = xyes; then if test "x$with_bundled_catch" = xyes; then catch_CFLAGS="-I\$(top_srcdir)/src/ThirdParty/Catch/single_include/catch2" catch_LIBS="" AC_MSG_NOTICE([Using bundled Catch library]) catch_summary="bundled; $catch_CFLAGS $catch_LIBS" else SAVE_CPPFLAGS=$CPPFLAGS CPPFLAGS="-std=c++17 $CPPFLAGS -I/usr/include/catch2" AC_LANG_PUSH([C++]) AC_CHECK_HEADER([catch_test_macros.hpp], [catch_CFLAGS="-I/usr/include/catch2 -DHAVE_CATCH2_V3" catch_LIBS="-lCatch2Main -lCatch2"], [AC_CHECK_HEADER([catch.hpp], [catch_CFLAGS="-I/usr/include/catch2" catch_LIBS=""], [AC_MSG_FAILURE(Catch2 not found or not usable. Re-run with --with-bundled-catch to use the bundled library.)] )]) AC_LANG_POP CPPFLAGS=$SAVE_CPPFLAGS catch_summary="system-wide; $catch_CFLAGS $catch_LIBS" fi else catch_CFLAGS="" catch_LIBS="" catch_summary="disabled; not checking for Catch2" fi AC_SUBST([catch_CFLAGS]) AC_SUBST([catch_LIBS]) # # stdc++fs (for PEGTL >=3 below, e.g. with GCC 8) # STDCXX_FS_LINKTEST_FILENAME="${srcdir}"/src/test_filesystem.cpp STDCXX_FS_LINKTEST_SOURCE="$(cat "${STDCXX_FS_LINKTEST_FILENAME}")" AC_LANG_PUSH([C++]) AC_MSG_CHECKING([whether we need to link to -lstdc++fs for PEGTL explicitly]) AC_LINK_IFELSE([AC_LANG_SOURCE([${STDCXX_FS_LINKTEST_SOURCE}])], [ AC_MSG_RESULT([no]) stdcxxfs_LIBS='' ], [ stdcxxfs_LIBS='-lstdc++fs' SAVE_LIBS=${LIBS} LIBS="${LIBS} ${stdcxxfs_LIBS}" AC_LINK_IFELSE([AC_LANG_SOURCE([${STDCXX_FS_LINKTEST_SOURCE}])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([ERROR]) AC_MSG_ERROR([Link test failed both with and without ${stdcxxfs_LIBS}; something is broken, please check file config.log for details.]) ]) LIBS=${SAVE_LIBS} ]) AC_LANG_POP() # # PEGTL C++ library # AC_ARG_WITH([bundled-pegtl], AS_HELP_STRING([--with-bundled-pegtl], [Build using the bundled PEGTL library]), [with_bundled_pegtl=$withval], [with_bundled_pegtl=no]) if test "x$with_bundled_pegtl" = xyes; then pegtl_CFLAGS="-I\$(top_srcdir)/src/ThirdParty/PEGTL/include" pegtl_AC_CFLAGS="-I$srcdir/src/ThirdParty/PEGTL/include" pegtl_LIBS="${stdcxxfs_LIBS}" AC_MSG_NOTICE([Using bundled PEGTL library]) pegtl_summary="bundled; $pegtl_CFLAGS $pegtl_LIBS" else pegtl_CFLAGS="" pegtl_AC_CFLAGS="" pegtl_LIBS="${stdcxxfs_LIBS}" pegtl_summary="system-wide; $pegtl_CFLAGS $pegtl_LIBS" fi AC_SUBST([pegtl_CFLAGS]) AC_SUBST([pegtl_AC_CFLAGS]) AC_SUBST([pegtl_LIBS]) SAVE_CPPFLAGS=$CPPFLAGS CPPFLAGS="-std=c++17 $CPPFLAGS $pegtl_AC_CFLAGS" AC_LANG_PUSH([C++]) AC_CHECK_HEADER([tao/pegtl.hpp], [AC_DEFINE([HAVE_TAO_PEGTL_HPP], [1], [PEGTL header file with .hpp extension is present])], [AC_MSG_FAILURE(PEGTL header file not found or not usable. Re-run with --with-bundled-pegtl to use the bundled library.)]) AC_LANG_POP CPPFLAGS=$SAVE_CPPFLAGS # # GDBus # AC_ARG_WITH([dbus], AS_HELP_STRING([--with-dbus], [Build the DBus Bridge service]), [], [with_dbus=yes]) if test "x$with_dbus" = xyes; then # # Check for required D-Bus modules # PKG_CHECK_MODULES([dbus], [dbus-1 gio-2.0 >= 2.46 polkit-gobject-1], [AC_DEFINE([HAVE_DBUS], [1], [Required GDBus API available]) dbus_summary="system-wide; $dbus_CFLAGS $dbus_LIBS"], [AC_MSG_FAILURE([Required D-Bus modules (dbus-1, gio-2.0, polkit-gobject-1) not found!])] ) # # Check for xmllint tool # AC_CHECK_PROGS(XMLLINT, [xmllint]) if test -z "$XMLLINT" ; then AC_MSG_FAILURE([The required xmllint tool is missing on your system. Make sure that xmllint is installed.]) fi # # Check for xsltproc tool # AC_CHECK_PROGS(XSLTPROC, [xsltproc]) if test -z "$XSLTPROC"; then AC_MSG_FAILURE([The required xsltproc tool is missing on your system. Make sure that xsltproc is installed.]) fi # # Check for gdbus-codegen tool # AC_CHECK_PROGS(GDBUS_CODEGEN, [gdbus-codegen]) if test -z "$GDBUS_CODEGEN"; then AC_MSG_FAILURE([The required gdbus-codegen tool is missing on your system. Make sure that gdbus-codegen is installed.]) fi dbus_services_dir=`$PKG_CONFIG dbus-1 --define-variable=datadir='${datadir}' --define-variable=prefix='${prefix}' --variable=system_bus_services_dir` if test "x$dbus_services_dir" = x; then AC_MSG_FAILURE([Cannot autodetect the D-Bus system services directory]) else # # Hack around expanded paths in system_bus_services_dir. Without this distcheck won't # work, because it uses ./configure --prefix=$somedir. The expanded path ignores this # prefix (and DESTDIR won't help here either) # case "$dbus_services_dir" in /usr/share/*|/usr/local/share/*) dbus_services_dir=$(echo "$dbus_services_dir" | sed -r 's,^(/usr/share|/usr/local/share),${datadir},') ;; /usr/*|/usr/local/*) dbus_services_dir=$(echo "$dbus_services_dir" | sed -r 's,^(/usr|/usr/local),${prefix},') ;; /*) dbus_services_dir='${prefix}'"$dbus_services_dir" ;; esac AC_SUBST(DBUS_SERVICES_DIR, $dbus_services_dir) fi dbus_data_dir=`$PKG_CONFIG dbus-1 --define-variable=datadir='${datadir}' --define-variable=prefix='${prefix}' --variable=datadir` if test "x$dbus_data_dir" = x; then AC_MSG_FAILURE([Cannot autodetect the D-Bus data directory]) else dbus_busconfig_dir="$dbus_data_dir/dbus-1/system.d" AC_SUBST(DBUS_BUSCONFIG_DIR, $dbus_busconfig_dir) fi else dbus_summary="None; building without DBus support" dbus_services_dir="-" dbus_busconfig_dir="-" fi # # PolicyKit # AC_ARG_WITH([polkit], AS_HELP_STRING([--with-polkit], [Install the PolicyKit configuration if D-Bus support is also enabled]), [], [with_polkit=yes]) if test "x$with_polkit" = xyes; then # # Check for required PolicyKit modules # PKG_CHECK_MODULES([polkit], [polkit-gobject-1], [AC_DEFINE([HAVE_POLKIT], [1], [Required PolicyKit modules available]) polkit_summary="system-wide; `$PKG_CONFIG polkit-gobject-1 --define-variable=prefix='${prefix}' --define-variable=datadir='${datadir}' --variable=policydir`"], [AC_MSG_FAILURE([Required PolicyKit modules (polkit-gobject-1) not found!])] ) polkit_policy_dir="`$PKG_CONFIG polkit-gobject-1 --define-variable=prefix='${prefix}' --define-variable=datadir='${datadir}' --variable=policydir`" if test "x$polkit_policy_dir" = x; then AC_MSG_FAILURE([Cannot autodetect the PolicyKit policy directory]) else AC_SUBST(POLKIT_POLICY_DIR, $polkit_policy_dir) fi else polkit_summary="None; building without PolicyKit support" polkit_policy_dir="-" fi # # LDAP # AC_ARG_WITH([ldap], AS_HELP_STRING([--with-ldap], [Build USBGuard with ldap support]), [], [with_ldap=no]) if test "x$with_ldap" = xyes; then # # Check for LDAP ldap.h # AC_CHECK_HEADER( [ldap.h], [ ldap_LIBS="-lldap" ldap_CFLAGS="" AC_DEFINE([HAVE_LDAP], [1], [ldap API available]) libldap_summary="system-wide; $ldap_CFLAGS $ldap_LIBS" ], [ ldap_LIBS="" ldap_CFLAGS="" AC_MSG_ERROR([Building with --with-ldap but ldap.h is not available]) libldap_summary="not found" ] ) else libldap_summary="None; building without LDAP support" fi AC_SUBST(ldap_LIBS) AC_SUBST(ldap_CFLAGS) # # AddressSanitizer # # Based on: https://github.com/machinezone/tcpkali/blob/15903a7692abecbd28899d44e822a6f894caa23c/configure.aci#L73 # # Enable Address Sanitizer, if supported by gcc (4.8+) or clang. # http://clang.llvm.org/docs/AddressSanitizer.html # https://code.google.com/p/address-sanitizer/wiki/HowToBuild # AC_ARG_ENABLE([asan], [AS_HELP_STRING([--enable-asan], [Enable Address Sanitizer])], [enable_asan=$enableval], [enable_asan=no]) if test "x$enable_asan" = xyes; then AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-faddress-sanitizer], [ASAN_FLAGS="$ASAN_FLAGS -faddress-sanitizer"], [enable_asan=no], []) if test "x$enable_asan" = xno; then AX_CHECK_COMPILE_FLAG([-fsanitize=address], [ASAN_FLAGS="$ASAN_FLAGS -fsanitize=address" enable_asan=yes], [enable_asan=no], []) if test "x$enable_asan" = xno; then AC_MSG_FAILURE([--enable-asan is given, but not supported on this platform. Check out https://code.google.com/p/address-sanitizer/wiki/HowToBuild]) fi fi # Keep error messages nice. Also consider: # export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer # export ASAN_OPTIONS=symbolize=1 AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [ASAN_FLAGS="$ASAN_FLAGS -fno-omit-frame-pointer"], [], []) AX_CHECK_COMPILE_FLAG([-static-libasan], [ASAN_FLAGS="$ASAN_FLAGS -static-libasan"], [], []) AC_LANG_POP fi # # Enable Thread Sanitizer, if supported by clang. # http://clang.llvm.org/docs/ThreadSanitizer.html # https://code.google.com/p/address-sanitizer/wiki/HowToBuild # AC_ARG_ENABLE([tsan], [AS_HELP_STRING([--enable-tsan], [Enable Thread Sanitizer])], [enable_tsan=$enableval], [enable_tsan=no]) if test "x$enable_tsan" = xyes; then if test "x$enable_asan" = xyes; then AC_MSG_FAILURE([Address Sanitizer (ASAN) and Thread Sanitizer (TSAN) are mutually exclusive]) fi AX_CHECK_COMPILE_FLAG([-fsanitize=thread], [TSAN_FLAGS="$TSAN_FLAGS -fsanitize=thread"], [enable_tsan=no], []) if test "x$enable_tsan" = xno; then AC_MSG_FAILURE([--enable-tsan is given, but not supported on this platform. Check out https://code.google.com/p/address-sanitizer/wiki/HowToBuild]) fi # Keep error messages nice. AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [TSAN_FLAGS="$TSAN_FLAGS -fno-omit-frame-pointer"], [], []) # -fsanitize=thread linking must be done with -pie or -shared # We can't do anything about this message in GCC; use clang. fi # # Check whether asciidoc (a2x) is present. # AC_CHECK_PROGS(A2X, [a2x]) if test -z "$A2X"; then AC_MSG_WARN([Unable to find documentation generator (asciidoc / a2x). Documentation will not be generated.]) fi # # Check whether the aspell utility is present. # # If aspell is not present, the test suite will skip spell # checking of documentation related files. # AC_CHECK_PROGS(ASPELL, [aspell]) if test -z "$ASPELL"; then AC_MSG_WARN([Unable to find the Aspell spell checker. The test suite will skip spell checking of documentation related files.]) fi # # Full test suite mode. # # 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([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]) if test "x$full_test_suite" = xyes; then if test "x$umockdev_available" != xyes; then AC_MSG_ERROR([umockdev is required to run the full test suite.]) fi fi # Checks for header files. AC_LANG_PUSH([C++]) AC_FUNC_ALLOCA AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.hi locale.h netdb.h stdint.h stdlib.h]) AC_CHECK_HEADERS([string.h sys/time.h syslog.h unistd.h wchar.h ext/stdio_filebuf.h]) # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL AC_C_INLINE AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UID_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_FORK AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([dup2 gettimeofday localtime_r memset mkdir regcomp setlocale strerror strstr]) AC_LANG_POP # ./configure script options AC_ARG_ENABLE([debug-build], [AS_HELP_STRING([--enable-debug-build], [enable debugging flags (default=no)])], [case "${enableval}" in yes) debug=yes ;; no) debug=no ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug-build]) ;; esac], [debug=no]) AC_ARG_ENABLE([systemd], [AS_HELP_STRING([--enable-systemd], [install the systemd service unit file (default=no)])], [case "${enableval}" in yes) systemd=yes ;; no) systemd=no ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-systemd]) ;; esac], [systemd=no]) AC_ARG_WITH([bash-completion-dir], AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Enable bash auto-completion. Uses pkgconfig if no path given. @<:@default=yes@:>@]), [], [with_bash_completion_dir=yes]) if test "x$with_bash_completion_dir" = "xyes"; then PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], [BASH_COMPLETION_DIR=$($PKG_CONFIG --variable=completionsdir bash-completion)], [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) else BASH_COMPLETION_DIR="$with_bash_completion_dir" fi if test "x$debug" = xyes; then CXXFLAGS="$CXXFLAGS $CXXFLAGS_DEBUG_ENABLED" CFLAGS="$CFLAGS $CFLAGS_DEBUG_ENABLED" else CXXFLAGS="$CXXFLAGS $CXXFLAGS_DEBUG_DISABLED" CFLAGS="$CFLAGS $CFLAGS_DEBUG_DISABLED" AC_DEFINE([NDEBUG], [1], [Debug build disabled]) AC_DEFINE([QUEX_OPTION_ASSERTS_DISABLED], [1], [Disable asserts in the Quex generated lexer]) fi if test "x$enable_asan" = xyes; then CXXFLAGS="$CXXFLAGS $ASAN_FLAGS" CFLAGS="$CFLAGS $ASAN_FLAGS" LDFLAGS="$LDFLAGS $ASAN_FLAGS" AC_DEFINE([ASAN_ENABLED], [1], [Address Sanitizer is enabled]) fi if test "x$enable_tsan" = xyes; then CXXFLAGS="$CXXFLAGS $TSAN_FLAGS" CFLAGS="$CFLAGS $TSAN_FLAGS" LDFLAGS="$LDFLAGS $TSAN_FLAGS" AC_DEFINE([TSAN_ENABLED], [1], [Thread Sanitizer is enabled]) fi if test "x$systemd" = xyes; then systemd_unit_dir="`$PKG_CONFIG systemd --variable=systemdsystemunitdir`" if test "x$systemd_unit_dir" = x; then AC_MSG_FAILURE([Cannot detect the systemd system unit dir]) fi AC_SUBST(SYSTEMD_UNIT_DIR, $systemd_unit_dir) AC_DEFINE([SYSTEMD_SUPPORT_ENABLED], [1], [Enable systemd support int the project]) else systemd_unit_dir="-" fi AC_SUBST([ANALYZE_CONFIGURE_ARGS], $ac_configure_args) AC_SUBST([BASH_COMPLETION_DIR]) AM_CONDITIONAL([ENABLE_BASH_COMPLETION], [test "x$with_bash_completion_dir" != "xno"]) AM_CONDITIONAL([SYSTEMD_SUPPORT_ENABLED], [test "x$systemd" = xyes ]) AM_CONDITIONAL([DBUS_ENABLED], [test "x$with_dbus" = xyes ]) AM_CONDITIONAL([DOCS_ENABLED], [! test -z "$A2X" ]) AM_CONDITIONAL([POLICYKIT_ENABLED], [test "x$with_polkit" = xyes]) AM_CONDITIONAL([FULL_TEST_SUITE_ENABLED], [test "x$full_test_suite" = xyes]) AM_CONDITIONAL([WITH_LDAP], [test "x$with_ldap" = xyes]) AM_CONDITIONAL([BASH_COMPLETION_ENABLED], [test "x$bash_completion" != xno]) AM_CONDITIONAL([CATCH_ENABLED], [test "x$enable_catch" = xyes ]) CXXFLAGS="$CXXFLAGS -fvisibility=hidden $COMMON_WARNING_FLAGS $WARNING_CXXFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden $COMMON_WARNING_FLAGS $WARNING_CFLAGS" AC_DEFINE_UNQUOTED([BINDIR], ["$bindir"], [Binaries root directory]) AC_DEFINE_UNQUOTED([DATADIR], ["$datadir"], [Data directory]) AC_DEFINE_UNQUOTED([DATAROOTDIR], ["$datarootdir"], [Data root directory]) AC_DEFINE_UNQUOTED([DOCDIR], ["$docdir"], [Documentation directory]) AC_DEFINE_UNQUOTED([EXEC_PREFIX], ["$exec_prefix"], [Exec Prefix]) AC_DEFINE_UNQUOTED([INCLUDEDIR], ["$includedir"], [Include directory]) AC_DEFINE_UNQUOTED([LIBEXECDIR], ["$libexecdir"], [Libexec directory]) AC_DEFINE_UNQUOTED([LOCALSTATEDIR], ["$localstatedir"], [Local state directory]) AC_DEFINE_UNQUOTED([PREFIX], ["$prefix"], [Prefix]) AC_DEFINE_UNQUOTED([SBINDIR], ["$sbindir"], [System binaries root directory]) AC_DEFINE_UNQUOTED([SHAREDSTATEDIR], ["$sharedstatedir"], [Shared state directory]) AC_DEFINE_UNQUOTED([SYSCONFDIR], ["$sysconfdir"], [System config root directory]) AC_DEFINE_UNQUOTED([USBGUARD_DAEMON_CONF_PATH], ["$sysconfdir/usbguard/usbguard-daemon.conf"], [Default USBGuard daemon config path]) AC_CONFIG_FILES([Makefile libusbguard.pc src/Tests/Fuzzers/Makefile src/Tests/Makefile]) AC_OUTPUT echo echo " Build Configuration Summary " echo "===================================" echo echo " Run full test suite: $full_test_suite" echo echo "## Libraries" echo echo " libqb: $libqb_summary" echo " crypto: $crypto_summary" echo " libaudit: $libaudit_summary" echo " libldap: $libldap_summary" echo " libseccomp: $libseccomp_summary" echo " libcap-ng: $libcap_ng_summary" echo " protobuf: $protobuf_summary" echo " Catch: $catch_summary" echo " PEGTL: $pegtl_summary" echo " GDBus: $dbus_summary" echo " umockdev: $umockdev_summary" echo echo "## Directories" echo echo " D-Bus System Services: $dbus_services_dir" echo " D-Bus Busconfig: $dbus_busconfig_dir" echo " PolicyKit Policies: $polkit_policy_dir" echo " systemd unit dir: $systemd_unit_dir" echo " Bash completion dir: $BASH_COMPLETION_DIR" echo echo "## Compilation Flags" echo echo "Debug Build: $debug" echo " DEFS: $DEFS" echo " CXXFLAGS: $CXXFLAGS" echo " CFLAGS: $CFLAGS" echo " CPPFLAGS: $CPPFLAGS" echo " LDFLAGS: $LDFLAGS" echo " ASAN_FLAGS: $ASAN_FLAGS" echo " TSAN_FLAGS: $TSAN_FLAGS" echo ================================================ FILE: doc/man/.gitignore ================================================ /*.1 /*.1.roff /*.5 /*.5.roff /*.8 /*.8.roff ================================================ FILE: doc/man/example-allow-device.adoc ================================================ .... # Allow a device by ID(it is the very first number from the list-devices command output) $ sudo usbguard allow-device 10 # Allow all devices named "Dell Wired Multimedia Keyboard" $ sudo usbguard allow-device name \"Dell Wired Multimedia Keyboard\" .... ================================================ FILE: doc/man/example-initial-policy.adoc ================================================ .... $ sudo usbguard generate-policy > rules.conf $ vi rules.conf (review/modify the rule set) $ sudo install -m 0600 -o root -g root rules.conf /etc/usbguard/rules.conf $ sudo systemctl restart usbguard .... ================================================ FILE: doc/man/footer.adoc ================================================ == BUGS If you find a bug in this software or if you'd like to request a feature to be implemented, please file a ticket at . == AUTHOR USBGuard was originally written by Daniel Kopeček. Many people have contributed to it. == RESOURCES Main web site: == COPYING Copyright © 2015-{docyear} Red Hat, Inc. + License GPLv2+: GNU GPL version 2 or later http://gnu.org/licenses/gpl.html. + This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. ================================================ FILE: doc/man/usbguard-daemon.8.adoc ================================================ usbguard-daemon(8) ================== :doctype: manpage == NAME usbguard-daemon - USBGuard daemon == SYNOPSIS usbguard-daemon [OPTIONS] == DESCRIPTION The *usbguard-daemon* is the main component of the USBGuard software framework. It runs as a service in the background and enforces the USB device authorization policy for all USB devices. The policy is defined by a set of rules using a rule language described in *usbguard-rules.conf*(5). The policy and the authorization state of USB devices can be modified during runtime using the *usbguard*(1) tool. == OPTIONS *-d*:: Enable debugging messages in the log. *-f*:: Enable classical daemon behavior (fork at start, sysV compliant). *-s*:: Log to syslog. *-k*:: Log to console. (default) *-K*:: Disable Logging to console. *-l* 'path':: Log to a file at 'path'. *-p* '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'). *-P*:: Disable permissions check on conf and policy files (default: '/etc/usbguard/usbguard-daemon.conf'). *-C*:: Drop capabilities to limit privileges of the process. *-W*:: Use a seccomp allowlist to limit available syscalls to the process. *-h*:: Show the help/usage screen. == SECURITY CONSIDERATIONS The daemon provides the USBGuard public IPC interface. Depending on your distribution defaults, the access to this interface is limited to a certain group or a specific user only. Please refer to the usbguard-daemon.conf(5) man page for more information on how to configure the ACL correctly. *Do not leave the ACL unconfigured as that will expose the IPC interface to all local users. That will allow them to manipulate the authorization state of USB devices and modify the USBGuard policy*. == SEE ALSO link:usbguard-daemon.conf.5.adoc#name[usbguard-daemon.conf(5)], link:usbguard-rules.conf.5.adoc#name[usbguard-rules.conf(5)], link:usbguard.1.adoc#name[usbguard(1)] include::footer.adoc[] ================================================ FILE: doc/man/usbguard-daemon.conf.5.adoc ================================================ usbguard-daemon.conf(5) ======================= :doctype: manpage == NAME usbguard-daemon.conf - USBGuard daemon configuration file == DESCRIPTION The *usbguard-daemon.conf* file is loaded by the USBGuard daemon after it parses its command-line options. It is used to configure runtime parameters of the daemon. The default search path is '/etc/usbguard/usbguard-daemon.conf'. It may be overridden using the *-c* command-line option, see *usbguard-daemon*(8) for further details. == OPTIONS *RuleFile*='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. Default: %sysconfdir%/usbguard/rules.conf *RuleFolder*='path':: The USBGuard daemon will use this folder to load the policy rule set from it and to write new rules received via the IPC interface. Usually, we set the option to `/etc/usbguard/rules.d/`. The USBGuard daemon is supposed to behave like any other standard Linux daemon therefore it loads rule files in alpha-numeric order. File names inside `RuleFolder` directory should start with a two-digit number prefix indicating the position, in which the rules are scanned by the daemon. Using RuleFile and RuleFolder at the same time is permitted. However, modification of the permanent policy is not possible if one of the following conditions are met: ** Neither RuleFile nor RuleFolder are specified. ** RuleFile is not specified, RuleFolder is but it does not contain any files, where we could save permanent rules. *ImplicitPolicyTarget*='target':: How to treat USB devices that don't match any rule in the policy. Target should be one of `allow`, `block` or `reject` (logically remove the device node from the system). Default: block *PresentDevicePolicy*='policy':: How to treat USB devices that are already connected when the daemon starts. Policy should be one of `allow`, `block`, `reject`, `keep` (keep whatever state the device is currently in) or `apply-policy` (evaluate the rule set for every present device). Default: apply-policy *PresentControllerPolicy*='policy':: How to treat USB *controller* devices that are already connected when the daemon starts. One of `allow`, `block`, `reject`, `keep` or `apply-policy`. Default: keep *InsertedDevicePolicy*='policy':: How to treat USB devices that are already connected _after_ the daemon starts. One of `block`, `reject`, `apply-policy`. Default: apply-policy *AuthorizedDefault*='authorizedDefault':: The USBGuard daemon modifies some of the default authorization state attributes of controller devices. This setting, enables you to define what value the default authorization is set to. Authorized default should be one of `keep` (do not change authorization state), `none` (every new device starts out deauthorized), `all` (every new device starts out authorized) or `internal` (internal devices start out authorized, external do not). Default: none *RestoreControllerDeviceState*='boolean':: The USBGuard daemon modifies some attributes of controller devices like the default authorization state of new child device instances. Using this setting, you can control whether the daemon will try to restore the attribute values to the state before modification on shutdown. Default: false *DeviceManagerBackend*='backend':: Which device manager backend implementation to use. Backend should be one of `uevent` (default) or `umockdev` (useful for testing). UEvent backend is a netlink based implementation which uses sysfs to scan for present devices and an uevent socket for receiving USB device related events. UMockDev based device manager is capable of simulating devices based on umockdev-record files. Default: uevent *IPCAllowedUsers*='username' ['username' ...]:: A space delimited list of usernames that the daemon will accept IPC connections from. Default: root *IPCAllowedGroups*='groupname' ['groupname' ...]:: A space delimited list of groupnames that the daemon will accept IPC connections from. *IPCAccessControlFiles*='path':: The files at this location will be interpreted by the daemon as IPC access control definition files. See the <> section for more details. *DeviceRulesWithPort*='boolean':: Generate device specific rules including the "via-port" attribute. Default: false *AuditBackend*='backend':: USBGuard audit events log backend. The 'backend' value should be one of `FileAudit` or `LinuxAudit`. Default: FileAudit *AuditFilePath*='filepath':: USBGuard audit events log file path. Required if AuditBackend is set to `FileAudit`. Default: %localstatedir%/log/usbguard/usbguard-audit.log *HidePII*='boolean':: Hides personally identifiable information such as device serial numbers and hashes of descriptors (which include the serial number) from audit entries. Default: false == SECURITY CONSIDERATIONS === IPC The daemon provides the USBGuard public IPC interface. Depending on your distribution defaults, access to this interface is limited to a certain group or a specific user only. Please set either the *IPCAllowedUsers*, *IPCAllowedGroups* or *IPCAccessControlFiles* options to limit access to the IPC interface. *Do not leave the ACL unconfigured as that will expose the IPC interface to all local users and will allow them to manipulate the authorization state of USB devices and modify the USBGuard policy*. === RestoreControllerDeviceState configuration option 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). [[ipc-access-control]] == IPC ACCESS CONTROL Access to the USBGuard IPC interface can be limited per user or group. Furthermore, by using the IPC Access Control files, it is possible to limit the access down to the level of Sections and Privileges as explained below. === *Recommended*: *IPCAccessControlFiles* When you set *IPCAccessControlFiles* option, the daemon will look for IPC access control files in the directory specified by the set value. Each file in the directory is processed as follows: 1. The basename of the file is interpreted as a username, UID, groupname or GID. If the name starts with `:` (colon), it is assumed that the rest of the name represents a group identifier (groupname or GID in case of a numeric-only string). Otherwise, it is interpreted as a user identifier (username or UID in case of numeric-only string). 2. The contents of the file are parsed as `Section=[privilege1][,privilege2] ...` formatted lines which specify the section privileges. If a section is omitted, it is assumed that no privileges are given for that section. Available sections and privileges: * *Devices* ** modify: Change authorization state of devices including permanent changes (i.e. modification of device specific rules in the policy). ** list: Ability to get a list of recognized devices and their attributes. ** listen: Listen to device presence and device policy changes. * *Policy* ** modify: Append rules to or remove any rules from the policy. ** list: Ability to view the currently enforced policy. * *Exceptions* ** listen: Receive exception messages. * *Parameters* ** modify: Set values of run-time parameters. ** list: Get values of run-time parameters. ** listen: Listen to property parameter changes. The following is a generally usable and reasonably safe example of an access control file. It allows one to modify USB device authorization state (`Devices=modify`), list USB devices (`Devices=list`), listen to USB device related events (`Devices=listen`), list USB authorization policy rules (`Policy=list`) and listen to exception events (`Exceptions=listen`): .... Devices=modify,list,listen Policy=list Exceptions=listen .... You can create or remove the IPC access control files using `usbguard add-user` and `usbguard remove-user` CLI commands. See usbguard(1) for more details. If you want to create the IPC access control files manually, you need to set the files permissions to `0600`. === Legacy: *IPCAllowedUsers* and *IPCAllowedGroups* Example configuration allowing full IPC access to users 'root', 'joe' and members of the group 'wheel': .... IPCAllowedUsers=root joe IPCAllowedGroups=wheel .... == SEE ALSO link:usbguard-daemon.8.adoc#name[usbguard-daemon(8)], link:usbguard-rules.conf.5.adoc#name[usbguard-rules.conf(5)] include::footer.adoc[] ================================================ FILE: doc/man/usbguard-dbus.8.adoc ================================================ usbguard-dbus(8) ================ :doctype: manpage == NAME usbguard-dbus - USBGuard D-Bus interface service == SYNOPSIS usbguard-dbus [OPTIONS] == DESCRIPTION The usbguard-dbus component exposes a D-Bus interface to a running instance of *usbguard-daemon(8)*. == OPTIONS *-s, --system*:: Listen on the system bus. *-S, --session*:: Listen on the session bus. *-h, --help*:: Show the help/usage screen. == SEE ALSO link:usbguard.1.adoc#name[usbguard(1)] include::footer.adoc[] ================================================ FILE: doc/man/usbguard-ldap.conf.5.adoc ================================================ usbguard-ldap.conf(5) ===================== :doctype: manpage == NAME usbguard-ldap.conf - USBGuard daemon ldap configuration file == DESCRIPTION The *usbguard-ldap.conf* file is loaded by the USBGuard daemon after it parses '/etc/nsswitch.conf' and result source is LDAP. It is used to configure LDAP client configuration. The default search path is '/etc/usbguard/usbguard-ldap.conf'. The USBGuard daemon in LDAP mode strictly requires this file and it won\'t start without file present. This file was inspired be standard *ldap.conf* syntax. Keys are case insensitive but values are not. == OPTIONS *URI* 'address':: The USBGuard Daemon will use this address to connect to this LDAP server. `URI ldap://127.0.0.1/` *ROOTDN* 'root domain name':: Domain name of the user that has access rights to LDAP. `ROOTDN cn=Manager,dc=example,dc=com` *BASE* 'standard LDAP base':: LDAP base of the server. `BASE dc=example,dc=com` *ROOTPW* 'password':: The password for given *ROOTDN*. `ROOTPW passme` *USBGUARDBASE* 'usbguard base':: This is supposed to be domain name of the USBGuard organizational unit. This option helps to the daemon found the right sub-tree with rules. If not set the daemon will use the default (ou=USBGuard,dc=example,dc=com). `USBGUARDBASE ou=USBGuard,dc=example,dc=com` *RULEQUERY* 'query string':: This query is used for fetching of rules from LDAP so it needs to match all rules for the machine and nothing else. It is suggested to use a default query because it is very simple to broke something with bad one. The default matches all object with common name starting with *Rule* prefix that contain our hostname as USBGuardHost and they don\'t contain negation of our hostname. If the USBGuard host is asterisk it will match but this same rule must not contain negation of matched host. `RULEQUERY (&(cn=Rule*)(|(&(USBGuardHost=host)(!(USBGuardHost=!host)))(&(USBGuardHost=\*)(!(USBGuardHost=!host)))))` *UPDATEINTERVAL* 'interval':: This is an interval that defines periodicity of update. The default is one hour. `UPDATEINTERVAL 1` == SEE ALSO link:usbguard-daemon.8.adoc#name[usbguard-daemon(8)], link:usbguard-daemon.conf.5.adoc#name[usbguard-daemon.conf(5)], link:usbguard-rules.conf.5.adoc#name[usbguard-rules.conf(5)] include::footer.adoc[] ================================================ FILE: doc/man/usbguard-rules.conf.5.adoc ================================================ usbguard-rules.conf(5) ====================== :doctype: manpage == NAME usbguard-rules.conf - USBGuard rule set file. == DESCRIPTION The *usbguard-rules.conf* file is loaded by the USBGuard daemon after it parses the main configuration file, usbguard-daemon.conf(5). The daemon expects the file to contain rules written in a language which is described in the <> section below. [[rule-language]] == Rule Language The USBGuard daemon decides which USB device to authorize based on a policy defined by a set of rules. When a USB device is inserted into the system, the daemon scans the existing rules sequentially. If a matching rule is found, it either authorizes (*allows*), deauthorizes (*blocks*) or removes (*rejects*) the device, based on the rule target. If no matching rule is found, the decision is based on an implicit default target. This implicit default is to block the device until a decision is made by the user. The rule language grammar, expressed in a BNF-like syntax, is the following: .... rule ::= target attributes. target ::= "allow" | "block" | "reject". attributes ::= attributes | attribute. attributes ::= . .... Rule attributes specify which devices to match or what condition have to be met for the rule to be applicable. See the <> section for the list of available attributes and <> for the list of supported rule rule conditions. === Targets The target of a rule specifies whether the device will be authorized for use or not. Three types of target are recognized: * *allow* - Authorize the device. The device and its interfaces will be allowed to communicate with the system. * *block* - Deauthorize the device. The device will remain in a blocked state until it is authorized. * *reject* - Deauthorize and Remove the device from the system. The device will have to be re-inserted to become visible to the system again. [[device-specification]] === Device Specification Except the target, all the other fields of a rule are optional. A rule where only the `target` is specified will match any device. That allows the policy administrator to write an explicit default target. If no rule from the policy is applicable to the device, an implicit target configured in usbguard-daemon.conf(5) will be used. However, if one wants to narrow the applicability of a rule to a set of devices or one device only, it's possible to do so with device attributes and rule conditions. ==== Device Attributes Device attributes are specific values read from the USB device after it's inserted to the system. Which attributes are available is defined below. Some of the attributes are derived and some are based on attributes read directly from the device. All attributes support two forms: * *single-valued* with a syntax: + .... name value .... * *multi-valued* with a syntax: + .... name [operator] { value1 value2 ... } .... where the optional 'operator' is one of: *all-of*:: The device attribute set must contain all of the specified values for the rule to match. *one-of*:: The device attribute set must contain at least one of the specified values for the rule to match. *none-of*:: The device attribute set must not contain any of the specified values for the rule to match. *equals*:: The device attribute set must contain exactly the same set of values for the rule to match. *equals-ordered*:: The device attribute set must contain exactly the same set of values in the same order for the rule to match. *match-all*:: The device attribute set must be a subset of the specified values for the rule to match. If the operator is not specified it is set to *equals*. [.underline]#List of attributes:# *id* usb-device-id:: Match a USB device ID. *id* [operator] { usb-device-id ... }:: Match a set of USB device IDs. *hash* "value":: Match a hash computed from the device attribute values and the USB descriptor data. The hash is computed for every device by USBGuard. *hash* [operator] { "value" ... }:: Match a set of device hashes. *parent-hash* "value":: Match a hash of the parent device. *parent-hash* [operator] { "value" ... }:: Match a set of parent device hashes. *name* "device-name":: Match the USB device name attribute. *name* [operator] { "device-name" ... }:: Match a set of USB device names. *serial* "serial-number":: Match the USB iSerial device attribute. *serial* [operator] { "serial-number" ... }:: Match a set of USB iSerial device attributes. *via-port* "port-id":: Match the USB port through which the device is connected. Note that some systems have unstable port numbering. The port might change after the system reboots or when certain kernel modules are reloaded. Use the *parent-hash* attribute if you want to ensure that a device is connected via a specific parent device. *via-port* [operator] { "port-id" ... }:: Match a set of USB ports. *with-interface* interface-type:: Match an interface type that the USB device provides. *with-interface* [operator] { interface-type ... }:: Match a set of interface types against the set of interfaces that the USB device provides. *with-connect-type* "connect-type":: Match the USB port/connect_type device attribute. *with-connect-type* [operator] { "connect-type" ... }:: Match a set of USB port/connect_type device attributes. *label* "label":: Associates arbitrary string with a rule. Label is useful for storing some contextual information about rule or for filtering rules by label. This attribute is not used when testing if a rule applies to a device. The 'usb-device-id' is a colon delimited pair in the form 'vendor_id:product_id'. All USB devices have this ID assigned by the manufacturer and it should uniquely identify a USB product type. Both 'vendor_id' and 'product_id' are 16-bit numbers represented in hexadecimal base. It's possible to use an asterisk character to match either any device ID `*:*` or any product ID from a specific vendor, e.g. `1234:*`. The 'port-id' value is a platform specific USB port identification. On Linux it's in the form of "usbN" in case of a USB controller (more accurately a "root hub") or "bus-port[.port[.port ...]]" (e.g. `1-2`, `1-2.1`, ...) in case of a USB device. The 'interface-type' represents a USB interface and should be formatted as three 8-bit numbers in hexadecimal base delimited by a colon character, i.e. 'cc:ss:pp'. The numbers represent the interface class ('cc'), subclass ('ss') and protocol ('pp') as assigned by the http://www.usb.org/about[USB-IF]. See the https://www.usb.org/defined-class-codes[list of assigned classes, subclasses and protocols] for details. Instead of the subclass and protocol number, you may write an asterisk character (`*`) to match all subclasses or protocols. Matching a specific class and a specific protocol is not allowed, i.e. if you use an asterisk as the subclass number, you have to use an asterisk for the protocol too. [[conditions]] === Conditions Whether a rule that matches a device will be applied or not can be further restricted using rule conditions. If the condition expression is met at the rule evaluation time, then the rule target is applied for the device. A condition expression is met if it evaluates to true. Otherwise, the rule evaluation continues with the next rule. A rule conditions has the following syntax: .... if [!]condition if [operator] { [!]conditionA [!]conditionB ... } .... Optionally, an exclamation mark (`!`) can be used to negate the result of a condition. Interpretation of the set operator: *all-of*:: Evaluate to true if all of the specified conditions evaluated to true. *one-of*:: Evaluate to true if one of the specified conditions evaluated to true. *none-of*:: Evaluate to true if none of the specified conditions evaluated to true. *equals*:: Same as *all-of*. *equals-ordered*:: Same as *all-of*. List of conditions: *localtime(time_range)*:: Evaluates to true if the local time is in the specified time range. 'time_range' can be written either as `HH:MM[:SS]` or `HH:MM[:SS]-HH:MM[:SS]`. *allowed-matches(query)*:: Evaluates to true if an allowed device matches the specified 'query'. The query uses the rule syntax. *Conditions in the query are not evaluated*. *rule-applied*:: Evaluates to true if the rule currently being evaluated ever matched a device. *rule-applied(past_duration)*:: Evaluates to true if the rule currently being evaluated matched a device in the past duration of time specified by the parameter. 'past_duration' can be written as `HH:MM:SS`, `HH:MM`, or `SS`. *rule-evaluated*:: Evaluates to true if the rule currently being evaluated was ever evaluated before. *rule-evaluated(past_duration)*:: Evaluates to true if the rule currently being evaluated was evaluated in the pas duration of time specified by the parameter. 'past_duration' can be written as `HH:MM:SS`, `HH:MM`, or `SS`. *random*:: Evaluates to true/false with a probability of `p(true)=0.5`. *random(p_true)*:: Evaluates to true with the specified probability `p(true)=p_true`. *true*:: Evaluates always to true. *false*:: Evaluates always to false. === Partial rule Partial rule is a rule without a rule target. Partial rules may by used by some commands of *usbguard* CLI tool. === Comments In order to easily understand the meaning of each rule, comments can be used. Everything after the "#" character is ignored by the rule parser. == Initial policy Using the *usbguard* CLI tool and its *generate-policy* subcommand, you can generate an initial policy for your system instead of writing one from scratch. The tool generates an *allow* policy for all devices connected to the system at the time of execution. It has several options to tweak the resulting policy, see usbguard(1) for further details. The policy will be printed out on the standard output. It's a good idea to review the generated rules before using them on a system. The typical workflow for generating an initial policy could look like this: include::example-initial-policy.adoc[] == Example Policies The following examples show what to put into the *rules.conf* file in order to implement the given policy. 1. *Allow USB mass storage devices (USB flash disks) and block everything else* + This policy will block any device that isn't just a mass storage device. Devices with a hidden keyboard interface in a USB flash disk will be blocked. Only devices with a single mass storage interface will be allowed to interact with the operating system. The policy consists of a single rule: + .... allow with-interface equals { 08:*:* } .... + The blocking is implicit in this case because we didn't write a `block` rule. Implicit blocking is useful to desktop users. A desktop applet listening to USBGuard events can ask the user for a decision if an implicit target was applied. 2. *Allow a specific Yubikey device to be connected via a specific port (and reject everything else on that port)* + .... allow 1050:0011 name "Yubico Yubikey II" serial "0001234567" via-port "1-2" hash "044b5e168d40ee0245478416caf3d998" reject via-port "1-2" .... + We could use just the hash to match the device. However, using the `name` and `serial` attributes provide an useful hint for later inspection of the policy. On the other hand, the hash is the most specific value we can use to identify a device. It's the best attribute to use if you want a rule to match just one device. 3. *Reject devices with suspicious combination of interfaces* + A USB flash disk which implements a keyboard or a network interface is very suspicious. The following set of rules forms a policy that allows USB flash disks and explicitly rejects devices with an additional and suspicious (as defined before) interface. + .... allow with-interface equals { 08:*:* } reject with-interface all-of { 08:*:* 03:00:* } reject with-interface all-of { 08:*:* 03:01:* } reject with-interface all-of { 08:*:* e0:*:* } reject with-interface all-of { 08:*:* 02:*:* } .... + The policy rejects all USB flash disk devices with an interface from the HID/Keyboard, Communications and Wireless classes. Note that default allow is the wrong approach and you shouldn't just reject a set of devices and allow the rest. The policy above assumes that blocking is the default. Rejecting a set of devices considered as "bad" is a good approach how to limit the exposure of the OS to such devices as much as possible. 4. *Allow a keyboard-only USB device only if there isn't already a USB device with a keyboard interface allowed* + .... allow with-interface one-of { 03:00:01 03:01:01 } if !allowed-matches(with-interface one-of { 03:00:01 03:01:01 }) .... 5. *Play "Russian roulette" with USB devices* + .... allow if random(0.1666) reject .... == SEE ALSO link:usbguard-daemon.8.adoc#name[usbguard-daemon(8)], link:usbguard-daemon.conf.5.adoc#name[usbguard-daemon.conf(5)] include::footer.adoc[] ================================================ FILE: doc/man/usbguard.1.adoc ================================================ usbguard(1) =========== :doctype: manpage == NAME usbguard - USBGuard command-line interface == SYNOPSIS usbguard [OPTIONS]  [SUBCOMMAND-OPTIONS] ... usbguard get-parameter 'name' usbguard set-parameter 'name' 'value' usbguard list-devices usbguard allow-device 'id' | 'rule' | 'partial-rule' usbguard block-device 'id' | 'rule' | 'partial-rule' usbguard reject-device 'id' | 'rule' | 'partial-rule' usbguard list-rules usbguard append-rule 'rule' usbguard remove-rule 'id' usbguard generate-policy usbguard watch usbguard read-descriptor 'file' usbguard add-user 'name' usbguard remove-user 'name' == DESCRIPTION The usbguard command provides a command-line interface (CLI) to a running usbguard-daemon(8) instance. It also provides a tool for generating initial USBGuard policies based on USB devices connected to the system. == SUBCOMMANDS === *get-parameter* ['OPTIONS'] 'name' Get the value of a runtime parameter. Parameter 'name' is one of 'InsertedDevicePolicy' and 'ImplicitPolicyTarget'. Available options: *-h, --help*:: Show help. === *set-parameter* ['OPTIONS'] 'name' 'value' Set the value of a runtime parameter. Parameter 'name' is one of 'InsertedDevicePolicy' and 'ImplicitPolicyTarget'. Available options: *-v, --verbose*:: Print the previous and new attribute value. *-h, --help*:: Show help. === *list-devices* ['OPTIONS'] List all USB devices recognized by the USBGuard daemon. Available options: *-a, --allowed*:: List allowed devices. *-b, --blocked*:: List blocked devices. *-t, --tree*:: List devices in a tree format. *-h, --help*:: Show help. === *allow-device* ['OPTIONS'] < 'id' | 'rule' | 'partial-rule' > Authorize a device to interact with the system. The device can be identified by either a device 'id', 'rule' or 'partial-rule' (rule without target). Both 'rule' and 'partial-rule' can be used to allow multiple devices at once. Note that 'id' refers to the internal device-rule ID (the very first number of the list-devices command output) rather than the device's ID attribute. Available options: *-p, --permanent*:: Make the decision permanent. A device specific allow rule will be appended to the current policy. *-h, --help*:: Show help. === *block-device* ['OPTIONS'] < 'id' | 'rule' | 'partial-rule' > Deauthorize a device. The device can be identified by either a device 'id', 'rule' or 'partial-rule' (rule without target). Both 'rule' and 'partial-rule' can be used to block multiple devices at once. Note that 'id' refers to the internal device-rule ID (the very first number of the list-devices command output) rather than the device's ID attribute. Available options: *-p, --permanent*:: Make the decision permanent. A device specific block rule will be appended to the current policy. *-h, --help*:: Show help. === *reject-device* ['OPTIONS'] < 'id' | 'rule' | 'partial-rule' > Deauthorize and remove a device. The device can be identified by either a device 'id', 'rule' or 'partial-rule' (rule without target). Both 'rule' and 'partial-rule' can be used to reject multiple devices at once. Note that 'id' refers to the internal device-rule ID (the very first number of the list-devices command output) rather than the device's ID attribute. Available options: *-p, --permanent*:: Make the decision permanent. A device specific reject rule will be appended to the current policy. *-h, --help*:: Show help. === *list-rules* ['OPTIONS'] List the rule set (policy) used by the USBGuard daemon. Available options: *-d, --show-devices*:: Show all devices which are affected by the specific rule. *-l, --label* 'label':: Only show rules having a specific label. *-h, --help*:: Show help. === *append-rule* ['OPTIONS'] 'rule' Append the 'rule' to the current rule set. Available options: *-a, --after* 'id':: Append the new rule after a rule with the specified rule 'id'. *-t, --temporary*:: Make the decision temporary. The rule policy file will not be updated. *-h, --help*:: Show help. === *remove-rule* ['OPTIONS'] 'id' Remove a rule identified by the rule 'id' from the rule set. Available options: *-h, --help*:: Show help. === *generate-policy* ['OPTIONS'] Generate a rule set (policy) which authorizes the currently connected USB devices. Available options: *-p, --with-ports*:: Generate port specific rules for all devices. By default, port specific rules are generated only for devices which do not export an iSerial value. *-P, --no-ports-sn*:: Don't generate port specific rules for devices without an iSerial value. Without this option, the tool will add a via-port attribute to any device that doesn't provide a serial number. This is a security measure to limit devices that cannot be uniquely identified to connect only via a specific port. This makes it harder to bypass the policy since the real device will occupy the allowed USB port most of the time. *-d, --devpath* 'devpath':: Only generate a rule for the device at the specified sub path of /sys. *-t, --target* 'target':: Generate an explicit "catch all" rule with the specified target. The target can be one of the following values: *allow*, *block*, *reject* *-X, --no-hashes*:: Don't generate a hash attribute for each device. *-H, --hash-only*:: Generate a hash-only policy. *-L, --ldif*:: Generate a ldif policy for LDAP. *-b, --usbguardbase* 'base':: Generate a ldif policy for LDAP with this base. This option is required when --ldif was specified. *-o, --objectclass* 'objectclass':: Generate a ldif policy for LDAP with this objectClass. *-n, --name-prefix* 'prefix':: Generate a ldif policy for LDAP with this name prefix. *-h, --help*:: Show help. === *watch* ['OPTIONS'] Watch the IPC interface events and print them to stdout. Available options: *-w, --wait*:: Wait for IPC connection to become available. *-o, --once*:: Wait only when starting, if needed. Exit when the connection is lost. *-e, --exec* 'path':: Run an executable file located at 'path' for every event. Pass event data to the process via environment variables. *-h, --help*:: Show help. === *read-descriptor* ['OPTIONS'] 'file' Read a USB descriptor from a file and print it in human-readable form. Available options: *-h, --help*:: Show help. === *add-user* 'name' ['OPTIONS'] Create an IPC access control file allowing the user/group identified by 'name' to use the USBGuard IPC bus. The change takes effect only after restarting the usbguard-daemon(8) instance. Available options: *-u, --user*:: The specified 'name' represents a username or UID (default). *-g, --group*:: The specified 'name' represents a groupname or GID. *-p, --policy* 'privileges':: Policy related privileges. *-d, --devices* 'privileges':: Device related privileges. *-e, --exceptions* 'privileges':: Exceptions related privileges. *-P, --parameters* 'privileges':: Run-time parameter related privileges. *-h, --help*:: Show help. Privileges: The 'privileges' are expected to be in the form of a list separated by a colon: .... $ sudo usbguard add-user joe --devices=listen,modify .... Consult the usbguard-daemon.conf(5) man-page for a detailed list of available privileges in each section. You can also use 'ALL' instead of 'privileges' to automatically assign all relevant privileges to a given section. === *remove-user* 'name' ['OPTIONS'] Remove an IPC access control file associated with the user/group identified by 'name'. The change takes effect only after restarting the usbguard-daemon(8) instance. Available options: *-u, --user*:: The specified 'name' represents a username or UID (default). *-g, --group*:: The specified 'name' represents a groupname or GID. *-h, --help*:: Show help. == EXAMPLES Generating an initial policy: include::example-initial-policy.adoc[] Allow device(s): include::example-allow-device.adoc[] == SEE ALSO link:usbguard-daemon.8.adoc#name[usbguard-daemon(8)], link:usbguard-daemon.conf.5.adoc#name[usbguard-daemon.conf(5)], link:usbguard-rules.conf.5.adoc#name[usbguard-rules.conf(5)] include::footer.adoc[] ================================================ FILE: libusbguard.pc.in ================================================ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/usbguard Name: libusbguard Description: USBGuard API library URL: https://github.com/USBGuard/usbguard Version: @VERSION@ Requires: libqb Libs: -L${libdir} -lusbguard Cflags: -I${includedir} ================================================ FILE: m4/ax_check_compile_flag.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # 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 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 4 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS ================================================ FILE: m4/ax_pthread.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # 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 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 22 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], [ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif ], [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) AS_IF([test "x$GCC" = "xyes"], [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix* | freebsd*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif ], [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" ax_pthread_clang_warning=no # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) PTHREAD_CFLAGS="-pthread" PTHREAD_LIBS= ax_pthread_ok=yes # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [ac_link="$ax_pthread_2step_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [break]) ]) done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ]) case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -mt,pthread) AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) PTHREAD_CFLAGS="-mt" PTHREAD_LIBS="-lpthread" ;; -*) AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_CACHE_CHECK([for joinable pthread attribute], [ax_cv_PTHREAD_JOINABLE_ATTR], [ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $ax_pthread_attr; return attr /* ; */])], [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], []) done ]) AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes"], [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$ax_cv_PTHREAD_JOINABLE_ATTR], [Define to necessary symbol if this constant uses a non-standard name on your system.]) ax_pthread_joinable_attr_defined=yes ]) AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ]) AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes"], [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ax_pthread_prio_inherit_defined=yes ]) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD ================================================ FILE: m4/libgcrypt.m4 ================================================ dnl Autoconf macros for libgcrypt dnl Copyright (C) 2002, 2004, 2011 Free Software Foundation, Inc. dnl dnl This file is free software; as a special exception the author gives dnl unlimited permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl dnl This file is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed dnl with the API version to also check the API compatibility. Example: dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using dnl this features allows to prevent build against newer versions of libgcrypt dnl with a changed API. dnl AC_DEFUN([AM_PATH_LIBGCRYPT], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_WITH(libgcrypt-prefix, AS_HELP_STRING([--with-libgcrypt-prefix=PFX], [prefix where LIBGCRYPT is installed (optional)]), libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") if test x$libgcrypt_config_prefix != x ; then if test x${LIBGCRYPT_CONFIG+set} != xset ; then LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config fi fi AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no) tmp=ifelse([$1], ,1:1.2.0,$1) if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` else req_libgcrypt_api=0 min_libgcrypt_version="$tmp" fi AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) ok=no if test "$LIBGCRYPT_CONFIG" != "no" ; then req_major=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` req_minor=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` major=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` micro=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` if test "$major" -gt "$req_major"; then ok=yes else if test "$major" -eq "$req_major"; then if test "$minor" -gt "$req_minor"; then ok=yes else if test "$minor" -eq "$req_minor"; then if test "$micro" -ge "$req_micro"; then ok=yes fi fi fi fi fi fi if test $ok = yes; then AC_MSG_RESULT([yes ($libgcrypt_config_version)]) else AC_MSG_RESULT(no) fi if test $ok = yes; then # If we have a recent libgcrypt, we should also check that the # API is compatible if test "$req_libgcrypt_api" -gt 0 ; then tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` if test "$tmp" -gt 0 ; then AC_MSG_CHECKING([LIBGCRYPT API version]) if test "$req_libgcrypt_api" -eq "$tmp" ; then AC_MSG_RESULT([okay]) else ok=no AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) fi fi fi fi if test $ok = yes; then LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` ifelse([$2], , :, [$2]) libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` if test x"$libgcrypt_config_host" != xnone ; then if test x"$libgcrypt_config_host" != x"$host" ; then AC_MSG_WARN([[ *** *** The config script $LIBGCRYPT_CONFIG was *** built for $libgcrypt_config_host and thus may not match the *** used host $host. *** You may want to use the configure option --with-libgcrypt-prefix *** to specify a matching config script. ***]]) fi fi else LIBGCRYPT_CFLAGS="" LIBGCRYPT_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(LIBGCRYPT_CFLAGS) AC_SUBST(LIBGCRYPT_LIBS) ]) ================================================ FILE: scripts/astyle.sh ================================================ #!/bin/bash # # 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 # PROJECT_ROOT="$(dirname "$0")/../" ASTYLERC_PATH="${PROJECT_ROOT}/src/astylerc" exec astyle $(< "${ASTYLERC_PATH}") "$@" ================================================ FILE: scripts/bash_completion/usbguard ================================================ _usbguard_get_ids() { usbguard list-devices 2>/dev/null | cut -d ":" -f1 } _usbguard_get_rules() { usbguard list-rules 2>/dev/null | cut -d ":" -f1 } _usbguard_in_option() { # Determines whether the cursor is currently on an option value (word that # starts with a dash). If it is the case, return true, false otherwise. # # Parameters # None # # Returns # retval (int) True / False # if [[ "$cur" == -* ]]; then return 0 else return 1 fi } _usbguard_contains() { # Copied from https://github.com/qtc-de/completion-helpers # # Takes two strings containing space separated words and checks if one of the # words in the second list matches one in the first. # E.g.: `_usbguard_contains "test test2" "no nope test"` returns true. # # Parameters # list_lookup (string) Space separated words to search in # list_search (string) Space separated words to search # # Returns # retval (int) Error / Success # # Side effects # None # for word in $2; do if [[ $1 =~ (^|[[:space:]])${word}($|[[:space:]]) ]]; then return 0 fi done return 1 } _usbguard_short_to_long() { # Copied from https://github.com/qtc-de/completion-helpers # # Takes a short option name and a a list that represents the current option list. # The functions assumes that the long option for a certain short option directly # follows the short option inside the argument list. The corresponding long # option is then returned inside the $long variable. # # Parameters # short (string) Name of the short option (with - prefix) # opts (list) Space separated words (option list) # # Returns # retval (int) Error / Success # # Side effects # stores the corresponding long option inside the $long variable # local short ret short=$1 shift ret=0 long= while (( "$#" )); do if [[ "$1" == "$short" ]]; then shift if [[ $1 =~ ^--[^[:space:]]+$ ]]; then long=$1 return 0 fi return 1 fi shift done return 1 } _usbguard_filter() { # Copied from https://github.com/qtc-de/completion-helpers # # Takes the name of a variable that contains the current option list as a string. # Iterates over the current command line and removes all options that are already # present. # # A second string of space separated words can be passed # that are excluded from filtering. This is useful, when certain options are allowed # to appear multiple times. # # By default, the function will try to remove long options if their corresponding short # options are used on the command line. To work correctly, this requires that each short # option has a long option that directly follows the short option in the options list. If # this assumption is incorrect, you should set a third parameter for _usbguard_filter to 'false'. # # Parameters # opts (string) Space separated words to filter (call by ref) # exclude (string) Space separated words to exclude # remove_longs (string) Decides whether short-to-long translation is attempted (true|false) # # Returns # retval (int) Error / Success # # Side effects # filtered option list is stored in first variable (passed by ref) # local Opts=$1 filter exclude cur long remove_longs cur="${COMP_WORDS[COMP_CWORD]}" filter=" ${!Opts} " exclude=$2 remove_longs=$3 # iterate over each word inside the current command line for var in ${COMP_LINE}; do # exclude the current word to allow full specified options to be space completed if [[ "$var" == "$cur" ]]; then continue # exclude words from the exclusion list elif _usbguard_contains "$exclude" $var; then continue # otherwise remove the word from the filter list else # if short option, remove long option if [[ "$remove_longs" != "false" && $var =~ ^-[a-zA-Z0-9]+$ ]]; then _usbguard_short_to_long $var $filter && \ filter=( "${filter//[[:space:]]${long}[[:space:]]/ }" ) fi # remove actual option filter=( "${filter//[[:space:]]${var}[[:space:]]/ }" ) fi done _upvars -v $Opts "$filter" } _usbguard_filter_shorts() { # Copied from https://github.com/qtc-de/completion-helpers # # Takes a string of space separated words and removes all short options from it. # Completion of short options is a matter of taste. The maintainers of bash-completion # do not recommend it. Instead, completions should only handle completion for arguments # that are required by short options, but to not complete short options themselves. # # Parameters # opts (string) Space separated option list (call by ref) # # Returns # retval (int) Error / Success # # Side effects # filtered option list is stored in first variable (passed by ref) # local Opts=$1 filter filter=" ${!Opts} " for word in $filter; do if [[ $word =~ ^-[a-zA-Z0-9]+$ ]]; then filter=( "${filter//[[:space:]]${word}[[:space:]]/ }" ) fi done _upvars -v $Opts "$filter" } _usbguard_comp_list() { # This function is used for list completion (comma separated words). If an option # expects a comma separated list of arguments, you can call this function with the # desired set of available list arguments. The function does already populate the # COMPREPLY variable and you normally want to return from the completion script # after calling it. # # Additionally to the array of available options, it is possible to specify an # integer as second argument that specifies the maximum amount of selectable # options. After this amount of options was specified, space completion is enabled. # # Parameters # options (string) Space separated list of available list options # max (int) Maximum number of list items # # Returns # retval (int) Error / Success # local cur prev prev_arr options=" $1 " count=1 compopt -o nospace cur="${COMP_WORDS[COMP_CWORD]}" if [[ "$cur" != ?*,* ]]; then mapfile -t COMPREPLY < <(compgen -W "${options}" -- "${cur}") return 0 else prev="${cur%,*}" cur="${cur##*,}" prev_arr=${prev//,/ } for word in $prev_arr; do count=$((count+1)) if _usbguard_contains "$options" $word; then options=( "${options//[[:space:]]${word}[[:space:]]/ }" ) continue fi done if [[ $count -ge $2 ]]; then compopt +o nospace fi mapfile -t COMPREPLY < <(compgen -P "$prev," -W "${options}" -- "${cur}") return 0 fi } _usbguard() { local args cur prev words cword value_options _init_completion || return _count_args COMPREPLY=() # If there was no positional argument provided yet, complete commands if [[ $args -eq 1 ]]; then opts="get-parameter set-parameter list-devices allow-device block-device reject-device list-rules append-rule" opts="${opts} remove-rule generate-policy watch read-descriptor add-user remove-user --version" else opts='-h --help' case "${words[1]}" in get-parameter) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then opts="InsertedDevicePolicy ImplicitPolicyTarget" fi ;; set-parameter) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then opts="InsertedDevicePolicy ImplicitPolicyTarget" elif ! _usbguard_in_option && [[ $args -eq 3 ]]; then return 0 else opts="$opts -v --verbose" fi ;; list-devices) opts="$opts -a --allowed -b --blocked -t --tree" ;; list-rules) if _usbguard_contains "-l --label" $prev; then return 0 fi opts="$opts -d --show-devices -l --label" ;; allow-device|block-device|reject-device) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then opts=$(_usbguard_get_ids || :) else opts="$opts -p --permanent" fi ;; append-rule) if _usbguard_contains "-a --after" $prev; then opts=$(_usbguard_get_rules || :) elif ! _usbguard_in_option && [[ $args -eq 2 ]]; then return 0 else opts="$opts -a --after -t --temporary" fi ;; remove-rule) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then opts=$(_usbguard_get_rules || :) fi ;; generate-policy) if _usbguard_contains "-d --devpath" $prev; then _filedir return 0 elif _usbguard_contains "-t --target" $prev; then opts="allow block reject" elif _usbguard_contains "-b --usbguardbase -o --objectclass -n --name-prefix" $prev; then return 0 else opts="$opts -p --with-ports -P --no-ports-sn -d --devpath -t --target -X --no-hashes" opts="$opts -H --hash-only -L --ldif -b --usbguardbase -o --objectclass -n --name-prefix" fi ;; watch) if _usbguard_contains "-e --exec" $prev; then _filedir return 0 fi opts="$opts -w --wait -o --once -e --exec" ;; read-descriptor) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then _filedir return 0 fi ;; add-user) value_options="-p --policy -d --devices -e --exceptions -P --parameters" _count_args "" "@(${value_options// /|})" if _usbguard_contains "$value_options" $prev; then _usbguard_comp_list "modify list listen" 3 return 0 elif ! _usbguard_in_option && [[ $args -eq 2 ]]; then _usergroup return 0 else opts="$opts -u --user -g --group $value_options" fi ;; remove-user) if ! _usbguard_in_option && [[ $args -eq 2 ]]; then _usergroup return 0 fi opts="$opts -u --user -g --group" ;; *) ;; esac fi _usbguard_filter "opts" _usbguard_filter_shorts "opts" mapfile -t COMPREPLY < <(compgen -W "${opts}" -- "${cur}") return 0 } complete -F _usbguard usbguard ================================================ FILE: scripts/copr-build-srpm.sh ================================================ #!/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: Daniel Kopecek # CURL=$(which curl) JQ=$(which jq) if [ -z "$CURL" ]; then echo "Required curl command missing. Aborting." exit 1 fi if [ -z "$JQ" ]; then echo "Required jq command missing. Aborting." exit 1 fi COPR_URL_API2="https://copr.fedorainfracloud.org/api_2/" COPR_LOGIN="${COPR_LOGIN:=invalidlogin}" COPR_TOKEN="${COPR_TOKEN:=invalidtoken}" COPR_PROJECT_ID="${COPR_PROJECT_ID:=0}" SRPM="$1" if [ -z "$SRPM" ]; then echo "Usage: $(basename $0) " exit 1 fi echo "[+] Fetching project chroots..." # # Fetch project chroots # COPR_PROJECT_CHROOTS=$( $CURL -o - -s "https://copr.fedorainfracloud.org/api_2/projects/${COPR_PROJECT_ID}/chroots" | \ $JQ -c '[ .chroots | .[] | .chroot | .name ]' ) if [ $? -ne 0 ]; then echo "[!] FAILED: Can't retrieve list of project chroots. Aborting." exit 1 fi COPR_BUILD_METADATA="{ \"project_id\": ${COPR_PROJECT_ID}, \"chroots\": $COPR_PROJECT_CHROOTS, \"enable_net\": false }" echo "[+] Submitting SRPM for build: $SRPM" # # Upload and build the srpm # COPR_RESPONSE=$($CURL \ -s \ --basic -u $COPR_LOGIN:$COPR_TOKEN \ -F "metadata=$COPR_BUILD_METADATA" \ -F "srpm=@$SRPM;type=application/x-rpm" \ -i \ -o - \ "$COPR_URL_API2/builds") if [ $? -ne 0 ]; then echo "[!] FAILED: Unable to submit the srpm. Server responded:" echo "$COPR_RESPONSE" exit 1 else echo "[+] Build successfully submitted. Server responded:" echo "$COPR_RESPONSE" fi ================================================ FILE: scripts/docker/build_on_alpine_linux_3_21.Dockerfile ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . FROM alpine:3.21 RUN echo '@edge-testing https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \ && \ apk add --update \ asciidoc \ autoconf \ automake \ bash \ dbus-glib-dev \ file \ g++ \ gcc \ git \ libgcrypt-dev \ libqb-dev@edge-testing \ libsodium-dev \ libtool \ make \ musl-dev \ pegtl@edge-testing \ pkgconf \ polkit-dev \ protobuf-dev \ tar ADD usbguard.tar usbguard/ ADD catch.tar usbguard/src/ThirdParty/Catch/ WORKDIR usbguard RUN git init &>/dev/null && ./autogen.sh RUN ./configure --with-bundled-catch || ! cat config.log RUN make dist RUN tar --version RUN tar xf usbguard-*.tar.gz RUN mv -v usbguard-*.*.*/ usbguard-release/ RUN mkdir usbguard-release/build/ WORKDIR usbguard-release/build/ RUN ../configure --with-bundled-catch || ! cat config.log RUN bash -c 'set -o pipefail; make V=1 "-j$(nproc)" |& tee build.log' RUN ! grep -F 'include file not found' build.log ================================================ FILE: scripts/docker/build_on_centos_8_2.Dockerfile ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . FROM centos:8.2.2004 RUN sed \ -e '/^baseurl=.*/d' \ -e 's,^mirrorlist=.*repo=\([^&]\+\).*,baseurl=http://linuxsoft.cern.ch/centos-vault/8.2.2004/\1/x86_64/os/,' \ -i /etc/yum.repos.d/CentOS-* \ && \ dnf clean metadata \ && \ dnf install -y epel-release dnf-plugins-core \ && \ dnf config-manager --set-enabled PowerTools \ && \ dnf install -y \ asciidoc \ autoconf \ automake \ dbus-glib-devel \ diffutils \ file \ gcc-c++ \ git \ libgcrypt-devel \ libqb-devel \ libsodium-devel \ libtool \ libxslt \ make \ polkit-devel \ protobuf-compiler \ protobuf-devel ADD usbguard.tar usbguard/ ADD catch.tar usbguard/src/ThirdParty/Catch/ ADD pegtl.tar usbguard/src/ThirdParty/PEGTL/ WORKDIR usbguard RUN git init &>/dev/null && ./autogen.sh RUN ./configure --with-bundled-catch --with-bundled-pegtl || ! cat config.log RUN make dist RUN tar xf usbguard-*.tar.gz RUN mv -v usbguard-*.*.*/ usbguard-release/ RUN mkdir usbguard-release/build/ WORKDIR usbguard-release/build/ RUN ../configure --with-bundled-catch --with-bundled-pegtl || ! cat config.log RUN bash -c 'set -o pipefail; make V=1 "-j$(nproc)" |& tee build.log' RUN ! grep -F 'include file not found' build.log ================================================ FILE: scripts/docker/build_on_debian_buster_with_gcc_9_2.Dockerfile ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . FROM gcc:9.2 SHELL ["/bin/bash", "-c"] RUN head -n1 /etc/os-release \ && \ apt-get update \ && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes -V \ asciidoc \ autoconf \ automake \ bash-completion \ build-essential \ docbook-xml \ docbook-xsl \ git \ ldap-utils \ libaudit-dev \ libcap-ng-dev \ libdbus-glib-1-dev \ libldap-dev \ libpolkit-gobject-1-dev \ libprotobuf-dev \ libqb-dev \ libseccomp-dev \ libsodium-dev \ libtool \ libxml2-utils \ libumockdev-dev \ pkg-config \ protobuf-compiler \ sudo \ systemd \ tao-pegtl-dev \ xsltproc RUN set -x \ && \ [[ "$(gcc -dumpversion) == 9.2.* ]] \ && \ [[ "$(g++ -dumpversion) == 9.2.* ]] ADD usbguard.tar usbguard/ ADD catch.tar usbguard/src/ThirdParty/Catch/ WORKDIR usbguard RUN git init &>/dev/null && ./autogen.sh RUN ./configure --enable-systemd --with-bundled-catch || ! cat config.log RUN make dist RUN tar xf usbguard-*.tar.gz RUN mv -v usbguard-*.*.*/ usbguard-release/ RUN mkdir usbguard-release/build/ WORKDIR usbguard-release/build/ RUN ../configure --enable-systemd --with-bundled-catch || ! cat config.log RUN bash -c 'set -o pipefail; make V=1 "-j$(nproc)" |& tee build.log' RUN ! grep -F 'include file not found' build.log RUN make V=1 check || { cat src/Tests/test-suite.log ; false ; } ================================================ FILE: scripts/docker/build_on_ubuntu_22_04.Dockerfile ================================================ ## ## Copyright (c) 2022 Sebastian Pipping ## ## 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 . FROM ubuntu:22.04 RUN apt-get update \ && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes -V \ asciidoc \ autoconf \ automake \ bash-completion \ build-essential \ catch2 \ docbook-xml \ docbook-xsl \ git \ ldap-utils \ libaudit-dev \ libcap-ng-dev \ libdbus-glib-1-dev \ libldap-dev \ libpolkit-gobject-1-dev \ libprotobuf-dev \ libqb-dev \ libseccomp-dev \ libsodium-dev \ libtool \ libxml2-utils \ libumockdev-dev \ pkg-config \ protobuf-compiler \ sudo \ systemd \ tao-pegtl-dev \ xsltproc ADD usbguard.tar usbguard/ WORKDIR usbguard RUN git init &>/dev/null && ./autogen.sh RUN ./configure --enable-systemd || ! cat config.log RUN make dist RUN tar xf usbguard-*.tar.gz RUN mv -v usbguard-*.*.*/ usbguard-release/ RUN mkdir usbguard-release/build/ WORKDIR usbguard-release/build/ RUN ../configure --enable-systemd || ! cat config.log RUN bash -c 'set -o pipefail; make V=1 "-j$(nproc)" |& tee build.log' RUN ! grep -F 'include file not found' build.log RUN make V=1 check || { cat src/Tests/test-suite.log ; false ; } ================================================ FILE: scripts/docker/build_on_ubuntu_25_04.Dockerfile ================================================ ## ## Copyright (c) 2025 Sebastian Pipping ## ## 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 . FROM ubuntu:25.04 RUN apt-get update \ && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes -V \ asciidoc \ autoconf \ automake \ bash-completion \ build-essential \ catch2 \ docbook-xml \ docbook-xsl \ g++-15 \ gcc-15 \ git \ ldap-utils \ libaudit-dev \ libcap-ng-dev \ libdbus-glib-1-dev \ libldap-dev \ libpolkit-gobject-1-dev \ libprotobuf-dev \ libqb-dev \ libseccomp-dev \ libsodium-dev \ libtool \ libxml2-utils \ libumockdev-dev \ pkg-config \ protobuf-compiler \ sudo \ systemd-dev \ tao-pegtl-dev \ xsltproc ADD usbguard.tar usbguard/ WORKDIR usbguard RUN git init &>/dev/null && ./autogen.sh RUN ./configure --enable-systemd CC=gcc-15 CXX=g++-15 || ! cat config.log RUN make dist RUN tar xf usbguard-*.tar.gz RUN mv -v usbguard-*.*.*/ usbguard-release/ RUN mkdir usbguard-release/build/ WORKDIR usbguard-release/build/ RUN ../configure --enable-systemd CC=gcc-15 CXX=g++-15 || ! cat config.log RUN bash -c 'set -o pipefail; make V=1 "-j$(nproc)" |& tee build.log' RUN ! grep -F 'include file not found' build.log RUN make V=1 check || { cat src/Tests/test-suite.log ; false ; } ================================================ FILE: scripts/ldap/ldap.sh ================================================ #!/bin/bash set -e BASE="dc=example,dc=com" USER="cn=Manager,$BASE" HOST="192.168.122.83" PASS="passme" ping -q -c 1 $HOST 2>&1 >/dev/null if [ "$1" = "delete" ]; then ldapdelete -H "ldap://${HOST}/" -D $USER -w $PASS -r $BASE exit fi if [ "$1" = "setup" ]; then ldapadd -v -H "ldap://${HOST}/" -D $USER -w $PASS -f ./setup.ldif exit fi if [ "$1" = "policy" ]; then POLICY='./usbguard-policy.ldif' if [ "$2" ]; then POLICY=$2 fi ldapadd -v -H "ldap://${HOST}/" -D $USER -w $PASS -f $POLICY exit fi if [ "$1" = "search" ]; then FILTER='objectclass=*' if [ "$2" ]; then FILTER=$2 fi ldapsearch -H "ldap://${HOST}/" -D $USER -b $BASE -w $PASS $FILTER exit fi ================================================ FILE: scripts/ldap/schema2ldif.pl ================================================ #!/usr/bin/env perl # Converts OpenLDAP schema from traditional slapd.conf format to LDIF format # usable for importing into cn=config. # # Copyright (c) 2012-2016 Mantas Mikulėnas # Released under the MIT license use warnings; use strict; my $name = shift(@ARGV) // "UNNAMED-SCHEMA"; my $unwrap = 0; print "dn: cn=$name,cn=schema,cn=config\n"; print "objectClass: olcSchemaConfig\n"; my $key; my $value; while () { if (/^(attributeType(?:s)?|objectClass(?:es)?) (.+)$/i) { if ($key && $value) { print "$key: $value\n"; } ($key, $value) = ($1, $2); if ($key =~ /^attributeType(s)?$/i) { $key = "olcAttributeTypes"; } elsif ($key =~ /^objectClass(es)?$/i) { $key = "olcObjectClasses"; } else { $key = "olc$key"; } } elsif (/^\s+(.+)$/) { if ($unwrap) { $value .= " $1"; } else { $value .= "\n $&"; } } elsif (/^#.*/) { print "$&\n"; } elsif (/.+/) { warn "$.:unrecognized input line: $&\n"; } } if ($key && $value) { print "$key: $value\n"; } ================================================ FILE: scripts/ldap/setup.ldif ================================================ dn: dc=test,dc=com objectclass: dcObject objectclass: organization dc: test o: "Test server" dn: ou=USBGuard,dc=test,dc=com objectClass: top objectClass: organizationalUnit ou: USBGuard ================================================ FILE: scripts/ldap/usbguard-policy.ldif ================================================ dn: cn=Rule1,ou=USBGuard,dc=test,dc=com objectClass: USBGuardPolicy objectClass: top cn: Rule1 RuleType: allow USBGuardHost: Axis USBGuardOrder: 0 DeviceID: 1038:1702 DeviceSerial: "" DeviceWithConnectType: "hotplug" DeviceName: "SteelSeries Rival 100 Gaming Mouse" DeviceHash: "Ty9aMqdLp96HdR+3R3oFUeWy250MhWmb8zznl5+uHWk=" DeviceParentHash: "OkrTUwAUxn55t8+ezGtkhdgxjz9TIluGUS+bjFE+iC4=" DeviceViaPort: "2-3" dn: cn=Rule2,ou=USBGuard,dc=test,dc=com objectClass: USBGuardPolicy objectClass: top cn: Rule2 RuleType: allow USBGuardHost: * USBGuardHost: !Axis USBGuardOrder: 1 DeviceID: 1038:1702 DeviceSerial: "" DeviceName: "Keyboard..." DeviceHash: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=" DeviceParentHash: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=" DeviceWithInterface: { 03:01:01 03:00:00 03:00:00 } dn: cn=Rule3,ou=USBGuard,dc=test,dc=com objectClass: USBGuardPolicy objectClass: top cn: Rule3 RuleType: allow USBGuardHost: * USBGuardOrder: 6 DeviceID: 1038:1702 DeviceSerial: "" DeviceName: "Flash" DeviceHash: "ccccccccccccccccccccccccccccccccccccccccccccc=" DeviceParentHash: "ddddddddddddddddddddddddddddddddddddddddddddd=" dn: cn=Rule4,ou=USBGuard,dc=test,dc=com objectClass: USBGuardPolicy objectClass: top cn: Rule4 RuleType: allow USBGuardHost: * USBGuardOrder: 2 ================================================ FILE: scripts/ldap/usbguard.ldif ================================================ dn: cn=usbguard,cn=schema,cn=config objectClass: olcSchemaConfig cn: usbguard olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.1 NAME 'USBGuardRuleTarget' DESC 'Hostname for USBGuard host' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.2 NAME 'USBGuardHost' DESC 'Hostname for USBGuard host' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.3 NAME 'USBGuardRuleOrder' DESC 'an integer to order the USBGuard Policy entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.4 NAME 'USBID' DESC 'USB device ID' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.5 NAME 'USBSerial' DESC 'USB device Serial' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.6 NAME 'USBWithConnectType' DESC 'USB device With-Connect-Type' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.7 NAME 'USBName' DESC 'USB device Name' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.8 NAME 'USBHash' DESC 'USB device hash' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.9 NAME 'USBParentHash' DESC 'USB device ParentHash' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.10 NAME 'USBViaPort' DESC 'USB device ViaPort' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.11 NAME 'USBWithInterface' DESC 'USB device With-Interface' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15955.9.1.12 NAME 'USBGuardRuleCondition' DESC 'Condition' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcObjectClasses: ( 1.3.6.1.4.1.15955.9.1.1 NAME 'USBGuardPolicy' SUP top STRUCTURAL DESC 'USBGuard Policy' MUST ( cn $ USBGuardRuleTarget $ USBGuardHost $ USBGuardRuleOrder ) MAY ( USBID $ USBSerial $ USBWithConnectType $ USBName $ USBHash $ USBParentHash $ USBViaPort $ USBWithInterface $ USBGuardRuleCondition $ description ) ) ================================================ FILE: scripts/ldap/usbguard.schema ================================================ attributetype ( 1.3.6.1.4.1.15955.9.1.1 NAME 'USBGuardRuleTarget' DESC 'Hostname for USBGuard host' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.2 NAME 'USBGuardHost' DESC 'Hostname for USBGuard host' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.3 NAME 'USBGuardRuleOrder' DESC 'an integer to order the USBGuard Policy entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) attributetype ( 1.3.6.1.4.1.15955.9.1.4 NAME 'USBID' DESC 'USB device ID' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.5 NAME 'USBSerial' DESC 'USB device Serial' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.6 NAME 'USBWithConnectType' DESC 'USB device With-Connect-Type' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.7 NAME 'USBName' DESC 'USB device Name' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.8 NAME 'USBHash' DESC 'USB device hash' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.9 NAME 'USBParentHash' DESC 'USB device ParentHash' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.10 NAME 'USBViaPort' DESC 'USB device ViaPort' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.11 NAME 'USBWithInterface' DESC 'USB device With-Interface' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.15955.9.1.12 NAME 'USBGuardRuleCondition' DESC 'Condition' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) objectclass ( 1.3.6.1.4.1.15955.9.1.1 NAME 'USBGuardPolicy' SUP top STRUCTURAL DESC 'USBGuard Policy' MUST ( cn $ USBGuardRuleTarget $ USBGuardHost $ USBGuardRuleOrder ) MAY ( USBID $ USBSerial $ USBWithConnectType $ USBName $ USBHash $ USBParentHash $ USBViaPort $ USBWithInterface $ USBGuardRuleCondition $ description ) ) ================================================ FILE: scripts/modeline.vim ================================================ set ts=2 sw=2 et ================================================ FILE: scripts/reformat-sources.sh ================================================ #!/bin/bash # # 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 # PROJECT_ROOT="$(dirname "$0")/../" ASTYLE="${PROJECT_ROOT}/scripts/astyle.sh" echo echo " PLEASE READ:" echo " ============" echo " This script requires AStyle version 3 and above." echo " Older versions won't work correctly (or not at all)." echo " ============" echo set -ex find "${PROJECT_ROOT}/src" \ -type f -not -path '*ThirdParty/*' \ -not \( -name \*.pb.h -o -name build-config.h \) \ \( -name '*.cpp' -or -name '*.hpp' -or -name '*.c' -or -name '*.h' \) \ -exec "${ASTYLE}" --preserve-date --suffix=none --lineend=linux --formatted "{}" \; ================================================ FILE: scripts/rule-generator.sh ================================================ #!/bin/sh # # 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 # TARGET=(allow block reject) function generate_target { echo -n ${TARGET[$RANDOM % 3]} } OPERATORS=(equals one-of none-of all-of equals-ordered match-all) function generate_hex { size=$1 cat /dev/urandom | tr -d -c '[:xdigit:]' | head -c $size } function generate_interface_type { case $(( RANDOM % 3 )) in 0) generate_hex 2 echo -n ':' generate_hex 2 echo -n ':' generate_hex 2 ;; 1) generate_hex 2 echo -n ':' generate_hex 2 echo -n ':*' ;; 2) generate_hex 2 echo -n ':*:*' ;; esac } function generate_device_id { generate_hex 4 echo -n ":" (( RANDOM % 2 )) && generate_hex 4 || echo -n '*' } function generate_string { if [[ -n "$1" ]]; then size=$1 else size=8 fi cat /dev/urandom | tr -d -c '[:print:]' | tr -d '"\\()' | head -c $size } function generate_dq_string { echo -n '"' generate_string echo -n '"' } function generate_operator { echo -n ${OPERATORS[$RANDOM % 5]} } function generate_set { if [ -n "$2" ]; then size=$2 else size=$((RANDOM % 8 + 1)) fi (( RANDOM % 2 )) && (generate_operator && echo -n " ") echo -n "{ " for i in $(seq $size); do $1 echo -n " " done echo -n "}" } function generate_string_attribute { name=$1 echo -n $name echo -n " " case $((RANDOM % 2)) in 0) generate_dq_string ;; 1) generate_set generate_dq_string ;; esac } function generate_interface_attribute { echo -n "with-interface" echo -n " " case $((RANDOM % 2)) in 0) generate_interface_type ;; 1) generate_set generate_interface_type ;; esac } function generate_id_attribute { echo -n "id" echo -n " " case $((RANDOM % 2)) in 0) generate_device_id ;; 1) generate_set generate_device_id ;; esac } generated=(0 0 0 0 0 0 0) function generate_attribute { while true; do rnd=$((RANDOM % 7)) if [ ${generated[$rnd]} -eq 0 ]; then generated[$rnd]=1 break fi done case "$rnd" in 0) generate_string_attribute "name" ;; 1) generate_string_attribute "hash" ;; 2) generate_string_attribute "parent-hash" ;; 3) generate_string_attribute "serial" ;; 4) generate_string_attribute "via-port" ;; 5) generate_interface_attribute ;; 6) generate_id_attribute ;; esac } function generate_condition { case $((RANDOM % 13)) in 0) echo -n "if true" ;; 1) echo -n "if !true" ;; 2) echo -n "if false" ;; 3) echo -n "if !false" ;; 4) echo -n "if localtime(1:00)" ;; 5) echo -n "if !localtime(2:00)" ;; 6) echo -n "if " generate_operator echo -n " { true false !true false }" ;; 8) echo -n "if random" ;; 9) echo -n "if random(0.4)" ;; 10) echo -n "if rule-applied" ;; 11) echo -n "if rule-evaluated" ;; 12) echo -n "if allowed-matches(name " generate_dq_string echo -n ")" ;; esac } function generate_rule { num_attributes=$1 generate_target echo -n " " for i in $(seq $num_attributes); do generate_attribute echo -n " " done (( RANDOM % 2 )) && (echo -n ' '; generate_condition) } if [ -n "$1" ]; then num_attributes=$1 else num_attributes=$((RANDOM % 7 + 1)) fi generate_rule $num_attributes echo ================================================ FILE: scripts/usb-descriptor-collect.sh ================================================ #!/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: Daniel Kopecek # set -e -o pipefail SED=$(which sed) FIND=$(which find) LSUSB=$(which lsusb) SHA1SUM=$(which sha1sum) TAR=$(which tar) MKTEMP=$(which mktemp) CP=$(which cp) WC=$(which wc) RM=$(which rm) TEMPDIR=$($MKTEMP -d --tmpdir usb-descriptor-collect.XXXXXX || (echo "Failed to create temporary directory"; exit 1)) ROOTDIR="$TEMPDIR/usb-descriptor-data" mkdir $ROOTDIR || (echo "Failed to create data root directory: $ROOTDIR"; exit 1) for dev_syspath in $($FIND /sys/bus/usb/devices/ -regex '.*/[0-9]+-[0-9]+\(\.[0-9]+\)*$' -o -regex '.*/usb[0-9]+$'); do echo "Collecting data from $dev_syspath" pushd "$dev_syspath" dev_bus=$(< busnum) dev_num=$(< devnum) echo " busnum: $dev_bus" echo " devnum: $dev_num" count_c=$($LSUSB -s $dev_bus:$dev_num -v 2> /dev/null | $SED -n 's|Configuration Descriptor|&|p' | $WC -l) count_i=$($LSUSB -s $dev_bus:$dev_num -v 2> /dev/null | $SED -n 's|Interface Descriptor|&|p' | $WC -l) count_e=$($LSUSB -s $dev_bus:$dev_num -v 2> /dev/null | $SED -n 's|Endpoint Descriptor|&|p' | $WC -l) echo " count_c: $count_c" echo " count_i: $count_i" echo " count_e: $count_e" descriptor_hash=$($SHA1SUM descriptors | $SED -n 's|^\([a-fA-F0-9]\{40\}\).*$|\1|p') echo " hash: $descriptor_hash" echo "count_c: $count_c" > "$ROOTDIR/$descriptor_hash.log" echo "count_i: $count_i" >> "$ROOTDIR/$descriptor_hash.log" echo "count_e: $count_e" >> "$ROOTDIR/$descriptor_hash.log" $CP -f descriptors "$ROOTDIR/$descriptor_hash.bin" popd done ARCHIVE_PATH="$TEMPDIR/usb-descriptor-data.tar.gz" echo "Creating data archive: $ARCHIVE_PATH" pushd "$TEMPDIR" $TAR zcvf $ARCHIVE_PATH usb-descriptor-data popd $RM -rf "$TEMPDIR/usb-descriptor-data" echo "=========================================" echo echo " Data collection complete!" echo " Please send the data archive to dnk.usbdev@gmail.com" echo echo " Archive path: $ARCHIVE_PATH" echo echo " Thanks!" echo echo "=========================================" ================================================ FILE: scripts/usbguard-zsh-completion ================================================ #compdef usbguard #autoload # usbguard completion, based on cli help text local curcontext="$curcontext" state line ret=1 local -a _command_args local -a _global_args local -a _subcommands local IFS=$'\n' _global_args=($(usbguard advanced | grep '^\s*--' | sed -r 's/^[\t ]*(--[^\t ,]+)( [^\t ,]*)?,? ?(--?[^\t ]+)?[\t ]*(.*)$/(\3)\1[\4]/')) _arguments -C -A "-v" -A "--version"\ '(- 1 *)'{-v,--version}'[display version information]' \ '1: :->cmds' \ $_global_args \ '*:: :->args' && ret=0 case $state in cmds) _subcommands=( "get-parameter:Get the value of a runtime parameter." "set-parameter:Set the value of a runtime parameter." "list-devices:List all USB devices recognized by the USBGuard daemon." "allow-device:Authorize a device to interact with the system." "block-device:Deauthorize a device." "reject-device:Deauthorize and remove a device from the system." "list-rules:List the rule set (policy) used by the USBGuard daemon." "append-rule:Append a rule to the rule set." "remove-rule:Remove a rule from the rule set." "generate-policy:Generate a rule set (policy) based on the connected USB devices." "watch:Watch for IPC interface events and print them to stdout." "read-descriptor:Read a USB descriptor from a file and print it in human-readable form." "add-user:Add USBGuard IPC user/group (requires root privileges)" "remove-user:Remove USBGuard IPC user/group (requires root privileges)" ) _describe -t subcommands 'usbguard subcommands' _subcommands && ret=0 ;; args) case $line[1] in help) _values 'commands' \ 'get-parameter' \ 'set-parameter' \ 'list-devices' \ 'allow-device' \ 'block-device' \ 'reject-device' \ 'list-rules' \ 'append-rule' \ 'remove-rule' \ 'generate-policy' \ 'watch' \ 'read-descriptor' \ 'add-user' \ 'remove-user' && ret=0 ;; get-parameter) _values "command" \ '[name]' _command_args=( \ '(--help)--help[Show help]' ) ;; set-parameter) _values "command" \ '[name]' \ '[value]' _command_args=( \ '(--verbose)--verbose[Print the previous and new attribute value]' \ '(--help)--help[Show help]' ) ;; list-devices) _command_args=( \ '(--allowed)--allowed[List allowed devices]' \ '(--blocked)--blocked[List blocked devices]' \ '(--help)--help[Show help]' ) ;; allow-device) _values "command" \ '[device-id]' _command_args=( \ '(--permanent)--permanent[Make the decision permanent]' \ '(--help)--help[Show help]' ) ;; block-device) _values "command" \ '[device-id]' _command_args=( \ '(--permanent)--permanent[Make the decision permanent]' \ '(--help)--help[Show help]' ) ;; reject-device) _values "command" \ '[device-id]' _command_args=( \ '(--permanent)--permanent[Make the decision permanent]' \ '(--help)--help[Show help]' ) ;; list-rules) _command_args=( \ '(--help)--help[Show help]' ) ;; append-rule) _values "command" \ '[rule]' _command_args=( \ '(--after)--after [Append the new rule after a rule with the specified id instead of appending it]' \ '(--help)--help[Show help]' ) ;; remove-rule) _values "command" \ '[device-id]' _command_args=( \ '(--help)--help[Show help]' ) ;; generate-policy) _command_args=( \ '(--with-ports-sn)--with-ports-sn[Generate port specific rules for all devices]' \ '(--no-ports-sn)--no-ports-sn[Do not generate port specific rule for devices without an iSerial value]' \ '(--target)--target [Generate an explicit "catch all" rule with the specified target (allow, block, reject)]' \ '(--no-hashes)--no-hashes[Do not generate a hash attribute for each device]' \ '(--hash-only)--hash-only[Generate a hash-only policy]' \ '(--help)--help[Show help]' ) ;; get-parameter) _command_args=( \ '(--wait)--wait[Wait for IPC connection to become available]' \ '(--once)--once[Wait only when starting, if needed. Exit when the connection is lost]' \ '(--help)--help[Show help]' ) ;; read-descriptor) _values "command" \ '[name]' _command_args=( \ '(--help)--help[Show help]' ) ;; add-user) _values "command" \ '[name]' _command_args=( \ '(--user)--user[The specified name represents a username or UID (default)]' \ '(--group)--group[The specified name represents a groupname or GID]' \ '(--policy)--policy [Policy related privileges]' \ '(--devices)--devices [Device related privileges]' \ '(--exceptions)--exceptions [Exceptions related privileges]' \ '(--parameters)--parameters [Run-time parameter related privileges]' \ '(--no-root-check)--no-root-check[Disable root privileges checking]' \ '(--help)--help[Show help]' ) ;; remove-user) _values "command" \ '[name]' _command_args=( \ '(--user)--user[The specified name represents a username or UID (default)]' \ '(--group)--group[The specified name represents a groupname or GID]' \ '(--no-root-check)--no-root-check[Disable root privileges checking]' \ '(--help)--help[Show help]' ) ;; esac ;; esac _arguments \ $_command_args \ && ret=0 return ret ================================================ FILE: src/.gitignore ================================================ /build-config.h /build-config.h.in ================================================ FILE: src/CLI/IPCSignalWatcher.cpp ================================================ // // 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 "IPCSignalWatcher.hpp" #include "usbguard/Exception.hpp" #include #include #include #include #include #include namespace usbguard { IPCSignalWatcher::~IPCSignalWatcher() { if (hasOpenExecutable()) { closeExecutable(); } } void IPCSignalWatcher::setExecutable(const std::string& path) { if (hasOpenExecutable()) { closeExecutable(); } openExecutable(path); } void IPCSignalWatcher::IPCConnected() { std::cout << "[IPC] Connected" << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "IPC.Connected" } }; runExecutable(env); } } void IPCSignalWatcher::IPCDisconnected(bool exception_initiated, const IPCException& exception) { std::cout << "[IPC] Disconnected: exception_initiated=" << exception_initiated; if (exception_initiated) { std::cout << " message=" << exception.message(); } std::cout << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "IPC.Disconnected" }, { "USBGUARD_MESSAGE", exception_initiated ? exception.message() : "" } }; runExecutable(env); } } void IPCSignalWatcher::DevicePresenceChanged(uint32_t id, DeviceManager::EventType event, Rule::Target target, const std::string& device_rule) { std::cout << "[device] PresenceChanged: id=" << id << std::endl; std::cout << " event=" << DeviceManager::eventTypeToString(event) << std::endl; std::cout << " target=" << Rule::targetToString(target) << std::endl; std::cout << " device_rule=" << device_rule << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "Device.PresenceChanged" }, { "USBGUARD_DEVICE_ID", std::to_string(id) }, { "USBGUARD_DEVICE_EVENT", DeviceManager::eventTypeToString(event) }, { "USBGUARD_DEVICE_TARGET", Rule::targetToString(target) }, { "USBGUARD_DEVICE_RULE", device_rule } }; runExecutable(env); } } void IPCSignalWatcher::DevicePolicyChanged(uint32_t id, Rule::Target target_old, Rule::Target target_new, const std::string& device_rule, uint32_t rule_id) { std::cout << "[device] PolicyChanged: id=" << id << std::endl; std::cout << " target_old=" << Rule::targetToString(target_old) << std::endl; std::cout << " target_new=" << Rule::targetToString(target_new) << std::endl; std::cout << " device_rule=" << device_rule << std::endl; std::cout << " rule_id=" << rule_id << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "Device.PolicyChanged" }, { "USBGUARD_DEVICE_ID", std::to_string(id) }, { "USBGUARD_DEVICE_TARGET_OLD", Rule::targetToString(target_old) }, { "USBGUARD_DEVICE_TARGET_NEW", Rule::targetToString(target_new) }, { "USBGUARD_DEVICE_RULE", device_rule }, { "USBGUARD_DEVICE_RULE_ID", std::to_string(rule_id) } }; runExecutable(env); } } void IPCSignalWatcher::DevicePolicyApplied(uint32_t id, Rule::Target target_new, const std::string& device_rule, uint32_t rule_id) { std::cout << "[device] PolicyApplied: id=" << id << std::endl; std::cout << " target_new=" << Rule::targetToString(target_new) << std::endl; std::cout << " device_rule=" << device_rule << std::endl; std::cout << " rule_id=" << rule_id << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "Device.PolicyApplied" }, { "USBGUARD_DEVICE_ID", std::to_string(id) }, { "USBGUARD_DEVICE_TARGET_NEW", Rule::targetToString(target_new) }, { "USBGUARD_DEVICE_RULE", device_rule }, { "USBGUARD_DEVICE_RULE_ID", std::to_string(rule_id) } }; runExecutable(env); } } void IPCSignalWatcher::PropertyParameterChanged(const std::string& name, const std::string& value_old, const std::string& value_new) { std::cout << "[property] ParameterChanged: name=" << name << std::endl; std::cout << " value_old=" << value_old << std::endl; std::cout << " value_new=" << value_new << std::endl; if (hasOpenExecutable()) { const std::map env = { { "USBGUARD_IPC_SIGNAL", "Property.ParameterChanged" }, { "USBGUARD_PROPERTY_NAME", name }, { "USBGUARD_PROPERTY_VALUE_OLD", value_old }, { "USBGUARD_PROPERTY_VALUE_NEW", value_new } }; runExecutable(env); } } void IPCSignalWatcher::openExecutable(const std::string& path) { const int fd = ::open(path.c_str(), O_RDONLY); if (fd < 0) { throw ErrnoException("openExecutable", path, errno); } struct ::stat st = { }; if (::fstat(fd, &st) != 0) { ::close(fd); throw ErrnoException("openExecutable", path, errno); } if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) { ::close(fd); throw Exception("openExecutable", path, "not an executable file"); } _exec_path = path; _exec_path_fd = fd; } void IPCSignalWatcher::closeExecutable() { _exec_path.clear(); (void)::close(_exec_path_fd); } bool IPCSignalWatcher::hasOpenExecutable() const { return (_exec_path_fd >= 0); } void IPCSignalWatcher::runExecutable(const std::map& environment) { /* * Fork child process, that will fork again and exec. */ const ::pid_t pid_fork1 = fork(); if (pid_fork1 == -1) { std::cerr << "ERROR: runExecutable: " << strerror(errno) << std::endl; return; } if (pid_fork1 > 0) { /* * Wait for the intermediary process to fork and exit. In case something * fails in the intermediary process, we can retrieve the error code from * the return status. */ int fork1_status = -1; const ::pid_t pid_waited = ::waitpid(pid_fork1, &fork1_status, 0); if (pid_waited == -1) { std::cerr << "ERROR: runExecutable: " << strerror(errno) << std::endl; } else if (WIFEXITED(fork1_status)) { const int fork1_errno = WEXITSTATUS(fork1_status); if (fork1_errno != 0) { std::cerr << "ERROR: runExecutable: " << strerror(errno) << std::endl; } } else if (WIFSIGNALED(fork1_status)) { const int fork1_signal = WTERMSIG(fork1_status); std::cerr << "ERROR: runExecutable: terminated by signal " << fork1_signal << std::endl; } return; } /* * Intermediary process. */ const ::pid_t sid = ::setsid(); if (sid == (::pid_t)-1) { ::_exit(errno); } const ::pid_t pid_fork2 = fork(); if (pid_fork2 == (::pid_t)-1) { ::_exit(errno); } if (pid_fork2 > 0) { ::_exit(0); } char* const exec_argv[] = { &_exec_path[0], nullptr }; char** const exec_envp = createExecutableEnvironment(environment); (void)::fexecve(_exec_path_fd, exec_argv, exec_envp); const int saved_errno = errno; destroyExecutableEnvironment(exec_envp); _exit(saved_errno); } char** IPCSignalWatcher::createExecutableEnvironment(const std::map& environment) { size_t environ_size = 0; if (environ != nullptr) { for (char** global_envp = environ; global_envp[0] != nullptr; ++global_envp) { ++environ_size; } } char** envp = new char* [environ_size + environment.size() + 1]; size_t i = 0; for (; i < environ_size; ++i) { envp[i] = cstrCopy(environ[i]); } for (const auto& map_entry : environment) { std::string environ_value; environ_value.append(map_entry.first); environ_value.append("="); environ_value.append(map_entry.second); envp[i++] = cstrCopy(environ_value.c_str()); } envp[i] = nullptr; return envp; } void IPCSignalWatcher::destroyExecutableEnvironment(char** const envp) { if (envp != nullptr) { char** envp_current = envp; while (envp_current[0] != nullptr) { delete [] envp_current[0]; ++envp_current; } delete [] envp; } } char* IPCSignalWatcher::cstrCopy(const char* c_str) { if (c_str == nullptr) { return nullptr; } const auto c_str_len = ::strlen(c_str); char* c_str_copy = new char [c_str_len + 1]; /* * new throws std::bad_alloc on failure, no need * to check the pointer. */ ::memcpy(c_str_copy, c_str, c_str_len); c_str_copy[c_str_len] = '\0'; return c_str_copy; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/IPCSignalWatcher.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard/IPCClient.hpp" namespace usbguard { class IPCSignalWatcher : public IPCClient { public: ~IPCSignalWatcher(); void setExecutable(const std::string& path); void IPCConnected() override; void IPCDisconnected(bool exception_initiated, const IPCException& exception) override; void DevicePresenceChanged(uint32_t id, DeviceManager::EventType event, Rule::Target target, const std::string& device_rule) override; void DevicePolicyChanged(uint32_t id, Rule::Target target_old, Rule::Target target_new, const std::string& device_rule, uint32_t rule_id) override; void DevicePolicyApplied(uint32_t id, Rule::Target target_new, const std::string& device_rule, uint32_t rule_id) override; void PropertyParameterChanged(const std::string& name, const std::string& value_old, const std::string& value_new) override; private: void openExecutable(const std::string& path); void closeExecutable(); bool hasOpenExecutable() const; void runExecutable(const std::map& environment); static char** createExecutableEnvironment(const std::map& environment); static void destroyExecutableEnvironment(char** const envp); static char* cstrCopy(const char* c_str); std::string _exec_path; int _exec_path_fd {-1}; }; } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/PolicyGenerator.cpp ================================================ // // 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 // Radovan Sroka // #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "PolicyGenerator.hpp" namespace usbguard { PolicyGenerator::PolicyGenerator() { _ruleset.push_back(std::dynamic_pointer_cast(std::make_shared(nullptr))); _with_hash = true; _hash_only = false; _port_specific = false; _port_specific_noserial = true; _devpath = ""; _with_catchall = false; _catchall_target = Rule::Target::Block; _dm = DeviceManager::create(*this, "uevent"); _dm->setEnumerationOnlyMode(true); } void PolicyGenerator::setWithHashAttribute(bool state) { _with_hash = state; } void PolicyGenerator::setHashOnly(bool state) { _hash_only = state; } void PolicyGenerator::setPortSpecificRules(bool state) { _port_specific = state; } void PolicyGenerator::setPortSpecificNoSerialRules(bool state) { _port_specific_noserial = state; } void PolicyGenerator::generate() { if (_devpath.empty()) { _dm->start(); _dm->scan(); } else { _dm->scan(_devpath); } if (_with_catchall) { Rule catchall_rule; catchall_rule.setTarget(_catchall_target); _ruleset.front()->appendRule(catchall_rule); } } const std::vector> PolicyGenerator::refRuleSet() const { return _ruleset; } void PolicyGenerator::setDevpath(const std::string& devpath) { _devpath = devpath; } void PolicyGenerator::setExplicitCatchAllRule(bool state, Rule::Target target) { _with_catchall = state; _catchall_target = target; } void PolicyGenerator::dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) { if (event != DeviceManager::EventType::Present) { /* * Ignore run-time device events */ return; } bool port_specific = _port_specific; /* * If the the global "port specific" flag isn't * set, check the "no iSerial port specific" flag * applicability. */ if (!port_specific && _port_specific_noserial) { port_specific = device->getSerial().empty(); } std::shared_ptr rule = device->getDeviceRule(/*include_port=*/port_specific); /* Remove everything but the hash value for hash-only rules */ if (_hash_only) { std::shared_ptr rule_hashonly(new Rule()); rule_hashonly->setRuleID(rule->getRuleID()); rule_hashonly->setHash(rule->getHash()); rule_hashonly->setParentHash(rule->getParentHash()); if (port_specific) { rule_hashonly->attributeViaPort().set(rule->attributeViaPort().values(), Rule::SetOperator::Equals); } rule = rule_hashonly; } /* Remove the hash attributes if set to do so */ else if (!_with_hash) { rule->attributeHash().clear(); rule->attributeParentHash().clear(); } rule->setTarget(Rule::Target::Allow); _ruleset.front()->appendRule(*rule); } uint32_t PolicyGenerator::dmHookAssignID() { return _ruleset.front()->assignID(); } void PolicyGenerator::dmHookDeviceException(const std::string& message) { USBGUARD_LOG(Error) << message; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/PolicyGenerator.hpp ================================================ // // 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 // Radovan Sroka // #pragma once #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard/DeviceManager.hpp" #include "usbguard/DeviceManagerHooks.hpp" #include "usbguard/Rule.hpp" #include "usbguard/RuleSet.hpp" #include "usbguard/MemoryRuleSet.hpp" namespace usbguard { class PolicyGenerator : public DeviceManagerHooks { public: PolicyGenerator(); void setWithHashAttribute(bool state); void setHashOnly(bool state); void setPortSpecificRules(bool state); void setPortSpecificNoSerialRules(bool state); void setDevpath(const std::string& devpath); void setExplicitCatchAllRule(bool state, Rule::Target target = Rule::Target::Block); void generate(); const std::vector> refRuleSet() const; void dmHookDeviceEvent(DeviceManager::EventType event, std::shared_ptr device) override; uint32_t dmHookAssignID() override; void dmHookDeviceException(const std::string& message) override; private: std::vector> _ruleset; std::shared_ptr _dm; bool _with_hash; bool _hash_only; bool _port_specific; bool _port_specific_noserial; std::string _devpath; bool _with_catchall; Rule::Target _catchall_target; }; } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-add-user.cpp ================================================ // // 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 "usbguard-add-user.hpp" #include "usbguard/USBGuard.hpp" #include "usbguard/IPCServer.hpp" #include #include #include namespace usbguard { static const char* options_short = "hugp:d:e:P:"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "user", no_argument, nullptr, 'u' }, { "group", no_argument, nullptr, 'g' }, { "policy", required_argument, nullptr, 'p' }, { "devices", required_argument, nullptr, 'd' }, { "exceptions", required_argument, nullptr, 'e' }, { "parameters", required_argument, nullptr, 'P' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " add-user [OPTIONS] " << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -u, --user The specified name represents a username or UID (default)." << std::endl; stream << " -g, --group The specified name represents a groupname or GID." << std::endl; stream << " -p, --policy Policy related privileges." << std::endl; stream << " -d, --devices Device related privileges." << std::endl; stream << " -e, --exceptions Exceptions related privileges." << std::endl; stream << " -P, --parameters Run-time parameter related privileges." << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; } static void createIPCAccessControlFile(const std::string& path, const std::string& name, bool is_group, const IPCServer::AccessControl& access_control) { IPCServer::checkAccessControlName(name); const std::string basename = getIPCAccessControlFileBasename(name, is_group); const std::string separator = (path.at(path.size() - 1) == '/' ? "" : "/"); const std::string filepath = path + separator + basename; /* * Ensure that only the owner can read/write the file. */ umask(0177); std::ofstream access_control_stream(filepath); if (!access_control_stream.good()) { throw ErrnoException("createIPCAccessControlFile", filepath, errno); } access_control.save(access_control_stream); return; } int usbguard_add_user(int argc, char* argv[]) { int opt = 0; bool opt_is_group = false; IPCServer::AccessControl access_control; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout); return EXIT_SUCCESS; case 'u': opt_is_group = false; break; case 'g': opt_is_group = true; break; case 'p': access_control.merge(std::string("Policy=").append(optarg)); break; case 'd': access_control.merge(std::string("Devices=").append(optarg)); break; case 'e': access_control.merge(std::string("Exceptions=").append(optarg)); break; case 'P': access_control.merge(std::string("Parameters=").append(optarg)); break; case '?': showHelp(std::cerr); default: return EXIT_FAILURE; } } argv += optind; argc -= optind; if (argc != 1) { showHelp(std::cerr); return EXIT_FAILURE; } if (!(getuid() == 0 && geteuid() == 0)) { USBGUARD_LOG(Error) << "This subcommand requires root privileges. Please retry as root."; return EXIT_FAILURE; } const std::string name(argv[0]); const std::string path(getIPCAccessControlFilesPath()); createIPCAccessControlFile(path, name, opt_is_group, access_control); return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-add-user.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_add_user(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-allow-device.cpp ================================================ // // 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 // Attila Lakatos // #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard.hpp" #include "usbguard-allow-device.hpp" #include "usbguard-apply-device-policy.hpp" #include namespace usbguard { int usbguard_allow_device(int argc, char* argv[]) { return usbguard_apply_device_policy(argc, argv, Rule::Target::Allow); } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-allow-device.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_allow_device(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-append-rule.cpp ================================================ // // 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 "usbguard.hpp" #include "usbguard-append-rule.hpp" #include "usbguard/IPCClient.hpp" #include namespace usbguard { static const char* options_short = "ha:t"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "after", required_argument, nullptr, 'a' }, { "temporary", no_argument, nullptr, 't' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " append-rule [OPTIONS] " << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -a, --after Append the new rule after a rule with the specified id" << std::endl; stream << " instead of appending it at the end of the rule set." << std::endl; stream << " -t, --temporary Make the decision temporary. The rule policy file will not" << std::endl; stream << " be updated." << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; } int usbguard_append_rule(int argc, char* argv[]) { uint32_t parent_id = usbguard::Rule::LastID; bool permanent = true; int opt = 0; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout); return EXIT_SUCCESS; case 'a': parent_id = std::stoul(optarg); break; case 't': permanent = false; break; case '?': showHelp(std::cerr); default: return EXIT_FAILURE; } } argc -= optind; argv += optind; if (argc != 1) { showHelp(std::cerr); return EXIT_FAILURE; } usbguard::IPCClient ipc(/*connected=*/true); const std::string rule_spec = argv[0]; const uint32_t id = ipc.appendRule(rule_spec, parent_id, permanent); std::cout << id << std::endl; return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-append-rule.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_append_rule(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-apply-device-policy.cpp ================================================ // // Copyright (C) 2020 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: Attila Lakatos , Zoltan Fridrich // #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard.hpp" #include "usbguard-apply-device-policy.hpp" #include "Common/Utility.hpp" #include "usbguard/IPCClient.hpp" #include #include namespace usbguard { static const char* options_short = "hp"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "permanent", no_argument, nullptr, 'p' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream, Rule::Target target) { std::string target_string = Rule::targetToString(target); stream << " Usage: " << usbguard_arg0 << " " << target_string << "-device [OPTIONS] ( | | )" << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -p, --permanent Make the decision permanent. A device specific " << target_string << std::endl; stream << " rule will be appended to or updated in the current policy." << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; } static bool isNumeric(const std::string& s) { return !s.empty() && std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); } int usbguard_apply_device_policy(int argc, char** argv, Rule::Target target) { bool permanent = false; int opt = 0; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout, target); return EXIT_SUCCESS; case 'p': permanent = true; break; case '?': showHelp(std::cerr, target); default: return EXIT_FAILURE; } } argc -= optind; argv += optind; if (argc == 0) { showHelp(std::cerr, target); return EXIT_FAILURE; } usbguard::IPCClient ipc(/*connected=*/true); /* If a single numeric argument is supplied interpret it as a rule ID */ if (argc == 1 && isNumeric(std::string(argv[0]))) { uint32_t id = std::stoul(argv[0]); ipc.applyDevicePolicy(id, target, permanent); return EXIT_SUCCESS; } /* * Interpret arguments as a rule/partial-rule */ std::string rule_string; if (argc == 1) { rule_string = argv[0]; } else { std::vector arguments(argv, argv + argc); rule_string = joinElements(arguments.begin(), arguments.end()); } try { /* Check whether rule target has been supplied */ std::string rule_target = rule_string.substr(0, rule_string.find(" ")); Rule::targetFromString(rule_target); } catch (const std::runtime_error& ex) { /* * The rule contains no target => partial rule * Supply a default match target */ rule_string.insert(0, Rule::targetToString(Rule::Target::Match) + " "); } for (auto device_rule : ipc.listDevices(rule_string)) { if (target != device_rule.getTarget()) { uint32_t id = device_rule.getRuleID(); try { ipc.applyDevicePolicy(id, target, permanent); } catch (const usbguard::Exception& ex) { /* * When a parent device is blocked/rejected, all its child * devices are removed from the device map. If we try to apply * device policy to a device whose parent has been * blocked/rejected, therefore this device is not present in * the device map anymore, we will receive an exception. * We ignore such exceptions. */ } } } return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-apply-device-policy.hpp ================================================ // // Copyright (C) 2020 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: Attila Lakatos // #pragma once #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard/RuleParser.hpp" namespace usbguard { int usbguard_apply_device_policy(int argc, char** argv, Rule::Target target); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-block-device.cpp ================================================ // // 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 // Attila Lakatos // #ifdef HAVE_BUILD_CONFIG_H #include #endif #include "usbguard.hpp" #include "usbguard-block-device.hpp" #include "usbguard-apply-device-policy.hpp" #include namespace usbguard { int usbguard_block_device(int argc, char* argv[]) { return usbguard_apply_device_policy(argc, argv, Rule::Target::Block); } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-block-device.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_block_device(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-generate-policy.cpp ================================================ // // 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 // Radovan Sroka // #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 "Common/LDAPUtil.hpp" #include #include namespace usbguard { static const char* options_short = "hpPd:t:HXLb:o:n:"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "with-ports", no_argument, nullptr, 'p' }, { "no-ports-sn", no_argument, nullptr, 'P' }, { "devpath", required_argument, nullptr, 'd' }, { "target", required_argument, nullptr, 't' }, { "hash-only", no_argument, nullptr, 'H' }, { "no-hashes", no_argument, nullptr, 'X' }, { "ldif", no_argument, nullptr, 'L' }, { "usbguardbase", required_argument, nullptr, 'b' }, { "objectclass", required_argument, nullptr, 'o' }, { "name-prefix", required_argument, nullptr, 'n' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " generate-policy [OPTIONS]" << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -p, --with-ports Generate port specific rules for all devices." << std::endl; stream << " -P, --no-ports-sn Don't generate port specific rule for devices" << std::endl; stream << " without an iSerial value." << std::endl; stream << " -d, --devpath Only generate a rule for the device at the specified" << std::endl; stream << " sub path of /sys." << std::endl; stream << " -t, --target Generate an explicit \"catch all\" rule with the" << std::endl; stream << " specified target. Possible targets: allow, block, reject." << std::endl; stream << " -X, --no-hashes Don't generate a hash attribute for each device." << std::endl; stream << " -H, --hash-only Generate a hash-only policy." << std::endl; stream << " -L, --ldif Generate a ldif policy for LDAP." << std::endl; stream << " -b, --usbguardbase Generate a ldif policy for LDAP with this base" << std::endl; stream << " this option is required when --ldif was specified" << std::endl; stream << " -o, --objectclass Generate a ldif policy for LDAP with this objectClass" << std::endl; stream << " -n, --name-prefix Generate a ldif policy for LDAP with this name prefix" << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; } int usbguard_generate_policy(int argc, char** argv) { bool port_specific = false; bool port_specific_noserial = true; std::string devpath = ""; bool with_catchall = false; std::string catchall_target = "block"; bool with_hashes = true; bool only_hashes = false; bool ldif = false; bool with_base = false; std::string base = ""; std::string objclass = "USBGuardPolicy"; std::string name_prefix = "Rule"; int opt = 0; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout); return EXIT_SUCCESS; case 'p': port_specific = true; break; case 'P': port_specific_noserial = false; break; case 'd': devpath = optarg; break; case 't': with_catchall = true; catchall_target = optarg; break; case 'H': only_hashes = true; break; case 'X': with_hashes = false; break; case 'L': ldif = true; break; case 'b': with_base = true; base = optarg; break; case 'o': objclass = optarg; break; case 'n': name_prefix = optarg; break; case '?': showHelp(std::cerr); default: return EXIT_FAILURE; } } PolicyGenerator generator; generator.setWithHashAttribute(with_hashes); generator.setHashOnly(only_hashes); generator.setPortSpecificRules(port_specific); generator.setPortSpecificNoSerialRules(port_specific_noserial); generator.setDevpath(devpath); generator.setExplicitCatchAllRule(with_catchall, Rule::targetFromString(catchall_target)); generator.generate(); auto rulesets = generator.refRuleSet(); char array[HOST_NAME_MAX]; int rc = gethostname(array, HOST_NAME_MAX); std::string hostname; if (rc != -1) { hostname = array; } else { /*TODO maybe some option for setting hostname explicitly * without hostname LDAP query will not work! */ std::cerr << "Cannot get hostname" << std::endl; } if (!ldif) { for (auto ruleset : rulesets) { ruleset->serialize(std::cout); } } else if (ldif && with_base) { std::map values = { {"HOSTNAME", hostname}, {"NAME_PREFIX", name_prefix}, {"USBGUARD_BASE", base}, {"OBJCLASS", objclass} }; LDAPUtil::serializeLDIF(rulesets, std::cout, values); } else { std::cerr << "If you want to generate ldif you must specify USBGuardBase" << std::endl; std::cerr << "USBGuardBase is usually \"ou=USBGuard,\" followed by your LDAP base" << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-generate-policy.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_generate_policy(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-get-parameter.cpp ================================================ // // 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 "usbguard.hpp" #include "usbguard-get-parameter.hpp" #include "usbguard/IPCClient.hpp" #include namespace usbguard { static const char* options_short = "h"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " get-parameter [OPTIONS] " << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; stream << " Parameters:" << std::endl; stream << " ImplicitPolicyTarget - How to treat devices that don't match any rule" << std::endl; stream << " Values: allow, block, reject" << std::endl; stream << " InsertedDevicePolicy - How to treat USB devices that are already connected after the daemon starts" << std::endl; stream << " Values: block, reject, apply-policy" << std::endl; stream << std::endl; } int usbguard_get_parameter(int argc, char* argv[]) { int opt = 0; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout); return EXIT_SUCCESS; case '?': showHelp(std::cerr); default: return EXIT_FAILURE; } } argv += optind; argc -= optind; if (argc != 1) { showHelp(std::cerr); return EXIT_FAILURE; } const std::string name = argv[0]; usbguard::IPCClient ipc(/*connected=*/true); const std::string value = ipc.getParameter(name); std::cout << value << std::endl; return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-get-parameter.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_get_parameter(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-list-devices.cpp ================================================ // // 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 "usbguard.hpp" #include "usbguard-list-devices.hpp" #include "usbguard/IPCClient.hpp" #include #include #include namespace usbguard { static const char* options_short = "habt"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "allowed", no_argument, nullptr, 'a' }, { "blocked", no_argument, nullptr, 'b' }, { "tree", no_argument, nullptr, 't' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " list-devices [OPTIONS]" << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -a, --allowed List allowed devices." << std::endl; stream << " -b, --blocked List blocked devices." << std::endl; stream << " -t, --tree List devices in a tree format." << std::endl; stream << " -h, --help Show this help." << std::endl; stream << std::endl; } /** * @brief Prints list of devices in a classic format * * @param rules Device rules to print */ static void classicFormat(const std::vector& rules) { for (const auto& rule : rules) { std::cout << rule.getRuleID() << ": " << rule.toString() << std::endl; } } /** * @brief Recursively prints the tree nodes * * @param tree Rules organized into a tree structure * @param node Node of a tree * @param prefix Helper string used for prefixing the output */ static void printNode( const std::map>>& tree, const std::pair>& node, const std::string& prefix) { const auto& rule = node.first; const auto& children = node.second; if (rule) { std::cout << rule.getRuleID() << ": " << Rule::targetToString(rule.getTarget()) << " " << rule.getName() << std::endl; } if (children.empty()) { return; } for (unsigned i = 0; i < children.size() - 1; ++i) { std::cout << prefix << "├── "; printNode(tree, tree.at(children[i]), prefix + "│ "); } std::cout << prefix << "└── "; printNode(tree, tree.at(children.back()), prefix + " "); } /** * @brief Recursively prints the rule tree * * @param tree Rules organized into a tree structure */ static void printTree(const std::map>>& tree) { std::cout << "." << std::endl; std::vector>> roots; for (const auto& it : tree) { if (!it.second.first) { roots.push_back(it.second); } } for (const auto& root : roots) { auto children = root.second; for (const auto& child : children) { if (root == roots.back() && child == children.back()) { std::cout << "└── "; printNode(tree, tree.at(child), " "); } else { std::cout << "├── "; printNode(tree, tree.at(child), "│ "); } } } } /** * @brief Prints list of devices in a tree format * * Complexity O(n*log(n)), where n = rules.size * * @param rules Device rules to print */ static void treeFormat(const std::vector& rules) { /* * key: hash * value: (rule, children_hashes) */ std::map>> tree; for (const auto& rule : rules) { auto hash = rule.getHash(); auto p_hash = rule.getParentHash(); auto hash_it = tree.find(hash); auto p_hash_it = tree.find(p_hash); if (p_hash_it == tree.end()) { tree.insert({p_hash, {{}, {hash}}}); } else { p_hash_it->second.second.push_back(hash); } if (hash_it == tree.end()) { tree.insert({hash, {rule, {}}}); } else { hash_it->second.first = rule; } } printTree(tree); } int usbguard_list_devices(int argc, char* argv[]) { bool list_blocked = false; bool list_allowed = false; bool tree_format = false; int opt = 0; while ((opt = getopt_long(argc, argv, options_short, options_long, nullptr)) != -1) { switch (opt) { case 'h': showHelp(std::cout); return EXIT_SUCCESS; case 'a': list_allowed = true; break; case 'b': list_blocked = true; break; case 't': tree_format = true; break; case '?': showHelp(std::cerr); default: return EXIT_FAILURE; } } std::string query = "match"; if (list_blocked != list_allowed) { query = list_allowed ? "allow" : "block"; } usbguard::IPCClient ipc(/*connected=*/true); auto device_rules = ipc.listDevices(query); if (tree_format) { treeFormat(device_rules); } else { classicFormat(device_rules); } return EXIT_SUCCESS; } } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-list-devices.hpp ================================================ // // 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 #ifdef HAVE_BUILD_CONFIG_H #include #endif namespace usbguard { int usbguard_list_devices(int argc, char** argv); } /* namespace usbguard */ /* vim: set ts=2 sw=2 et */ ================================================ FILE: src/CLI/usbguard-list-rules.cpp ================================================ // // 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 "usbguard.hpp" #include "usbguard-list-rules.hpp" #include "usbguard/IPCClient.hpp" #include namespace usbguard { static const char* options_short = "hdl:"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "show-devices", no_argument, nullptr, 'd'}, { "label", required_argument, nullptr, 'l' }, { nullptr, 0, nullptr, 0 } }; static void showHelp(std::ostream& stream) { stream << " Usage: " << usbguard_arg0 << " list-rules [OPTIONS]" << std::endl; stream << std::endl; stream << " Options:" << std::endl; stream << " -d, --show-devices Show all devices which are affected by the specific rule." << std::endl; stream << " -h, --help Show this help." << std::endl; stream << " -l, --label