MISP/app/Controller/Component/ACLComponent.php

466 lines
16 KiB
PHP
Raw Normal View History

2016-04-17 23:13:39 +02:00
<?php
App::uses('Component', 'Controller');
class ACLComponent extends Component {
2016-04-18 03:19:01 +02:00
// syntax:
// $__aclList[$controller][$action] = $permission_rules
// $controller == '*' - any controller can have this action
// $action == array() - site admin only has access
// $action == '*' - any role has access
// $action == array('OR' => array()) - any role in the array has access
// $action == array('AND' => array()) - roles with all permissions in the array have access
// If we add any new functionality to MISP and we don't add it to this list, it will only be visible to site admins.
2016-04-17 23:13:39 +02:00
private $__aclList = array(
'*' => array(
'blackhole' => array(),
'checkAction' => array(),
'checkAuthUser' => array(),
'checkExternalAuthUser' => array(),
'cleanModelCaches' => array(),
2016-04-18 03:19:01 +02:00
'debugACL' => array(),
2016-04-17 23:13:39 +02:00
'generateCount' => array(),
'getActions' => array(),
'pruneDuplicateUUIDs' => array(),
2016-04-22 15:03:20 +02:00
'queryACL' => array(),
2016-04-17 23:13:39 +02:00
'removeDuplicateEvents' => array(),
'updateDatabase' => array(),
'upgrade2324' => array(),
),
'attributes' => array(
'add' => array('perm_add'),
'add_attachment' => array('perm_add'),
'add_threatconnect' => array('perm_add'),
'attributeReplace' => array('perm_add'),
'attributeStatistics' => array('*'),
2016-04-17 23:13:39 +02:00
'checkComposites' => array('perm_admin'),
'delete' => array('perm_add'),
'deleteSelected' => array('perm_add'),
'describeTypes' => array('perm_auth'),
'download' => array('*'),
'downloadAttachment' => array('*'),
'downloadSample' => array('*'),
'edit' => array('perm_add'),
'editField' => array('perm_add'),
'editSelected' => array('perm_add'),
'fetchEditForm' => array('perm_add'),
'fetchViewValue' => array('*'),
'generateCorrelation' => array(),
'hoverEnrichment' => array('perm_add'),
'index' => array('*'),
'pruneOrphanedAttributes' => array(),
'reportValidationIssuesAttributes' => array(),
'restore' => array('perm_add'),
2016-04-17 23:13:39 +02:00
'restSearch' => array('*'),
'returnAttributes' => array('*'),
'rpz' => array('*'),
'search' => array('*'),
'searchAlternate' => array('*'),
'text' => array('*'),
'updateAttributeValues' => array('perm_add'),
'view' => array('*'),
),
'eventBlacklists' => array(
'add' => array(),
'delete' => array(),
'edit' => array(),
'index' => array(),
),
'eventDelegations' => array(
'acceptDelegation' => array('perm_add'),
'delegateEvent' => array('perm_add'),
'deleteDelegation' => array('perm_add'),
'view' => array('*'),
),
'events' => array(
'add' => array('perm_add'),
'addIOC' => array('perm_add'),
'addTag' => array('perm_tagger'),
'add_misp_export' => array('perm_modify'),
'alert' => array('perm_publish'),
'automation' => array('perm_auth'),
'checkuuid' => array('perm_sync'),
'contact' => array('*'),
'create_dummy_event' => array(),
'create_massive_dummy_events' => array(),
'csv' => array('*'),
'delegation_index' => array('*'),
'delete' => array('perm_add'),
'dot' => array(),
'downloadExport' => array('*'),
'downloadOpenIOCEvent' => array('*'),
'downloadSearchResult' => array('*'),
'edit' => array('perm_add'),
'export' => array('*'),
'exportChoice' => array('*'),
'filterEventIdsForPush' => array('perm_sync'),
'filterEventIndex' => array('*'),
'freeTextImport' => array('perm_add'),
'hids' => array('*'),
'index' => array('*'),
'nids' => array('*'),
'proposalEventIndex' => array('*'),
'publish' => array('perm_publish'),
'pushProposals' => array('perm_sync'),
'queryEnrichment' => array('perm_add'),
'removePivot' => array('*'),
'removeTag' => array('perm_tagger'),
'reportValidationIssuesEvents' => array(),
'restSearch' => array('*'),
'saveFreeText' => array('perm_add'),
'stix' => array('*'),
'strposarray' => array(),
'updateGraph' => array('*'),
'upload_sample' => array('perm_auth'),
'view' => array('*'),
'viewEventAttributes' => array('*'),
'viewGraph' => array('*'),
'xml' => array('*'),
),
'favouriteTags' => array(
'index' => array('*'),
'toggle' => array('*'),
'getToggleField' => array('*')
),
2016-04-17 23:13:39 +02:00
'feeds' => array(
'add' => array(),
'delete' => array(),
'disable' => array(),
2016-04-17 23:13:39 +02:00
'edit' => array(),
'enable' => array(),
2016-04-17 23:13:39 +02:00
'fetchFromFeed' => array(),
'getEvent' => array(),
'index' => array(),
'previewEvent' => array(),
'previewIndex' => array(),
'view' => array(),
),
'jobs' => array(
2016-04-18 03:19:01 +02:00
'cache' => array('*'),
'getGenerateCorrelationProgress' => array('*'),
'getProgress' => array('*'),
2016-04-17 23:13:39 +02:00
'index' => array(),
),
'logs' => array(
2016-04-18 03:19:01 +02:00
'admin_index' => array('perm_audit'),
'admin_search' => array('perm_audit'),
'event_index' => array('*'),
'maxDateActivity' => array('*'),
'returnDates' => array('*'),
2016-04-17 23:13:39 +02:00
),
'news' => array(
'add' => array(),
'edit' => array(),
'delete' => array(),
'index' => array('*'),
),
2016-04-17 23:13:39 +02:00
'orgBlacklists' => array(
'add' => array(),
'delete' => array(),
'edit' => array(),
'index' => array(),
),
'organisations' => array(
'admin_add' => array(),
'admin_delete' => array(),
'admin_edit' => array(),
'admin_generateuuid' => array(),
'admin_merge' => array(),
2016-04-18 03:19:01 +02:00
'fetchOrgsForSG' => array('*'),
'fetchSGOrgRow' => array('*'),
'getUUIDs' => array('perm_sync'),
'index' => array('*'),
'landingpage' => array('*'),
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'pages' => array(
2016-04-18 03:19:01 +02:00
'display' => array('*'),
2016-04-17 23:13:39 +02:00
),
'posts' => array(
2016-04-18 03:19:01 +02:00
'add' => array('*'),
'delete' => array('*'),
'edit' => array('*'),
2016-04-17 23:13:39 +02:00
),
'regexp' => array(
2016-04-18 03:19:01 +02:00
'admin_add' => array('perm_regexp_access'),
'admin_clean' => array('perm_regexp_access'),
'admin_delete' => array('perm_regexp_access'),
'admin_edit' => array('perm_regexp_access'),
'admin_index' => array('perm_regexp_access'),
'cleanRegexModifiers' => array('perm_regexp_access'),
'index' => array('*'),
2016-04-17 23:13:39 +02:00
),
'roles' => array(
'admin_add' => array(),
'admin_delete' => array(),
'admin_edit' => array(),
'admin_index' => array('perm_admin'),
2016-04-18 03:19:01 +02:00
'index' => array('*'),
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'servers' => array(
'add' => array(),
'delete' => array(),
'deleteFile' => array(),
'edit' => array(),
2016-04-18 03:19:01 +02:00
'fetchServersForSG' => array('*'),
2016-04-17 23:13:39 +02:00
'filterEventIndex' => array(),
'getVersion' => array('*'),
2016-04-18 03:19:01 +02:00
'index' => array('OR' => array('perm_sync', 'perm_admin')),
2016-04-17 23:13:39 +02:00
'previewEvent' => array(),
'previewIndex' => array(),
2016-04-18 03:19:01 +02:00
'pull' => array('perm_auth'),
2016-04-17 23:13:39 +02:00
'purgeSessions' => array(),
2016-04-18 03:19:01 +02:00
'push' => array('perm_auth'),
2016-04-17 23:13:39 +02:00
'restartWorkers' => array(),
'serverSettings' => array(),
'serverSettingsEdit' => array(),
'serverSettingsReloadSetting' => array(),
'startWorker' => array(),
'startZeroMQServer' => array(),
'statusZeroMQServer' => array(),
'stopWorker' => array(),
'stopZeroMQServer' => array(),
2016-04-18 03:19:01 +02:00
'testConnection' => array('perm_sync'),
2016-04-17 23:13:39 +02:00
'uploadFile' => array(),
),
'shadowAttributes' => array(
2016-04-18 03:19:01 +02:00
'accept' => array('perm_add'),
'acceptSelected' => array('perm_add'),
'add' => array('perm_add'),
'add_attachment' => array('perm_add'),
'delete' => array('perm_add'),
'discard' => array('perm_add'),
'discardSelected' => array('perm_add'),
'download' => array('*'),
'edit' => array('perm_add'),
'editField' => array('perm_add'),
'fetchEditForm' => array('perm_add'),
2016-04-17 23:13:39 +02:00
'generateCorrelation' => array(),
2016-04-18 03:19:01 +02:00
'getProposalsByUuid' => array('perm_sync'),
'getProposalsByUuidList' => array('perm_sync'),
'index' => array('*'),
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'sharingGroups' => array(
2016-04-18 03:19:01 +02:00
'add' => array('perm_sharing_group'),
'delete' => array('perm_sharing_group'),
'edit' => array('perm_sharing_group'),
'index' => array('*'),
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'sightings' => array(
2016-04-18 03:19:01 +02:00
'add' => array('perm_add'),
'delete' => array('perm_add'),
2016-04-17 23:13:39 +02:00
),
'tags' => array(
2016-04-18 03:19:01 +02:00
'add' => array('perm_tag_editor'),
'delete' => array('perm_tag_editor'),
'edit' => array('perm_tag_editor'),
'index' => array('*'),
'quickAdd' => array('perm_tag_editor'),
'selectTag' => array('perm_tagger'),
'selectTaxonomy' => array('perm_tagger'),
'showEventTag' => array('*'),
'tagStatistics' => array('*'),
2016-04-18 03:19:01 +02:00
'view' => array('*'),
'viewTag' => array('*'),
2016-04-17 23:13:39 +02:00
),
'tasks' => array(
'index' => array(),
'setTask' => array(),
),
'taxonomies' => array(
'addTag' => array(),
'disable' => array(),
'enable' => array(),
2016-04-18 03:19:01 +02:00
'index' => array('*'),
'taxonomyMassConfirmation' => array('perm_tagger'),
2016-04-17 23:13:39 +02:00
'update' => array(),
2016-04-18 03:19:01 +02:00
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'templateElements' => array(
2016-04-18 03:19:01 +02:00
'add' => array('perm_template'),
'delete' => array('perm_template'),
'edit' => array('perm_template'),
'index' => array('*'),
'templateElementAddChoices' => array('perm_template'),
2016-04-17 23:13:39 +02:00
),
'templates' => array(
2016-04-18 03:19:01 +02:00
'add' => array('perm_template'),
'delete' => array('perm_template'),
'deleteTemporaryFile' => array('perm_add'),
'edit' => array('perm_template'),
'index' => array('*'),
'populateEventFromTemplate' => array('perm_add'),
'saveElementSorting' => array('perm_template'),
'submitEventPopulation' => array('perm_add'),
'templateChoices' => array('*'),
'uploadFile' => array('*'),
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
'threads' => array(
2016-04-18 03:19:01 +02:00
'index' => array('*'),
'view' => array('*'),
'viewEvent' => array('*'),
2016-04-17 23:13:39 +02:00
),
'users' => array(
2016-04-18 03:19:01 +02:00
'admin_add' => array('perm_admin'),
'admin_delete' => array('perm_admin'),
'admin_edit' => array('perm_admin'),
'admin_email' => array('perm_admin'),
'admin_filterUserIndex' => array('perm_admin'),
'admin_index' => array('perm_admin'),
'admin_view' => array('perm_admin'),
2016-04-17 23:13:39 +02:00
'arrayCopy' => array(),
2016-04-18 14:52:05 +02:00
'change_pw' => array('*'),
2016-04-17 23:13:39 +02:00
'checkAndCorrectPgps' => array(),
2016-04-18 14:06:17 +02:00
'dashboard' => array('*'),
2016-04-18 03:19:01 +02:00
'delete' => array('perm_admin'),
'downloadTerms' => array('*'),
'edit' => array('*'),
'fetchPGPKey' => array('perm_admin'),
'histogram' => array('*'),
'index' => array('*'),
'initiatePasswordReset' => array('perm_admin'),
'login' => array('*'),
'logout' => array('*'),
'memberslist' => array('*'),
'resetauthkey' => array('*'),
'routeafterlogin' => array('*'),
'statistics' => array('*'),
'terms' => array('*'),
'updateLoginTime' => array('*'),
'verifyCertificate' => array(),
2016-04-17 23:13:39 +02:00
'verifyGPG' => array(),
2016-04-18 03:19:01 +02:00
'view' => array('*'),
2016-04-17 23:13:39 +02:00
),
2016-04-22 15:03:20 +02:00
'warninglists' => array(
'enableWarninglist' => array(),
'getToggleField' => array(),
'index' => array('*'),
'toggleEnable' => array(),
'update' => array(),
'view' => array('*')
),
2016-04-17 23:13:39 +02:00
'whitelists' => array(
2016-04-18 03:19:01 +02:00
'admin_add' => array('perm_regexp_access'),
'admin_delete' => array('perm_regexp_access'),
'admin_edit' => array('perm_regexp_access'),
'admin_index' => array('perm_regexp_access'),
'index' => array('*'),
2016-04-17 23:13:39 +02:00
)
);
2016-04-18 03:19:01 +02:00
// The check works like this:
// If the user is a site admin, return true
// If the requested action has an OR-d list, iterate through the list. If any of the permissions are set for the user, return true
// If the requested action has an AND-ed list, iterate through the list. If any of the permissions for the user are not set, turn the check to false. Otherwise return true.
// If the requested action has a permission, check if the user's role has it flagged. If yes, return true
// If we fall through all of the checks, return an exception.
2016-04-17 23:13:39 +02:00
public function checkAccess($user, $controller, $action) {
2016-04-18 03:19:01 +02:00
if ($user['Role']['perm_site_admin']) return true;
2016-04-17 23:13:39 +02:00
if (!isset($this->__aclList[$controller])) $this->__error(404, 'Invalid controller.');
2016-06-04 01:10:45 +02:00
if ($user['Role']['perm_site_admin']) return true;
2016-04-18 03:19:01 +02:00
if (isset($this->__aclList[$controller][$action]) && !empty($this->__aclList[$controller][$action])) {
if (in_array('*', $this->__aclList[$controller][$action])) return true;
if (isset($this->__aclList[$controller][$action]['OR'])) {
2016-04-18 15:32:09 +02:00
foreach ($this->__aclList[$controller][$action]['OR'] as $permission) if ($user['Role'][$permission]) return true;
2016-04-18 03:19:01 +02:00
} else if (isset($this->__aclList[$controller][$action]['AND'])) {
$allConditionsMet = true;
2016-04-18 15:32:09 +02:00
foreach ($this->__aclList[$controller][$action]['AND'] as $permission) if (!$user['Role'][$permission]) $allConditionsMet = false;
2016-04-18 03:19:01 +02:00
if ($allConditionsMet) return true;
} else if ($user['Role'][$this->__aclList[$controller][$action][0]]) return true;
}
2016-04-17 23:13:39 +02:00
$this->__error(403, 'You do not have permission to use this functionality.');
}
2016-04-17 23:13:39 +02:00
private function __error($code, $message) {
switch ($code) {
2016-06-04 01:10:45 +02:00
case 404:
2016-04-17 23:13:39 +02:00
throw new NotFoundException($message);
break;
2016-04-18 03:19:01 +02:00
case 403:
throw new MethodNotAllowedException($message);
2016-04-17 23:13:39 +02:00
default:
2016-06-04 01:10:45 +02:00
throw new InternalErrorException('Unknown error: ' . $message);
2016-04-17 23:13:39 +02:00
}
}
2016-04-18 03:19:01 +02:00
private function __findAllFunctions() {
2016-04-17 23:13:39 +02:00
$functionFinder = '/function[\s\n]+(\S+)[\s\n]*\(/';
$dir = new Folder(APP . 'Controller');
$files = $dir->find('.*\.php');
$results = array();
foreach ($files as $file) {
$controllerName = lcfirst(str_replace('Controller.php', "", $file));
if ($controllerName === 'app') $controllerName = '*';
$functionArray = array();
$fileContents = file_get_contents(APP . 'Controller' . DS . $file);
preg_match_all($functionFinder, $fileContents, $functionArray);
foreach ($functionArray[1] as $function) {
if (substr($function, 0, 1) !== '_' && $function !== 'beforeFilter') $results[$controllerName][] = $function;
}
}
2016-04-18 03:19:01 +02:00
return $results;
}
2016-04-18 03:19:01 +02:00
public function printAllFunctionNames($content = false) {
$results = $this->__findAllFunctions();
2016-04-17 23:13:39 +02:00
ksort($results);
2016-04-18 09:14:36 +02:00
return $results;
2016-06-04 01:10:45 +02:00
}
2016-04-18 03:19:01 +02:00
public function findMissingFunctionNames($content = false) {
$results = $this->__findAllFunctions();
$missing = array();
foreach ($results as $controller => &$functions) {
foreach ($functions as &$function) {
2016-06-04 01:10:45 +02:00
if (!isset($this->__aclList[$controller])
|| !in_array($function, array_keys($this->__aclList[$controller])))
2016-04-18 03:19:01 +02:00
$missing[$controller][] = $function;
}
}
return $missing;
}
2016-04-18 03:19:01 +02:00
public function printRoleAccess($content = false) {
$results = array();
$this->Role = ClassRegistry::init('Role');
$conditions = array();
if (is_numeric($content)) $conditions = array('Role.id' => $content);
$roles = $this->Role->find('all', array(
'recursive' => -1,
2016-06-04 01:10:45 +02:00
'conditions' => $conditions
2016-04-18 03:19:01 +02:00
));
if (empty($roles)) throw new NotFoundException('Role not found.');
foreach ($roles as &$role) {
$urls = $this->__checkRoleAccess($role['Role']);
$results[$role['Role']['id']] = array('name' => $role['Role']['name'], 'urls' => $urls);
}
return $results;
}
2016-04-18 03:19:01 +02:00
private function __checkRoleAccess($role) {
$result = array();
foreach ($this->__aclList as $controller => &$actions) {
$controllerNames = Inflector::variable($controller) == Inflector::underscore($controller) ? array(Inflector::variable($controller)) : array(Inflector::variable($controller), Inflector::underscore($controller));
foreach ($controllerNames as $controllerName) {
foreach ($actions as $action => $permissions) {
if ($role['perm_site_admin']) $result[] = DS . $controllerName . DS . $action;
else if (in_array('*', $permissions)) $result[] = DS . $controllerName . DS . $action . DS . '*';
else if (isset($permissions['OR'])) {
$access = false;
2016-06-04 01:10:45 +02:00
foreach ($permissions['OR'] as $permission) if ($role[$permission]) $access = true;
if ($access) $result[] = DS . $controllerName . DS . $action . DS . '*';
} else if (isset($permissions['AND'])) {
$access = true;
foreach ($permissions['AND'] as $permission) if ($role[$permission]) $access = false;
if ($access) $result[] = DS . $controllerName . DS . $action . DS . '*';
} else if (isset($permissions[0]) && $role[$permissions[0]]) $result[] = DS . $controllerName . DS . $action . DS . '*';
}
2016-04-18 03:19:01 +02:00
}
}
return $result;
}
2016-04-17 23:13:39 +02:00
}