diff --git a/CHANGELOG.md b/CHANGELOG.md index d17091b..f1a2fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [UNRELEASED] +### Fixed + +- Fix missing right checks on Jamf import, merge, sync, cron and MDM command endpoints + ## [3.2.1] - 2026-04-30 ### Fixed diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ef1bed5 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +include ../../PluginsMakefile.mk diff --git a/ajax/cron.php b/ajax/cron.php index 695f256..78a88aa 100644 --- a/ajax/cron.php +++ b/ajax/cron.php @@ -40,7 +40,7 @@ Html::header_nocache(); -Session::checkLoginUser(); +Session::checkRight('config', UPDATE); /** @var DBmysql $DB */ global $DB; diff --git a/ajax/getMDMCommandForm.php b/ajax/getMDMCommandForm.php index 9ab2c99..c6f655d 100644 --- a/ajax/getMDMCommandForm.php +++ b/ajax/getMDMCommandForm.php @@ -36,7 +36,7 @@ throw new NotFoundHttpException(); } -Session::checkLoginUser(); +Session::checkRight(PluginJamfMobileDevice::$rightname, READ); // An action must be specified if (!isset($_GET['command'])) { @@ -44,8 +44,9 @@ } if (isset($_GET['itemtype'], $_GET['items_id'])) { + /** @var class-string $className */ $className = 'PluginJamf' . $_GET['itemtype']; - if (is_a($className, 'CommonDBTM', true) === false) { + if (is_a($className, PluginJamfAbstractDevice::class, true) === false) { throw new RuntimeException('Invalid itemtype!'); } @@ -53,6 +54,17 @@ if (!$device->getFromDB($_GET['items_id'])) { throw new RuntimeException('Invalid itemtype/items_id!'); } + + $device_data = $device->getJamfDeviceData(); + $glpi_itemtype = $device_data['itemtype'] ?? null; + if (!is_string($glpi_itemtype) || !is_a($glpi_itemtype, CommonDBTM::class, true)) { + throw new RuntimeException('Invalid itemtype/items_id!'); + } + + $glpi_item = new $glpi_itemtype(); + if (!$glpi_item->getFromDB($device_data['items_id']) || !Session::haveAccessToEntity($glpi_item->fields['entities_id'])) { + throw new RuntimeException('Invalid itemtype/items_id!'); + } } else { $device = null; } diff --git a/ajax/import.php b/ajax/import.php index 5dce5ad..b74dbba 100644 --- a/ajax/import.php +++ b/ajax/import.php @@ -40,7 +40,7 @@ Html::header_nocache(); -Session::checkLoginUser(); +Session::checkRight(PluginJamfMobileDevice::$rightname, CREATE); /** @var DBmysql $DB */ global $DB; diff --git a/ajax/merge.php b/ajax/merge.php index dcb8c16..6485c05 100644 --- a/ajax/merge.php +++ b/ajax/merge.php @@ -40,7 +40,7 @@ Html::header_nocache(); -Session::checkLoginUser(); +Session::checkRight(PluginJamfMobileDevice::$rightname, CREATE); /** @var DBmysql $DB */ global $DB; @@ -76,6 +76,11 @@ } $item = new $itemtype(); + if (!$item->getFromDB($glpi_id) || !Session::haveAccessToEntity($item->fields['entities_id'])) { + $failures++; + continue; + } + /** @var class-string $plugin_itemtype */ $plugin_itemtype = 'PluginJamf' . $data['jamf_type']; /** @var class-string $plugin_sync_itemtype */ diff --git a/ajax/sync.php b/ajax/sync.php index bb087c3..57ac1c8 100644 --- a/ajax/sync.php +++ b/ajax/sync.php @@ -40,7 +40,7 @@ Html::header_nocache(); -Session::checkLoginUser(); +Session::checkRight(PluginJamfMobileDevice::$rightname, UPDATE); /** @var DBmysql $DB */ global $DB; @@ -54,6 +54,15 @@ throw new RuntimeException('Required argument missing!'); } +if (!is_a($_REQUEST['itemtype'], CommonDBTM::class, true)) { + throw new RuntimeException('Invalid itemtype!'); +} + +$synced_item = new $_REQUEST['itemtype'](); +if (!$synced_item->getFromDB((int) $_REQUEST['items_id']) || !Session::haveAccessToEntity($synced_item->fields['entities_id'])) { + throw new RuntimeException('Invalid item!'); +} + try { $jamf_class = PluginJamfAbstractDevice::getJamfItemClassForGLPIItem($_REQUEST['itemtype'], $_REQUEST['items_id']); if ($jamf_class !== null) { diff --git a/front/import.php b/front/import.php index 4e5a5c5..822bde5 100644 --- a/front/import.php +++ b/front/import.php @@ -37,7 +37,7 @@ throw new NotFoundHttpException(); } -Session::checkRight('plugin_jamf_mobiledevice', CREATE); +Session::checkRight(PluginJamfMobileDevice::$rightname, CREATE); Html::header('Jamf Plugin', '', 'tools', 'PluginJamfMenu', 'import'); global $DB, $CFG_GLPI; diff --git a/front/menu.php b/front/menu.php index 2ece589..b6dc5b9 100644 --- a/front/menu.php +++ b/front/menu.php @@ -45,7 +45,7 @@ $plugin_dir = $CFG_GLPI['root_doc'] . '/plugins/jamf'; $links = []; -if (Session::haveRight('plugin_jamf_mobiledevice', CREATE)) { +if (Session::haveRight(PluginJamfMobileDevice::$rightname, CREATE)) { $links[] = [ 'name' => _x('menu', 'Import devices', 'jamf'), 'url' => PluginJamfImport::getSearchURL(), diff --git a/front/merge.php b/front/merge.php index 619f70b..a45b2f2 100644 --- a/front/merge.php +++ b/front/merge.php @@ -39,7 +39,7 @@ throw new NotFoundHttpException(); } -Session::checkRight('plugin_jamf_mobiledevice', CREATE); +Session::checkRight(PluginJamfMobileDevice::$rightname, CREATE); Html::header('Jamf Plugin', '', 'tools', 'PluginJamfMenu', 'import'); global $DB, $CFG_GLPI; diff --git a/inc/computersync.class.php b/inc/computersync.class.php index 65c1394..896fb53 100644 --- a/inc/computersync.class.php +++ b/inc/computersync.class.php @@ -61,7 +61,7 @@ protected function syncGeneral(): PluginJamfDeviceSync $other_general_items['udid'] = 'uuid'; foreach ($other_general_items as $jamf_field => $item_field) { if ($general[$jamf_field] !== $this->item->fields[$item_field]) { - $this->item_changes[$item_field] = $this->db->escape($general[$jamf_field]); + $this->item_changes[$item_field] = $general[$jamf_field]; } } diff --git a/inc/mobilesync.class.php b/inc/mobilesync.class.php index b91cce5..c32bf60 100644 --- a/inc/mobilesync.class.php +++ b/inc/mobilesync.class.php @@ -66,7 +66,7 @@ protected function syncGeneral(): PluginJamfDeviceSync foreach ($other_general_items as $jamf_field => $item_field) { if ($general[$jamf_field] !== $this->item->fields[$item_field]) { - $this->item_changes[$item_field] = $this->db->escape($general[$jamf_field]); + $this->item_changes[$item_field] = $general[$jamf_field]; } } diff --git a/rector.php b/rector.php index 3c3e284..ef24ec6 100644 --- a/rector.php +++ b/rector.php @@ -29,31 +29,28 @@ * ------------------------------------------------------------------------- */ +use Rector\Configuration\RectorConfigBuilder; + require_once __DIR__ . '/../../src/Plugin.php'; -use Rector\Caching\ValueObject\Storage\FileCacheStorage; -use Rector\Config\RectorConfig; -use Rector\ValueObject\PhpVersion; +$baseline_file = __DIR__ . '/../../PluginsRector.php'; +if (!file_exists($baseline_file)) { + throw new RuntimeException( + sprintf( + 'Unable to find "%s". Running rector on a plugin requires a GLPI development checkout that ships PluginsRector.php.', + $baseline_file, + ), + ); +} + +$baseline = require $baseline_file; + +/** @var RectorConfigBuilder $config */ +$config = $baseline([ + __DIR__ . '/ajax', + __DIR__ . '/front', + __DIR__ . '/inc', + __DIR__ . '/tests', +]); -return RectorConfig::configure() - ->withPaths([ - __DIR__ . '/ajax', - __DIR__ . '/front', - __DIR__ . '/inc', - __DIR__ . '/tests', - ]) - ->withPhpVersion(PhpVersion::PHP_82) - ->withCache( - cacheDirectory: __DIR__ . '/var/rector', - cacheClass: FileCacheStorage::class, - ) - ->withRootFiles() - ->withParallel(timeoutSeconds: 300) - ->withImportNames(removeUnusedImports: true) - ->withPreparedSets( - deadCode: true, - codeQuality: true, - codingStyle: true, - ) - ->withPhpSets(php82: true) // apply PHP sets up to PHP 8.2 -; +return $config; diff --git a/setup.php b/setup.php index 80a4e7b..e3cd3ea 100644 --- a/setup.php +++ b/setup.php @@ -61,7 +61,7 @@ function plugin_init_jamf() 'Phone', ]]); Plugin::registerClass('PluginJamfUser_JSSAccount', ['addtabon' => ['User']]); - if (Session::haveRight('plugin_jamf_mobiledevice', READ)) { + if (Session::haveRight(PluginJamfMobileDevice::$rightname, READ)) { $PLUGIN_HOOKS['menu_toadd']['jamf'] = ['tools' => 'PluginJamfMenu']; }