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' ),
2016-04-18 14:40:08 +02:00
'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 (),
2016-05-20 11:20:03 +02:00
'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 ( '*' ),
),
2016-04-28 16:16:23 +02:00
'favouriteTags' => array (
'index' => array ( '*' ),
'toggle' => array ( '*' ),
'getToggleField' => array ( '*' )
),
2016-04-17 23:13:39 +02:00
'feeds' => array (
'add' => array (),
'delete' => array (),
2016-05-26 01:39:31 +02:00
'disable' => array (),
2016-04-17 23:13:39 +02:00
'edit' => array (),
2016-05-26 01:39:31 +02:00
'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
),
2016-05-20 01:17:26 +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 (),
2016-04-19 10:32:22 +02:00
'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 (),
2016-04-29 15:59:02 +02:00
'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 ( '*' ),
2016-05-22 23:35:24 +02:00
'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 ( '*' ),
2016-05-20 11:20:03 +02:00
'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-06-04 01:08:16 +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-06-04 01:08:16 +02:00
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-06-04 01:08:16 +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-06-04 01:08:16 +02:00
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-06-04 01:08:16 +02:00
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-06-04 01:08:16 +02:00
2016-04-18 03:19:01 +02:00
private function __checkRoleAccess ( $role ) {
$result = array ();
foreach ( $this -> __aclList as $controller => & $actions ) {
2016-04-18 15:39:55 +02:00
$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 ;
2016-04-18 15:39:55 +02:00
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
}