summaryrefslogtreecommitdiffstats
path: root/modules-available/usblockoff
diff options
context:
space:
mode:
authorroot2017-11-05 06:08:37 +0100
committerroot2017-11-05 06:08:37 +0100
commit56adda043ed5f4e04c12aec2d6ebbca2372332b8 (patch)
tree0c584a7264d8435d8c2ceac4d14679fd886627e9 /modules-available/usblockoff
parent[syslog] Tweak machineuuid index in installer (diff)
downloadslx-admin-56adda043ed5f4e04c12aec2d6ebbca2372332b8.tar.gz
slx-admin-56adda043ed5f4e04c12aec2d6ebbca2372332b8.tar.xz
slx-admin-56adda043ed5f4e04c12aec2d6ebbca2372332b8.zip
Initial commit
Diffstat (limited to 'modules-available/usblockoff')
-rw-r--r--modules-available/usblockoff/api.inc.php59
-rw-r--r--modules-available/usblockoff/config.json4
-rw-r--r--modules-available/usblockoff/inc/default-configs/rules.conf0
-rw-r--r--modules-available/usblockoff/inc/default-configs/usbguard-daemon.conf160
-rw-r--r--modules-available/usblockoff/install.inc.php31
-rw-r--r--modules-available/usblockoff/lang/de/module.json4
-rw-r--r--modules-available/usblockoff/lang/de/rule.json19
-rw-r--r--modules-available/usblockoff/lang/de/template-tags.json14
-rw-r--r--modules-available/usblockoff/lang/en/module.json4
-rw-r--r--modules-available/usblockoff/lang/en/rule.json19
-rw-r--r--modules-available/usblockoff/lang/en/template-tags.json14
-rw-r--r--modules-available/usblockoff/page.inc.php234
-rw-r--r--modules-available/usblockoff/templates/server-prop-bool.html16
-rw-r--r--modules-available/usblockoff/templates/server-prop-dropdown.html19
-rw-r--r--modules-available/usblockoff/templates/server-prop-generic.html16
-rw-r--r--modules-available/usblockoff/templates/usb-choose-config.html118
-rw-r--r--modules-available/usblockoff/templates/usb-configuration.html91
-rw-r--r--modules-available/usblockoff/templates/usb-device-list.html170
18 files changed, 992 insertions, 0 deletions
diff --git a/modules-available/usblockoff/api.inc.php b/modules-available/usblockoff/api.inc.php
new file mode 100644
index 00000000..9029819d
--- /dev/null
+++ b/modules-available/usblockoff/api.inc.php
@@ -0,0 +1,59 @@
+<?php
+
+HandleParameters();
+
+function HandleParameters() {
+ $getAction = Request::get('action', 0, 'string');
+ if ($getAction == "newdevice") {
+ $id = Request::get('id', '', 'string');
+ $serial = Request::get('serial', '', 'sting');
+ $name = Request::get('name', '', 'string');
+ $ip = Request::get('ip', 0, 'string');
+ $ruleInformation['hash'] = Request::get('hash', '', 'string');
+ $ruleInformation['parent-hash'] = Request::get('parent-hash', '', 'string');
+ $ruleInformation['via-port'] = Request::get('via-port', '', 'string');
+ $ruleInformation['with-interface'] = Request::get('with-interface', '', 'string');
+ $ruleInformation['interface-policy'] = Request::get('interface-policy', '', 'string');
+ newDevice($id, $serial, $name, $ip, $ruleInformation);
+ } elseif ($getAction == "deletedevice") {
+ $serial = Request::get('serial', '', 'string');
+ deleteDevice($serial);
+ }
+}
+
+/**
+ * Adds a new USB-Device to the db.
+ *
+ * @param string $id USB-Device id.
+ * @param string $serial USB-Device serial number.
+ * @param string $name USB-Device name.
+ */
+function newDevice($id, $serial, $name, $ip, $ruleInformation) {
+ $NOW = time();
+ //$machineuuid = Database::queryFirst("SELECT machineuuid, currentuser FROM machine AS m WHERE m.clientip = :ip", array('ip' => $ip));
+ $client = Database::queryFirst("SELECT m.machineuuid AS 'muid', m.currentuser AS 'user' FROM machine AS m WHERE m.clientip=:ip", array('ip' => $ip));
+
+ // TODO: Same device when ID/Serial/Name are the same? Maybe hash value but the hash value can be different on multiple unix.
+ $dbresult = Database::queryFirst("SELECT uid FROM `usb_devices` WHERE id=:id AND serial=:serialnr AND name=:name", array(
+ 'id' => $id, 'serialnr' => $serial, 'name' => $name));
+ if (empty($dbresult)) {
+ $dbquery = Database::exec("INSERT INTO `usb_devices` (id, serial, name, machineuuid, time, user, ruleInformation) VALUES (:id, :serialnr,
+ :name, :machineuuid, :now, :user, :ruleInformation)", array('id' => $id, 'serialnr' => $serial, 'name' => $name, 'machineuuid' => $client['muid'], 'now' => $NOW,
+ 'user' => $client['user'], 'ruleInformation' => json_encode($ruleInformation)));
+ echo "Successfully added";
+ } else {
+ $dbquery = Database::exec("UPDATE `usb_devices` SET machineuuid=:machineuuid, time=:now, user=:user, ruleInformation=:ruleInformation WHERE id=:id AND serial=:serialnr AND name=:name",
+ array('id' => $id, 'serialnr' => $serial, 'name' => $name, 'machineuuid' => $client['muid'], 'now' => $NOW, 'user' => $client['user'], 'ruleInformation' => json_encode($ruleInformation)));
+ echo "Successfully updated";
+ }
+
+}
+
+/**
+ * Deletes a device from the db given a serial number.
+ *
+ * @param string $serial USB-Device serial number.
+ */
+function deleteDevice($serial) {
+ $dbquery = Database::exec("DELETE FROM `usb_devices` WHERE serial=:serial", array('serial' => $serial));
+}
diff --git a/modules-available/usblockoff/config.json b/modules-available/usblockoff/config.json
new file mode 100644
index 00000000..59b54a80
--- /dev/null
+++ b/modules-available/usblockoff/config.json
@@ -0,0 +1,4 @@
+{
+ "category":"main.beta",
+ "dependencies": ["bootstrap_switch", "bootstrap_dialog"]
+}
diff --git a/modules-available/usblockoff/inc/default-configs/rules.conf b/modules-available/usblockoff/inc/default-configs/rules.conf
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/modules-available/usblockoff/inc/default-configs/rules.conf
diff --git a/modules-available/usblockoff/inc/default-configs/usbguard-daemon.conf b/modules-available/usblockoff/inc/default-configs/usbguard-daemon.conf
new file mode 100644
index 00000000..44f2d66c
--- /dev/null
+++ b/modules-available/usblockoff/inc/default-configs/usbguard-daemon.conf
@@ -0,0 +1,160 @@
+#
+# Rule set file path.
+#
+# The USBGuard daemon will use this file to load the policy
+# rule set from it and to write new rules received via the
+# IPC interface.
+#
+# RuleFile=/path/to/rules.conf
+#
+RuleFile=/usr/local/etc/usbguard/rules.conf
+
+#
+# Implicit policy target.
+#
+# How to treat devices that don't match any rule in the
+# policy. One of:
+#
+# * allow - authorize the device
+# * block - block the device
+# * reject - remove the device
+#
+ImplicitPolicyTarget=allow
+
+#
+# Present device policy.
+#
+# How to treat devices that are already connected when the
+# daemon starts. One of:
+#
+# * allow - authorize every present device
+# * block - deauthorize every present device
+# * reject - remove every present device
+# * keep - just sync the internal state and leave it
+# * apply-policy - evaluate the ruleset for every present
+# device
+#
+PresentDevicePolicy=apply-policy
+
+#
+# Present controller policy.
+#
+# How to treat USB controllers that are already connected
+# when the daemon starts. One of:
+#
+# * allow - authorize every present device
+# * block - deauthorize every present device
+# * reject - remove every present device
+# * keep - just sync the internal state and leave it
+# * apply-policy - evaluate the ruleset for every present
+# device
+#
+PresentControllerPolicy=keep
+
+#
+# Inserted device policy.
+#
+# How to treat USB devices that are already connected
+# *after* the daemon starts. One of:
+#
+# * block - deauthorize every present device
+# * reject - remove every present device
+# * apply-policy - evaluate the ruleset for every present
+# device
+#
+InsertedDevicePolicy=apply-policy
+
+#
+# Restore controller device state.
+#
+# The USBGuard daemon modifies some attributes of controller
+# devices like the default authorization state of new child device
+# instances. Using this setting, you can controll whether the
+# daemon will try to restore the attribute values to the state
+# before modificaton on shutdown.
+#
+# SECURITY CONSIDERATIONS: If set to true, the USB authorization
+# policy could be bypassed by performing some sort of attack on the
+# daemon (via a local exploit or via a USB device) to make it shutdown
+# and restore to the operating-system default state (known to be permissive).
+#
+RestoreControllerDeviceState=false
+
+#
+# Device manager backend
+#
+# Which device manager backend implementation to use. One of:
+#
+# * uevent - Netlink based implementation which uses sysfs to scan for present
+# devices and an uevent netlink socket for receiving USB device
+# related events.
+# * dummy - A dummy device manager which simulates several devices and device
+# events. Useful for testing.
+#
+DeviceManagerBackend=uevent
+
+#!!! WARNING: It's good practice to set at least one of the !!!
+#!!! two options bellow. If none of them are set, !!!
+#!!! the daemon will accept IPC connections from !!!
+#!!! anyone, thus allowing anyone to modify the !!!
+#!!! rule set and (de)authorize USB devices. !!!
+
+#
+# Users allowed to use the IPC interface.
+#
+# A space delimited list of usernames that the daemon will
+# accept IPC connections from.
+#
+# IPCAllowedUsers=username1 username2 ...
+#
+IPCAllowedUsers=root
+
+#
+# Groups allowed to use the IPC interface.
+#
+# A space delimited list of groupnames that the daemon will
+# accept IPC connections from.
+#
+# IPCAllowedGroups=groupname1 groupname2 ...
+#
+IPCAllowedGroups=
+
+#
+# IPC access control definition files path.
+#
+# The files at this location will be interpreted by the daemon
+# as access control definition files. The (base)name of a file
+# should be in the form:
+#
+# [user][:<group>]
+#
+# and should contain lines in the form:
+#
+# <section>=[privilege] ...
+#
+# This way each file defines who is able to connect to the IPC
+# bus and what privileges he has.
+#
+IPCAccessControlFiles=/usr/local/etc/usbguard/IPCAccessControl.d/
+
+#
+# Generate device specific rules including the "via-port"
+# attribute.
+#
+# This option modifies the behavior of the allowDevice
+# action. When instructed to generate a permanent rule,
+# the action can generate a port specific rule. Because
+# some systems have unstable port numbering, the generated
+# rule might not match the device after rebooting the system.
+#
+# If set to false, the generated rule will still contain
+# the "parent-hash" attribute which also defines an association
+# to the parent device. See usbguard-rules.conf(5) for more
+# details.
+#
+DeviceRulesWithPort=false
+
+#
+# USBGuard audit events log file path.
+#
+AuditFilePath=/usr/local/var/log/usbguard/usbguard-audit.log
diff --git a/modules-available/usblockoff/install.inc.php b/modules-available/usblockoff/install.inc.php
new file mode 100644
index 00000000..690f45d4
--- /dev/null
+++ b/modules-available/usblockoff/install.inc.php
@@ -0,0 +1,31 @@
+<?php
+
+$res = array();
+
+$t1 = $res[] = tableCreate('usb_devices', '
+ `uid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `id` varchar(50),
+ `serial` varchar(512) NOT NULL DEFAULT 0,
+ `name` varchar(1024) CHARACTER SET ascii DEFAULT NULL,
+ `machineuuid` char(36) CHARACTER SET ascii DEFAULT NULL,
+ `time` INT(11) NOT NULL DEFAULT 0,
+ `user` varchar(8),
+ `ruleInformation` varchar(1024),
+ PRIMARY KEY (`uid`)
+');
+
+$t2 = $res[] = tableCreate('usb_configs', '
+ `configid` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `configname` VARCHAR(200) NOT NULL,
+ `rulesconfig` BLOB,
+ `daemonconfig` BLOB,
+ PRIMARY KEY (`configid`)
+');
+
+//$ret = Database::exec("DROP TABLE `usb_devices`");
+
+if (in_array(UPDATE_DONE, $res)) {
+ finalResponse(UPDATE_DONE, 'Table created successfully');
+}
+
+finalResponse(UPDATE_NOOP, 'Everything already up to date');
diff --git a/modules-available/usblockoff/lang/de/module.json b/modules-available/usblockoff/lang/de/module.json
new file mode 100644
index 00000000..bfde75fe
--- /dev/null
+++ b/modules-available/usblockoff/lang/de/module.json
@@ -0,0 +1,4 @@
+{
+ "module_name": "USB Lock-Off",
+ "page_title": "USB Lock-Off"
+}
diff --git a/modules-available/usblockoff/lang/de/rule.json b/modules-available/usblockoff/lang/de/rule.json
new file mode 100644
index 00000000..0af86c37
--- /dev/null
+++ b/modules-available/usblockoff/lang/de/rule.json
@@ -0,0 +1,19 @@
+{
+ "abr_helptext": "allow: Autorisiert das Gerät.\u000Dblock: Blockiert das Gerät.\u000Dreject: Entfernt das Gerät aus dem System.",
+ "id": "ID",
+ "id_helptext": "ID des USB-Geräts.",
+ "serial": "Seriennummer",
+ "serial_helptext": "Seriennummer des USB-Geräts.",
+ "name": "Name",
+ "name_helptext": "Name des USB-Geräts.",
+ "hash": "Hashwert",
+ "hash_helptext": "Hashwert des USB-Geräts. Von USBGuard mittels sodium oder gcrypt berechnet.",
+ "parent-hash": "Parent-Hashwert",
+ "parent-hash_helptext": "Hashwert des Client an dem das USB-Gerät angeschlossen wurde.",
+ "via-port": "Erlaubte Ports",
+ "via-port_helptext": "USB-Port(s), an welche das USB-Gerät angeschlossen werden kann.",
+ "with-interface": "Interfaces",
+ "with-interface_helptext": "Die Interfaces, welches das USB-Gerät besitzt.",
+ "interface-policy": "Interface Police",
+ "interface-policy_helptext": "Per-Interface Authorisierung."
+}
diff --git a/modules-available/usblockoff/lang/de/template-tags.json b/modules-available/usblockoff/lang/de/template-tags.json
new file mode 100644
index 00000000..b17eb1fb
--- /dev/null
+++ b/modules-available/usblockoff/lang/de/template-tags.json
@@ -0,0 +1,14 @@
+{
+ "lang_howToRuleLang": "Verwendung der Regel Sprache.",
+ "lang_device": "USB Gerät",
+ "lang_devices": "USB Geräte",
+ "lang_general": "Allgemein",
+ "lang_config": "Konfiguration",
+ "lang_config_helptext": "Erstelle eine neue Konfiguration oder wähle eine aus, um sie zu Laden und Bearbeiten zu können",
+ "lang_configName": "Konfigurationsname",
+ "lang_configName_helptext": "Name der Konfiguration",
+ "lang_deleteConfig": "Konfiguration Löschen",
+ "lang_deleteConfig_helptext": "Löscht die Konfiguration aus der Datenbank",
+ "lang_createNewConfig": "<Neue Konfiguration erstellen>",
+ "lang_deleteConfigMessage": "Sind sie sicher, dass sie die Konfiguration Löschen wollen?"
+}
diff --git a/modules-available/usblockoff/lang/en/module.json b/modules-available/usblockoff/lang/en/module.json
new file mode 100644
index 00000000..bfde75fe
--- /dev/null
+++ b/modules-available/usblockoff/lang/en/module.json
@@ -0,0 +1,4 @@
+{
+ "module_name": "USB Lock-Off",
+ "page_title": "USB Lock-Off"
+}
diff --git a/modules-available/usblockoff/lang/en/rule.json b/modules-available/usblockoff/lang/en/rule.json
new file mode 100644
index 00000000..d2e7b8ca
--- /dev/null
+++ b/modules-available/usblockoff/lang/en/rule.json
@@ -0,0 +1,19 @@
+{
+ "abr_helptext": "allow: authorize the device.\u000Dblock: block the device.\u000DReject: remove the device from the system.",
+ "id": "ID",
+ "id_helptext": "ID of the USB-device.",
+ "serial": "Serialnumber",
+ "serial_helptext": "Serialnumber of the USB-device.",
+ "name": "Name",
+ "name_helptext": "Name of the USB-device.",
+ "hash": "Hash value",
+ "hash_helptext": "Hash value of the USB-device. Calculated via USBGuard through sodium or gcrypt.",
+ "parent-hash": "Parent-hash value",
+ "parent-hash_helptext": "Hash value of the Client the USB-device was connected.",
+ "via-port": "Via port",
+ "via-port_helptext": "Accepted USB-port(s) for the USB-device.",
+ "with-interface": "Interfaces",
+ "with-interface_helptext": "Interfaces of the USB-device.",
+ "interface-policy": "interface-policy",
+ "interface-policy_helptext": "Per-interface authorisation."
+}
diff --git a/modules-available/usblockoff/lang/en/template-tags.json b/modules-available/usblockoff/lang/en/template-tags.json
new file mode 100644
index 00000000..20529d4a
--- /dev/null
+++ b/modules-available/usblockoff/lang/en/template-tags.json
@@ -0,0 +1,14 @@
+{
+ "lang_howToRuleLang": "Usage of the Rule Language.",
+ "lang_device": "usb device",
+ "lang_devices": "usb devices",
+ "lang_general": "General",
+ "lang_config": "Configuration",
+ "lang_config_helptext": "Create a new configuration or choose one to load and edit it",
+ "lang_configName": "Configuration name",
+ "lang_configName_helptext": "The name of the configuration",
+ "lang_deleteConfig": "Delete configuration",
+ "lang_deleteConfig_helptext": "Delets the configuration",
+ "lang_createNewConfig": "<create new configuration>",
+ "lang_deleteConfigMessage": "Are you sure you want to delete the configuration?"
+}
diff --git a/modules-available/usblockoff/page.inc.php b/modules-available/usblockoff/page.inc.php
new file mode 100644
index 00000000..e2effad4
--- /dev/null
+++ b/modules-available/usblockoff/page.inc.php
@@ -0,0 +1,234 @@
+<?php
+$glob3 = 'globale Variable 3';
+$name = 'testname';
+$logedIn = true;
+class Page_usblockoff extends Page {
+
+ /**
+ * Called before any page rendering happens - early hook to check parameters etc.
+ */
+ protected function doPreprocess() {
+ User::load();
+
+ if (!User::isLoggedIn()) {
+ Message::addError('main.no-permission');
+ Util::redirect('?do=Main'); // does not return
+ }
+
+ $this->action = Request::post('action');
+ error_log($this->action);
+
+ if ($this->action === 'updateConfig') {
+ $this->updateConfig();
+ } elseif ($this->action === 'deleteConfig') {
+ $this->deleteConfig();
+ }
+ // elseif ($this->action === 'addDevices') {
+ // $this->addDevices();
+ //}
+ }
+
+ /**
+ * Menu etc. has already been generated, now it's time to generate page content.
+ */
+ protected function doRender() {
+ $this->loadConfigChooser();
+ }
+
+
+ protected function loadConfigChooser() {
+ $dbquery = Database::simpleQuery("SELECT configid, configname FROM `usb_configs`");
+ $configs = array();
+ while ($dbentry = $dbquery->fetch(PDO::FETCH_ASSOC)) {
+ $config['config_id'] = $dbentry['configid'];
+ $config['config_name'] = $dbentry['configname'];
+ $configs[] = $config;
+ }
+
+ Render::addTemplate('usb-choose-config', array( 'config_list' => array_values($configs)));
+ }
+
+ protected function deleteConfig() {
+ $configID = Request::post('id', 0, 'int');
+
+ if ($configID != 0) {
+ Database::exec("DELETE FROM `usb_configs` WHERE configid=:configid", array('configid' => $configID));
+ }
+
+ Util::redirect('?do=usblockoff');
+ }
+
+ protected function updateConfig() {
+ // Add new settings in usbguard-daemon.conf here:
+ $result['RuleFile'] = Request::post('RuleFile', '', 'string');
+ $result['ImplicitPolicyTarget'] = Request::post('ImplicitPolicyTarget', '', 'string');
+ $result['PresentDevicePolicy'] = Request::post('PresentDevicePolicy', '', 'string');
+ $result['PresentControllerPolicy'] = Request::post('PresentControllerPolicy', '', 'string');
+ $result['InsertedDevicePolicy'] = Request::post('InsertedDevicePolicy', '', 'string');
+ $result['RestoreControllerDeviceState'] = Request::post('RestoreControllerDeviceState', '', 'string');
+ $result['DeviceManagerBackend'] = Request::post('DeviceManagerBackend', '', 'string');
+ $result['IPCAllowedUsers'] = Request::post('IPCAllowedUsers', '', 'string');
+ $result['IPCAllowedGroups'] = Request::post('IPCAllowedGroups', '', 'string');
+ $result['IPCAccessControlFiles'] = Request::post('IPCAccessControlFiles', '', 'string');
+ $result['DeviceRulesWithPort'] = Request::post('DeviceRulesWithPort', '', 'string');
+ $result['AuditFilePath'] = Request::post('AuditFilePath', '', 'string');
+ $result['rules'] = Request::post('rules', '', 'string');
+
+ $id = Request::post('id', 0, 'int');
+ $configname = Request::post('configName', '', 'string');
+ $dbquery = Database::queryFirst("SELECT * FROM `usb_configs` WHERE configid=:id", array('id' => $id));
+
+ // Load daemon.conf from db else load default
+ if ($dbquery !== false) {
+ $daemonConf = explode("\r\n", $dbquery['daemonconfig']);
+ } else {
+ $currentdir = getcwd();
+ $file = $currentdir . '/modules/usblockoff/inc/default-configs/usbguard-daemon.conf';
+ $daemonConf = file($file);
+ }
+ $newDaemonConf = array();
+
+ foreach ($daemonConf as $line) {
+ $t_line = trim($line, "\r\n");
+ if ($t_line == '' || $t_line[0] == '#') {
+ $newDaemonConf[] = $line . "\r\n";
+ continue;
+ } else {
+ $splitstr = explode('=', $line);
+
+ $splitstr[1] = $result[$splitstr[0]];
+ $newDaemonConf[] = implode('=', $splitstr)."\r\n";
+ }
+ }
+
+ // INSERT IN DB
+ if ($id == '0') {
+ $dbquery = Database::exec("INSERT INTO `usb_configs` (configname, rulesconfig, daemonconfig) VALUES (:configname, :rulesconfig, :daemonconfig)",
+ array('configname' => $configname, 'rulesconfig' => $result['rules'], 'daemonconfig' => implode($newDaemonConf)));
+ } else {
+ $dbquery = Database::exec("UPDATE `usb_configs` SET configname=:configname, rulesconfig=:rulesconfig, daemonconfig=:daemonconfig WHERE configid=:configid",
+ array('configid' => $id,'configname' => $configname, 'rulesconfig' => $result['rules'], 'daemonconfig' => implode($newDaemonConf)));
+ }
+ }
+
+ /**
+ * AJAX
+ */
+ protected function doAjax()
+ {
+ User::load();
+ if (!User::isLoggedIn()) {
+ die('Unauthorized');
+ }
+ $action = Request::any('action');
+ if ($action === 'deviceList') {
+ $this->ajaxDeviceList();
+ } elseif ($action === 'loadConfig') {
+ $id = Request::any('id', 0, 'int');
+ $this->ajaxConfig($id);
+ }
+ }
+
+ private function ajaxConfig($id) {
+
+ $form = array();
+ $rulesConf;
+
+ if($id == 0) {
+ $currentdir = getcwd();
+
+ $rulesConf = file_get_contents($currentdir . '/modules/usblockoff/inc/default-configs/rules.conf');
+ $daemonConf = file($currentdir . '/modules/usblockoff/inc/default-configs/usbguard-daemon.conf');
+ } else {
+ $dbquery = Database::queryFirst("SELECT * FROM `usb_configs` WHERE configid=:id", array('id' => $id));
+ $daemonConf = explode("\r\n", $dbquery['daemonconfig']);
+ $rulesConf = $dbquery['rulesconfig'];
+ }
+
+ $element = array();
+ $hlptxt = '';
+
+ foreach ($daemonConf as $line) {
+ $t_line = trim($line, "\r\n");
+ if ($t_line == '#' || $t_line == '' || strpos($t_line, '#!!!') !== false) {
+ continue;
+ } elseif ($t_line[0] == '#') {
+ $ttxt = trim($line, "#");
+ $hlptxt .= $ttxt . '<br>';
+ } else {
+ $splitstr = explode('=', $t_line);
+ $element['name'] = $splitstr[0];
+ $element['value'] = $splitstr[1];
+ $element['helptext'] = $hlptxt;
+
+ $form[] = $element;
+ $hlptxt = '';
+ }
+ }
+
+ echo Render::parse('usb-configuration', array(
+ 'list' => array_values($form),
+ 'rules' => $rulesConf,
+ ));
+ }
+
+ private function ajaxDeviceList() {
+
+ $usbdevices = array();
+
+ $dbquery = Database::simpleQuery("SELECT * FROM `usb_devices`");
+ while ($entry = $dbquery->fetch(PDO::FETCH_ASSOC)) {
+ $locationquery = Database::queryFirst("SELECT l.locationname AS 'name', m.clientip AS 'ip' FROM machine AS m JOIN location AS l ON l.locationid=m.locationid
+ WHERE m.machineuuid=:machineuuid", array( 'machineuuid' => $entry['machineuuid']));
+
+ $device['uid'] = $entry['uid'];
+ $device['id'] = $entry['id'];
+ $device['name'] = $entry['name'];
+ $device['serial'] = $entry['serial'];
+ $device['machineuuid'] = $entry['machineuuid'];
+ $device['user'] = $entry['user'];
+ $device['clientip'] = $locationquery['ip'];
+ $device['date'] = date('d.m.Y', $entry['time']);
+ $device['time'] = date('G:i', $entry['time']);
+ $device['location'] = $locationquery['name'];
+ $ruleInformation = json_decode($entry['ruleInformation'], true);
+ $device['hash'] = $ruleInformation['hash'];
+ $device['parent-hash'] = $ruleInformation['parent-hash'];
+ $device['via-port'] = $ruleInformation['via-port'];
+ $device['with-interface'] = $ruleInformation['with-interface'];
+ $usbdevices[] = $device;
+ }
+
+ $settings = array();
+ $setting = array();
+ $setting['title'] = "Action";
+ $setting['select_list'] = array(array(
+ 'option' => 'allow',
+ 'active' => true,
+ ), array(
+ 'option' => 'block',
+ 'active' => false,
+ ), array(
+ 'option' => 'reject',
+ 'active' => false,
+ ));
+ $setting['helptext'] = array('helptext' => Dictionary::translateFile('rule', 'abr_helptext'));
+ $setting['property'] = 'action';
+ $setting['settingHtml'] = Render::parse('server-prop-dropdown', (array)$setting);
+ $settings[] = $setting;
+
+ $ruleValues = array('id' => true, 'serial' => true, 'name' => true, 'hash' => false, 'parent-hash' => false, 'via-port' => false, 'with-interface' => false, 'interface-policy' => false);
+ foreach ($ruleValues as $key => $value) {
+ $settings[] = array(
+ 'settingHtml' => Render::parse('server-prop-bool', array('title' => Dictionary::translateFile('rule', $key),
+ 'helptext' => array('helptext' => Dictionary::translateFile('rule', $key . "_helptext")),
+ 'property' => $key, 'currentvalue' => $value)),
+ );
+ }
+
+ echo Render::parse('usb-device-list', array(
+ 'list' => array_values($usbdevices),
+ 'settings' => array_values($settings)
+ ));
+ }
+}
diff --git a/modules-available/usblockoff/templates/server-prop-bool.html b/modules-available/usblockoff/templates/server-prop-bool.html
new file mode 100644
index 00000000..f430d02c
--- /dev/null
+++ b/modules-available/usblockoff/templates/server-prop-bool.html
@@ -0,0 +1,16 @@
+<div class="list-group-item">
+ <div class="row">
+ <div class="col-md-3"><label for="prop-{{property}}">{{title}}</label></div>
+ <div class="col-md-7">
+ <input class="settings-bs-switch" id="prop-{{property}}" type="checkbox" name="prop-{{property}}" value="1"
+ {{#currentvalue}}checked{{/currentvalue}}>
+ </div>
+ <div class="col-md-2">
+ {{#helptext}}
+ <a class="btn btn-default" title="{{helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ {{/helptext}}
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/modules-available/usblockoff/templates/server-prop-dropdown.html b/modules-available/usblockoff/templates/server-prop-dropdown.html
new file mode 100644
index 00000000..80667766
--- /dev/null
+++ b/modules-available/usblockoff/templates/server-prop-dropdown.html
@@ -0,0 +1,19 @@
+<div class="list-group-item">
+ <div class="row">
+ <div class="col-md-3"><label for="prop-{{property}}">{{title}}</label></div>
+ <div class="col-md-7">
+ <select class="form-control" id="prop-{{property}}" name="prop-{{property}}">
+ {{#select_list}}
+ <option {{#active}}selected{{/active}}>{{option}}</option>
+ {{/select_list}}
+ </select>
+ </div>
+ <div class="col-md-2">
+ {{#helptext}}
+ <a class="btn btn-default" title="{{helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ {{/helptext}}
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/modules-available/usblockoff/templates/server-prop-generic.html b/modules-available/usblockoff/templates/server-prop-generic.html
new file mode 100644
index 00000000..9e94c23d
--- /dev/null
+++ b/modules-available/usblockoff/templates/server-prop-generic.html
@@ -0,0 +1,16 @@
+<div class="list-group-item">
+ <div class="row">
+ <div class="col-md-3"><label for="prop-{{property}}">{{title}}</label></div>
+ <div class="col-md-7">
+ <input class="form-control" id="prop-{{property}}" type="{{inputtype}}" name="prop-{{property}}"
+ value="{{currentvalue}}">
+ </div>
+ <div class="col-md-2">
+ {{#helptext}}
+ <a class="btn btn-default" title="{{helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ {{/helptext}}
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/modules-available/usblockoff/templates/usb-choose-config.html b/modules-available/usblockoff/templates/usb-choose-config.html
new file mode 100644
index 00000000..d446e4cf
--- /dev/null
+++ b/modules-available/usblockoff/templates/usb-choose-config.html
@@ -0,0 +1,118 @@
+<form method="post" action="?do=usblockoff" id="configForm">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" id="formAction" value="updateConfig">
+ <input type="hidden" name="id" value="0" id="configID">
+
+ <div class="panel panel-default">
+ <div class="panel-heading">{{lang_general}}</div>
+ <div class="panel-body">
+ <div class="list-group">
+
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-sm-3">
+ <label>{{lang_config}}</label>
+ </div>
+ <div class="col-sm-7">
+ <div class="col-sm-7">
+ <!--<input class="form-control" name="{{name}}" id="{{name}}" value="{{value}}">-->
+ <select class="form-control" id="select_config" name="select_config" onchange="loadConfig(this);">
+ <option value="0">{{lang_createNewConfig}}</option>
+ {{#config_list}}
+ <option value={{config_id}}>{{config_name}}</option>
+ {{/config_list}}
+ </select>
+ </div>
+ </div>
+ <div class="col-sm-2">
+ <a class="btn btn-default" title="{{lang_config_helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-sm-3">
+ <label>{{lang_configName}}</label>
+ </div>
+ <div class="col-sm-7">
+ <div class="col-sm-7">
+ <input required class="form-control" name="configName" id="configName" value="{{configName}}">
+ </div>
+ </div>
+ <div class="col-sm-2">
+ <a class="btn btn-default" title="{{lang_configName_helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-sm-3">
+ <label>{{lang_deleteConfig}}</label>
+ </div>
+ <div class="col-sm-7">
+ <div class="col-sm-7">
+ <!-- <button class="btn btn-danger confirm-delete" type="submit" onclick="deleteConfig();">{{lang_delete}}</button>-->
+ <button class="btn btn-danger" value="" id="deleteConfigButton" title="{{lang_delete}}" onclick="deleteConfig(event);">
+ <span class="glyphicon glyphicon-trash"> {{lang_delete}}</span>
+ </button>
+ </div>
+ </div>
+ <div class="col-sm-2">
+ <a class="btn btn-default" title="{{lang_deleteConfig_helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ <div id="configDIV"></div>
+</form>
+<script type="text/javascript">
+document.addEventListener("DOMContentLoaded", function () {
+ $('#select_config').change();
+});
+
+function loadConfig(selectedOption) {
+ var configID = selectedOption.value;
+ var configName = $('#select_config option:selected').text();
+ $('#configDIV').load("?do=usblockoff&action=loadConfig&id=" + configID);
+ $('#configID').val(configID);
+ if (configID == 0) {
+ $('#configName').val('');
+ } else {
+ $('#configName').val(configName);
+ }
+}
+
+function deleteConfig(event) {
+ event.preventDefault();
+
+ BootstrapDialog.confirm({
+ title: '{{lang_delete}}',
+ message: '{{lang_deleteConfigMessage}}',
+ type: BootstrapDialog.TYPE_DANGER, // <-- Default value is BootstrapDialog.TYPE_PRIMARY
+ closable: false, // <-- Default value is false
+ draggable: false, // <-- Default value is false
+ btnCancelLabel: '{{lang_cancel}}', // <-- Default value is 'Cancel',
+ btnOKLabel: '{{lang_delete}}', // <-- Default value is 'OK',
+ btnOKClass: 'btn-danger', // <-- If you didn't specify it, dialog type will be used,
+ callback: function(result) {
+ if (result) {
+ var configID = $('#select_config option:selected').val();
+ $('#configID').val(configID);
+ $('#formAction').val('deleteConfig');
+ $('#configForm').submit();
+ }
+ }
+ });
+}
+</script>
diff --git a/modules-available/usblockoff/templates/usb-configuration.html b/modules-available/usblockoff/templates/usb-configuration.html
new file mode 100644
index 00000000..939dffcd
--- /dev/null
+++ b/modules-available/usblockoff/templates/usb-configuration.html
@@ -0,0 +1,91 @@
+<div class="panel panel-default">
+ <div class="panel-heading">usbugard-daemon.conf</div>
+ <div class="panel-body">
+ <div class="list-group">
+
+ {{#list}}
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-sm-3">
+ <label>{{name}}</label>
+ </div>
+ <div class="col-sm-7">
+ <div class="col-sm-7">
+ <input class="form-control" name="{{name}}" id="{{name}}" value="{{value}}">
+ </div>
+ </div>
+ <div class="col-sm-2">
+ <a class="btn btn-default" title="{{helptext}}">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ </div>
+ </div>
+ </div>
+ {{/list}}
+
+ </div>
+ </div>
+</div>
+
+<div class="panel panel-default">
+ <div class="panel-heading">rules.conf</div>
+ <div class="panel-body">
+ <div class="list-group">
+
+ <div class="form-group">
+ <textarea class="form-control" rows="10" name="rules" id="rules">{{rules}}</textarea>
+ </div>
+
+ <div>
+ <a class="btn btn-success" onclick="loadAddDeviceModal();">
+ <span style="margin-right: 5px;" class="glyphicon glyphicon-plus"></span>
+ <span>{{lang_devices}}</span>
+ </a>
+ <a class="btn btn-default" title="{{lang_howToRuleLang}}" href="https://dkopecek.github.io/usbguard/documentation/rule-language.html"
+ style="float: right;" target="_blank">
+ <span class="glyphicon glyphicon-question-sign"></span>
+ </a>
+ </div>
+
+ </div>
+ </div>
+</div>
+
+<div>
+ <button type="submit" id="configFormButton" class="btn btn-primary">{{lang_save}}</button>
+ <!-- TODO: Reset Button should't call loadConfig instead do not reset the select input... but how? -->
+ <button class="btn btn-default" type="reset" onclick="loadConfig($('#select_config'));">{{lang_reset}}</button>
+</div>
+
+
+<div class="modal fade" id="myModal" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header" id="myModalHeader"></div>
+ <div class="modal-body" id="myModalBody" ></div>
+ <div class="modal-footer">
+ <button id="myModalAddButton" class="btn btn-success" type="button" onclick="addDevices();">
+ <span style="margin-right: 5px;" class="glyphicon glyphicon-plus"></span>
+ <span id="myModalAddButtonText"></span>
+ </button>
+ <a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script type="text/javascript">
+ $('a.btn[title]').tooltip({placement: "left", html: true});
+ //var configID = $('#select_config option:selected').val();
+ //$('#deleteConfigButton').val(configID);
+
+ function loadAddDeviceModal() {
+ // TODO Change text of the MODAL!!
+ $('#myModalHeader').text("Device list").css("font-weight", "Bold");
+ $('#myModalAddButton').attr("form", "addDevicesForm");
+ $('#myModal .modal-dialog').css('width', '60%');
+ $('#myModal .modal-dialog').css('min-width', '60%');
+ $('#myModal').modal('show');
+ $('#myModalBody').load("?do=usblockoff&action=deviceList");
+ }
+</script>
diff --git a/modules-available/usblockoff/templates/usb-device-list.html b/modules-available/usblockoff/templates/usb-device-list.html
new file mode 100644
index 00000000..a7ecf989
--- /dev/null
+++ b/modules-available/usblockoff/templates/usb-device-list.html
@@ -0,0 +1,170 @@
+<div>
+<form method="post" action="?do=usblockoff" id="addDevicesForm">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="addDevices">
+
+ <div class="input-group" id="search">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span>
+ <input type="text" id="myInput" class="form-control" onkeyup="search()" placeholder="Search for .." style="font-size: 16px;"/>
+ <span class="input-group-addon" style="width:0px; padding-left:0px; padding-right:0px; border:none;"></span>
+ <select class="form-control" id="searchFor" style="font-size: 16px;" onchange="search()">
+ <option value="0" select>Name</option>
+ <option value="1">Date / Time</option>
+ <option value="2">User Information</option>
+ <option value="3">USB Information</option>
+ <option value="4">Rules Information</option>
+ </select>
+ </div>
+
+ <div style="max-height: 800px; overflow-x: auto;">
+ <table class="table table-hover" id="myTable">
+ <thead>
+ <tr>
+ <th width="1" style="text-align: center;">Name</th>
+ <th width="1" style="text-align: center;">Time</th>
+ <th width="1">User Info</th>
+ <th width="1">USB Info</th>
+ <th width="1">Rule Info</th>
+ </tr>
+ </thead>
+ {{#list}}
+ <input type="hidden" id="{{uid}}-prop-name" value="{{name}}">
+ <input type="hidden" id="{{uid}}-prop-id" value="{{id}}">
+ <input type="hidden" id="{{uid}}-prop-serial" value="{{serial}}">
+ <input type="hidden" id="{{uid}}-prop-via-port" value="{{via-port}}">
+ <input type="hidden" id="{{uid}}-prop-hash" value="{{hash}}">
+ <input type="hidden" id="{{uid}}-prop-parent-hash" value="{{parent-hash}}">
+ <input type="hidden" id="{{uid}}-prop-with-interface" value="{{with-interface}}">
+
+ <tbody onclick="clickRow(this, {{uid}});" id="{{uid}}">
+ <tr>
+ <td nowrap align="center" style="vertical-align: middle;"><label>{{name}}</label></td>
+ <td nowrap align="center" style="vertical-align: middle;">{{time}}<br>{{date}}</td>
+ <td nowrap><font size="0">User: {{user}}<br>Location: {{location}}<br>Client: {{clientip}}</font></td>
+ <td nowrap><font size="0">id: {{id}}<br>Serial: {{serial}}<br>via-port: {{via-port}}</font></td>
+ <td nowrap><font size="0">hash: {{hash}}<br>parent-hash: {{parent-hash}}<br>with-interface: {{with-interface}}</font></td>
+ </tr>
+ </tbody>
+ {{/list}}
+ </table>
+ </div>
+
+ <div class="panel panel-default">
+ <div class="panel-heading">Rule Options</div>
+ <div class="panel-body">
+ <div class="list-group">
+
+ {{#settings}}
+ {{{settingHtml}}}
+ {{/settings}}
+
+ </div>
+ </div>
+ </div>
+
+</form>
+</div>
+
+<script type="text/javascript">
+ $('a.btn[title]').tooltip();
+ $('.settings-bs-switch').bootstrapSwitch({size: 'small'});
+ countSelected();
+
+ function clickRow(tbody, uid) {
+ $(tbody).toggleClass('selected');
+ countSelected();
+
+ // OLD SEND TO PHP STUFF
+ //if ($(tbody).find('#uid').length == 1) {
+ // $(tbody).find('#uid').remove();
+ //} else {
+ // $(tbody).append('<input type="hidden" name="uids[]" value="' + uid + '" id="uid">');
+ //}
+ }
+
+ function countSelected() {
+ var numSelected = $('.selected').length;
+ if (numSelected == 0) {
+ $('#myModalAddButton').prop('disabled', true);
+ } else {
+ $('#myModalAddButton').prop('disabled', false);
+ }
+ if (numSelected == 1) {
+ $('#myModalAddButtonText').text(' ' + numSelected + ' {{lang_device}}');
+ } else {
+ $('#myModalAddButtonText').text(' ' + numSelected + ' {{lang_devices}}');
+ }
+ }
+
+ function search() {
+ var searchForIndex = $('#searchFor').val();
+ // Declare variables
+ var input, filter, table, tr, td, i;
+ input = document.getElementById("myInput");
+ filter = input.value.toUpperCase();
+ table = document.getElementById("myTable");
+ tr = table.getElementsByTagName("tr");
+
+ // Loop through all table rows, and hide those who don't match the search query
+ for (i = 0; i < tr.length; i++) {
+ td = tr[i].getElementsByTagName("td")[searchForIndex];
+ if (td) {
+ if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
+ tr[i].style.display = "";
+ } else {
+ tr[i].style.display = "none";
+ }
+ }
+ }
+ }
+
+ function addDevices() {
+ $('.selected').each(function() {
+ var rule = $('#prop-action').val();
+ var selected = $(this);
+ $('.settings-bs-switch').each(function() {
+ if($(this).is(":checked")) {
+ var settingname = $(this).attr('name').substring(5);
+ var info = $('#' + $(selected).attr('id') + '-' + $(this).attr('name'));
+
+ if(settingname == 'id' || settingname == 'with-interface') {
+ rule += ' ' + settingname + ' ' + info.val();
+ } else {
+ rule += ' ' + settingname + ' "' + info.val() + '"';
+ }
+ }
+ });
+ if ($('#rules').val() != "") {
+ $('#rules').val($('#rules').val() + "\r\n");
+ }
+ $('#rules').val($('#rules').val() + rule);
+ });
+ $('#myModal').modal('toggle');
+ }
+
+</script>
+
+<style type='text/css'>
+ .selected {
+ background-color: #F5F5F5;
+ }
+ #myTable {
+ border-collapse: collapse; /* Collapse borders */
+ width: 100%; /* Full-width */
+ border: 1px solid #ddd; /* Add a grey border */
+ }
+
+ #myTable th, #myTable td {
+ padding: 12px; /* Add padding */
+ }
+
+ #myTable tr {
+ /* Add a bottom border to all table rows */
+ border-bottom: 1px solid #ddd;
+ }
+
+ #myTable tr.header, #myTable tr:hover {
+ /* Add a grey background color to the table header and on hover */
+ background-color: #f1f1f1;
+ }
+</style>