diff options
Diffstat (limited to 'modules-available')
19 files changed, 1223 insertions, 0 deletions
diff --git a/modules-available/statistics/inc/devicetype.inc.php b/modules-available/statistics/inc/devicetype.inc.php index 41ee237d..571d6d2c 100644 --- a/modules-available/statistics/inc/devicetype.inc.php +++ b/modules-available/statistics/inc/devicetype.inc.php @@ -3,4 +3,5 @@ class DeviceType { const SCREEN = 'SCREEN'; + const USB = 'USB'; } diff --git a/modules-available/usblockoff/api.inc.php b/modules-available/usblockoff/api.inc.php new file mode 100644 index 00000000..318f21a1 --- /dev/null +++ b/modules-available/usblockoff/api.inc.php @@ -0,0 +1,165 @@ +<?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'); + $client = Database::queryFirst("SELECT m.machineuuid AS 'muid', m.currentuser AS 'user' FROM machine AS m WHERE m.clientip=:ip", array('ip' => $ip)); + + // $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); + // TODO: product and vendor id necessary? It's already in the hwname part. + list($vid, $pid) = explode(':', $id); + $hwProps = array( + 'vendorid' => $vid, + 'productid' => $pid, + 'name' => $name + ); + // TODO: WITH INTERFACE in the HW table?! Should be equal for every device but not guaranteed (ODROID). + $deviceProps = array( + 'hash' => Request::get('hash', '', 'string'), + 'parent-hash' => Request::get('parent-hash', '', 'string'), + 'via-port' => Request::get('via-port', '', 'string'), + 'with-interface' => Request::get('with-interface', '', 'string'), + 'interface-policy' => Request::get('interface-policy', '', 'string'), + 'machineuuid' => $client['muid'], + 'user' => $client['user'], + 'lastseen' => time() + ); + newDevice($id, $serial, $hwProps, $deviceProps); + } 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, $hwProps, $deviceProps) +{ + // Add or Update the usb device in the statistic_hw table. + $hwid = (int)Database::insertIgnore('statistic_hw', 'hwid', array( + 'hwtype' => DeviceType::USB, + 'hwname' => $id)); + // TODO: Is it okay to use the id (vendor:product) as hwname to identify a usb device? + + // Add all the global prop values to the statistics_hw_prop table. + // productid, vendorid, name, interfaces + // TODO: + addHwProps('statistic_hw_prop', $hwid, $hwProps); + + // Add the hwid -> serial in the usblockoff_hw table if not already existent. + $dbquery2 = Database::queryFirst("Select * FROM `usblockoff_hw` WHERE hwid=:hwid AND serial=:serial", array( + 'hwid' => $hwid, + 'serial' => $serial)); + + if (empty($dbquery2)) { + Database::exec("INSERT INTO `usblockoff_hw` (hwid, serial) VALUES (:hwid, :serial)", array( + 'hwid' => $hwid, + 'serial' => $serial + )); + } + + // Add all the prop values to the usblockoff_hw_prop table. + // PROP: serial, machineuuid, time, user, ruleInformation, Port, hash, interface-policy + addUSBHwProps('usblockoff_hw_prop', $hwid, $serial, $deviceProps); + + echo "Successfully added"; +} + +function addHwProps($table, $hwid, $propArray) { + foreach ($propArray as $prop => $value) { + if (empty($value)) { + continue; + } + Database::exec("INSERT INTO " . $table . " (hwid, prop, value) VALUES (:hwid, :prop, :value) ON DUPLICATE KEY UPDATE value=:value", array( + 'hwid' => $hwid, + 'prop' => $prop, + 'value' => $value + )); + } +} + +function addUSBHwProps($table, $hwid, $serial, $propArray) { + foreach ($propArray as $prop => $value) { + if (empty($value)) { + continue; + } + Database::exec("INSERT INTO " . $table . " (hwid, serial, prop, value) VALUES (:hwid, :serial, :prop, :value) ON DUPLICATE KEY UPDATE value=:value", array( + 'hwid' => $hwid, + 'serial' => $serial, + 'prop' => $prop, + 'value' => $value + )); + } +} + +/** + * 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. + */ +/* VERSION WITH OLD DB --------------------------------------------------------------------------------------- +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. + */ +// TODO: Edit for the new db struct. +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..f15ba11d --- /dev/null +++ b/modules-available/usblockoff/config.json @@ -0,0 +1,4 @@ +{ + "category":"main.beta", + "dependencies": ["bootstrap_switch", "bootstrap_dialog", "statistics"] +} 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..967771d1 --- /dev/null +++ b/modules-available/usblockoff/install.inc.php @@ -0,0 +1,66 @@ +<?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`) +'); +*/ + +$t1 = $res[] = tableCreate('usblockoff_hw', ' + `hwid` INT(10) UNSIGNED NOT NULL , + `serial` VARCHAR(128), + PRIMARY KEY (`hwid`, `serial`) +'); + +$t2 = $res[] = tableCreate('usblockoff_hw_prop', ' + `hwid` INT(10) UNSIGNED NOT NULL , + `serial` VARCHAR(128), + `prop` CHAR(16), + `value` VARCHAR(500), + PRIMARY KEY (`hwid`, `serial`, `prop`) +'); + +// TODO: ADD CONSTRAINT + +$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`"); +//$ret = Database::exec("DROP TABLE `usblockoff_hw`"); +//$ret = Database::exec("DROP TABLE `usblockoff_hw_prop`"); + +if ($t1 === UPDATE_DONE || $t2 === UPDATE_DONE) { + $ret = Database::exec('ALTER TABLE `usblockoff_hw` + ADD CONSTRAINT `usblockoff_hw_ibfk_1` FOREIGN KEY (`hwid`) REFERENCES `statistic_hw` (`hwid`) ON DELETE CASCADE'); + if ($ret === false) { + finalResponse(UPDATE_FAILED, 'Adding constraints to usblockoff_hw failed: ' . Database::lastError()); + } + + $ret = Database::exec('ALTER TABLE `usblockoff_hw_prop` + ADD CONSTRAINT `usblockoff_hw__prop_ibfk_1` FOREIGN KEY (`hwid`, `serial`) REFERENCES `usblockoff_hw` (`hwid`, `serial`) ON DELETE CASCADE'); + if ($ret === false) { + finalResponse(UPDATE_FAILED, 'Adding constraints to usblockoff_hw_prop failed: ' . Database::lastError()); + } + $res[] = UPDATE_DONE; +} + + +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..fc805fe0 --- /dev/null +++ b/modules-available/usblockoff/page.inc.php @@ -0,0 +1,313 @@ +<?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 = null; + + 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(); + $usbdevices = $this->getUsbDeviceList(); +/* + $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) + )); + } + + private function getUsbDeviceList() { + $usbdevices = array(); + + // TODO: Per USB Device 3 querys are executed.. better build a more complex sql query? + + $dbquery = Database::simpleQuery("SELECT * FROM `usblockoff_hw`"); + while ($entry = $dbquery->fetch(PDO::FETCH_ASSOC)) { + + $device = array(); + + // Get all props from the hw table. + $dbquery2 = Database::simpleQuery("SELECT * FROM `statistic_hw_prop` WHERE hwid=:hwid", array( + 'hwid' => $entry['hwid'] + )); + + while ($prop = $dbquery2->fetch(PDO::FETCH_ASSOC)) { + $device[$prop['prop']] = $prop['value']; + } + + // Get all props from the device table. + $dbquery3 = Database::simpleQuery("SELECT * FROM `usblockoff_hw_prop` WHERE hwid=:hwid AND serial=:serial", array( + 'hwid' => $entry['hwid'], + 'serial' => $entry['serial'] + )); + + while ($prop = $dbquery3->fetch(PDO::FETCH_ASSOC)) { + $device[$prop['prop']] = $prop['value']; + } + if (!empty($device['machineuuid'])) { + $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['clientip'] = $locationquery['ip']; + $device['location'] = $locationquery['name']; + } + + //$device['uid'] = $entry['uid']; + $device['id'] = $device['vendorid'] . ":" . $device['productid']; + //$device['name'] = $entry['name']; + $device['serial'] = $entry['serial']; + //$device['machineuuid'] = $entry['machineuuid']; + //$device['user'] = $entry['user']; + $device['date'] = date('d.m.Y', $device['lastseen']); + $device['time'] = date('G:i', $device['lastseen']); + //$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; + } + + return $usbdevices; + } +} 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..de7c990a --- /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..337c40aa --- /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..3c06585e --- /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..06dcf92f --- /dev/null +++ b/modules-available/usblockoff/templates/usb-choose-config.html @@ -0,0 +1,120 @@ +<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"></span> {{lang_delete}} + </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: '<span class="glyphicon glyphicon-trash"></span> {{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..fdfb0793 --- /dev/null +++ b/modules-available/usblockoff/templates/usb-configuration.html @@ -0,0 +1,96 @@ +<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 class="pull-right"> + <a class="btn btn-default" title="{{lang_howToRuleLang}}" + href="https://usbguard.github.io/documentation/rule-language.html" + style="margin-right: 3px;" target="_blank"> + <span class="glyphicon glyphicon-question-sign"></span> + </a> + <a class="btn btn-success" style="float: right;" onclick="loadAddDeviceModal();"> + <span style="margin-right: 5px;" class="glyphicon glyphicon-plus"></span> + <span>{{lang_devices}}</span> + </a> + </div> + </div> + </div> +</div> + +<div class="pull-right"> + <!-- TODO: Reset Button should't call loadConfig instead do not reset the select input... but how? --> + <button class="btn btn-warning" type="reset" onclick="loadConfig($('#select_config'));"> + <!-- TODO: Add discardChanges to the main-> globalVariables --> + <span class="glyphicon glyphicon-refresh"></span> {{lang_discardChanges}} + </button> + <button type="submit" id="configFormButton" class="btn btn-primary"> + <span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}} + </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"> + <a class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</a> + <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> + </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..a6cd96b0 --- /dev/null +++ b/modules-available/usblockoff/templates/usb-device-list.html @@ -0,0 +1,173 @@ +<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> |