2013-05-22 10:52:03 +02:00
< ? php
App :: uses ( 'AppController' , 'Controller' );
App :: uses ( 'Xml' , 'Utility' );
2020-05-05 15:23:26 +02:00
App :: uses ( 'AttachmentTool' , 'Tools' );
2022-02-23 13:43:10 +01:00
App :: uses ( 'JsonTool' , 'Tools' );
2020-12-11 08:54:40 +01:00
App :: uses ( 'SecurityAudit' , 'Tools' );
2013-05-22 10:52:03 +02:00
2020-09-23 17:28:01 +02:00
/**
* @ property Server $Server
*/
2018-07-19 11:48:22 +02:00
class ServersController extends AppController
{
2021-11-23 14:53:27 +01:00
public $components = array ( 'RequestHandler' ); // XXX ACL component
2018-07-19 11:48:22 +02:00
public $paginate = array (
2021-08-25 10:29:45 +02:00
'limit' => 60 ,
'recursive' => - 1 ,
'contain' => array (
'User' => array (
'fields' => array ( 'User.id' , 'User.org_id' , 'User.email' ),
),
'Organisation' => array (
'fields' => array ( 'Organisation.name' , 'Organisation.id' ),
2018-07-19 11:48:22 +02:00
),
2021-08-25 10:29:45 +02:00
'RemoteOrg' => array (
'fields' => array ( 'RemoteOrg.name' , 'RemoteOrg.id' ),
2018-07-19 11:48:22 +02:00
),
2021-08-25 10:29:45 +02:00
),
2023-05-21 10:09:05 +02:00
'maxLimit' => 9999 ,
2021-08-25 10:29:45 +02:00
'order' => array (
'Server.priority' => 'ASC'
),
2018-07-19 11:48:22 +02:00
);
public $uses = array ( 'Server' , 'Event' );
public function beforeFilter ()
{
2021-02-25 22:04:50 +01:00
$this -> Auth -> allow ([ 'cspReport' ]); // cspReport must work without authentication
2018-07-19 11:48:22 +02:00
parent :: beforeFilter ();
2021-02-25 22:04:50 +01:00
$this -> Security -> unlockedActions [] = 'cspReport' ;
2018-07-19 11:48:22 +02:00
// permit reuse of CSRF tokens on some pages.
switch ( $this -> request -> params [ 'action' ]) {
case 'push' :
case 'pull' :
case 'getVersion' :
case 'testConnection' :
$this -> Security -> csrfUseOnce = false ;
}
}
public function index ()
{
2021-08-25 10:29:45 +02:00
// Do not fetch server authkey from DB
$fields = $this -> Server -> schema ();
unset ( $fields [ 'authkey' ]);
$fields = array_keys ( $fields );
2023-04-18 11:11:59 +02:00
$filters = $this -> IndexFilter -> harvestParameters ([ 'search' ]);
$conditions = [];
if ( ! empty ( $filters [ 'search' ])) {
$strSearch = '%' . trim ( strtolower ( $filters [ 'search' ])) . '%' ;
$conditions [ 'OR' ][][ 'LOWER(Server.name) LIKE' ] = $strSearch ;
$conditions [ 'OR' ][][ 'LOWER(Server.url) LIKE' ] = $strSearch ;
}
2018-08-22 17:00:13 +02:00
if ( $this -> _isRest ()) {
2018-11-23 14:11:33 +01:00
$params = array (
2021-08-25 10:29:45 +02:00
'fields' => $fields ,
2018-11-23 14:11:33 +01:00
'recursive' => - 1 ,
'contain' => array (
2021-08-25 10:29:45 +02:00
'User' => array (
'fields' => array ( 'User.id' , 'User.org_id' , 'User.email' ),
),
'Organisation' => array (
'fields' => array ( 'Organisation.id' , 'Organisation.name' , 'Organisation.uuid' , 'Organisation.nationality' , 'Organisation.sector' , 'Organisation.type' ),
),
'RemoteOrg' => array (
'fields' => array ( 'RemoteOrg.id' , 'RemoteOrg.name' , 'RemoteOrg.uuid' , 'RemoteOrg.nationality' , 'RemoteOrg.sector' , 'RemoteOrg.type' ),
),
2019-01-20 10:19:05 +01:00
),
2023-04-18 11:11:59 +02:00
'conditions' => $conditions ,
2018-11-23 14:11:33 +01:00
);
$servers = $this -> Server -> find ( 'all' , $params );
2019-01-20 10:19:05 +01:00
$servers = $this -> Server -> attachServerCacheTimestamps ( $servers );
2018-11-23 14:11:33 +01:00
return $this -> RestResponse -> viewData ( $servers , $this -> response -> type ());
} else {
2021-08-25 10:29:45 +02:00
$this -> paginate [ 'fields' ] = $fields ;
2023-04-18 11:11:59 +02:00
$this -> paginate [ 'conditions' ] = $conditions ;
2019-01-20 10:19:05 +01:00
$servers = $this -> paginate ();
$servers = $this -> Server -> attachServerCacheTimestamps ( $servers );
$this -> set ( 'servers' , $servers );
2018-11-23 14:11:33 +01:00
$collection = array ();
$collection [ 'orgs' ] = $this -> Server -> Organisation -> find ( 'list' , array (
'fields' => array ( 'id' , 'name' ),
));
$this -> loadModel ( 'Tag' );
$collection [ 'tags' ] = $this -> Tag -> find ( 'list' , array (
'fields' => array ( 'id' , 'name' ),
));
$this -> set ( 'collection' , $collection );
}
2018-07-19 11:48:22 +02:00
}
public function previewIndex ( $id )
{
$urlparams = '' ;
$passedArgs = array ();
2021-01-18 10:04:53 +01:00
$server = $this -> Server -> find ( 'first' , array ( 'conditions' => array ( 'Server.id' => $id ), 'recursive' => - 1 ));
2018-07-19 11:48:22 +02:00
if ( empty ( $server )) {
throw new NotFoundException ( 'Invalid server ID.' );
}
$validFilters = $this -> Server -> validEventIndexFilters ;
foreach ( $validFilters as $k => $filter ) {
if ( isset ( $this -> passedArgs [ $filter ])) {
$passedArgs [ $filter ] = $this -> passedArgs [ $filter ];
if ( $k != 0 ) {
$urlparams .= '/' ;
}
$urlparams .= $filter . ':' . $this -> passedArgs [ $filter ];
}
}
$combinedArgs = array_merge ( $this -> passedArgs , $passedArgs );
if ( ! isset ( $combinedArgs [ 'sort' ])) {
$combinedArgs [ 'sort' ] = 'timestamp' ;
$combinedArgs [ 'direction' ] = 'desc' ;
}
2019-08-02 14:42:23 +02:00
if ( empty ( $combinedArgs [ 'page' ])) {
$combinedArgs [ 'page' ] = 1 ;
}
if ( empty ( $combinedArgs [ 'limit' ])) {
$combinedArgs [ 'limit' ] = 60 ;
}
2019-10-10 19:10:52 +02:00
try {
2021-01-18 10:04:53 +01:00
list ( $events , $total_count ) = $this -> Server -> previewIndex ( $server , $this -> Auth -> user (), $combinedArgs );
2019-10-10 19:10:52 +02:00
} catch ( Exception $e ) {
2021-10-28 21:56:41 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> throwException ( 500 , $e -> getMessage ());
} else {
$this -> Flash -> error ( __ ( 'Download failed.' ) . ' ' . $e -> getMessage ());
$this -> redirect ( array ( 'action' => 'index' ));
}
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $events , $this -> response -> type ());
2019-10-10 19:10:52 +02:00
}
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'Event' );
2021-03-30 09:38:41 +02:00
$this -> set ( 'threatLevels' , $this -> Event -> ThreatLevel -> listThreatLevels ());
2018-07-19 11:48:22 +02:00
App :: uses ( 'CustomPaginationTool' , 'Tools' );
$customPagination = new CustomPaginationTool ();
$params = $customPagination -> createPaginationRules ( $events , $this -> passedArgs , $this -> alias );
2019-08-02 14:42:23 +02:00
if ( ! empty ( $total_count )) {
$params [ 'pageCount' ] = ceil ( $total_count / $params [ 'limit' ]);
}
2018-07-19 11:48:22 +02:00
$this -> params -> params [ 'paging' ] = array ( $this -> modelClass => $params );
2019-10-10 19:10:52 +02:00
if ( count ( $events ) > 60 ) {
$customPagination -> truncateByPagination ( $events , $params );
}
2018-07-19 11:48:22 +02:00
$this -> set ( 'events' , $events );
$this -> set ( 'eventDescriptions' , $this -> Event -> fieldDescriptions );
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'distributionLevels' , $this -> Event -> distributionLevels );
$shortDist = array ( 0 => 'Organisation' , 1 => 'Community' , 2 => 'Connected' , 3 => 'All' , 4 => ' sharing Group' );
$this -> set ( 'shortDist' , $shortDist );
$this -> set ( 'id' , $id );
$this -> set ( 'urlparams' , $urlparams );
$this -> set ( 'passedArgs' , json_encode ( $passedArgs ));
$this -> set ( 'passedArgsArray' , $passedArgs );
$this -> set ( 'server' , $server );
}
public function previewEvent ( $serverId , $eventId , $all = false )
{
2020-10-01 12:11:45 +02:00
$server = $this -> Server -> find ( 'first' , array (
'conditions' => array ( 'Server.id' => $serverId ),
'recursive' => - 1 ,
2021-01-18 10:04:53 +01:00
));
2018-07-19 11:48:22 +02:00
if ( empty ( $server )) {
throw new NotFoundException ( 'Invalid server ID.' );
}
2019-10-10 19:10:52 +02:00
try {
2021-01-18 10:04:53 +01:00
$event = $this -> Server -> previewEvent ( $server , $eventId );
2019-10-10 19:10:52 +02:00
} catch ( NotFoundException $e ) {
2020-10-01 12:11:45 +02:00
throw new NotFoundException ( __ ( " Event '%s' not found. " , $eventId ));
2019-10-10 19:10:52 +02:00
} catch ( Exception $e ) {
2020-10-01 12:11:45 +02:00
$this -> Flash -> error ( __ ( 'Download failed. %s' , $e -> getMessage ()));
2019-10-10 19:10:52 +02:00
$this -> redirect ( array ( 'action' => 'previewIndex' , $serverId ));
2018-07-19 11:48:22 +02:00
}
2019-10-10 19:10:52 +02:00
2021-01-18 10:13:11 +01:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $event , $this -> response -> type ());
}
2020-10-01 12:11:45 +02:00
$this -> loadModel ( 'Warninglist' );
if ( isset ( $event [ 'Event' ][ 'Attribute' ])) {
$this -> Warninglist -> attachWarninglistToAttributes ( $event [ 'Event' ][ 'Attribute' ]);
}
if ( isset ( $event [ 'Event' ][ 'ShadowAttribute' ])) {
$this -> Warninglist -> attachWarninglistToAttributes ( $event [ 'Event' ][ 'ShadowAttribute' ]);
}
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'Event' );
$params = $this -> Event -> rearrangeEventForView ( $event , $this -> passedArgs , $all );
2021-02-23 19:28:08 +01:00
$this -> __removeGalaxyClusterTags ( $event );
2018-07-19 11:48:22 +02:00
$this -> params -> params [ 'paging' ] = array ( 'Server' => $params );
$this -> set ( 'event' , $event );
$this -> set ( 'server' , $server );
$dataForView = array (
'Attribute' => array ( 'attrDescriptions' => 'fieldDescriptions' , 'distributionDescriptions' => 'distributionDescriptions' , 'distributionLevels' => 'distributionLevels' ),
'Event' => array ( 'eventDescriptions' => 'fieldDescriptions' , 'analysisLevels' => 'analysisLevels' ),
'Object' => array ()
);
foreach ( $dataForView as $m => $variables ) {
if ( $m === 'Event' ) {
$currentModel = $this -> Event ;
} elseif ( $m === 'Attribute' ) {
$currentModel = $this -> Event -> Attribute ;
} elseif ( $m === 'Object' ) {
$currentModel = $this -> Event -> Object ;
}
foreach ( $variables as $alias => $variable ) {
$this -> set ( $alias , $currentModel -> { $variable });
}
}
2021-03-30 09:38:41 +02:00
$this -> set ( 'threatLevels' , $this -> Event -> ThreatLevel -> listThreatLevels ());
2021-01-12 10:46:05 +01:00
$this -> set ( 'title_for_layout' , __ ( 'Remote event preview' ));
2018-07-19 11:48:22 +02:00
}
2021-02-23 19:28:08 +01:00
private function __removeGalaxyClusterTags ( array & $event )
{
$galaxyTagIds = [];
foreach ( $event [ 'Galaxy' ] as $galaxy ) {
foreach ( $galaxy [ 'GalaxyCluster' ] as $galaxyCluster ) {
$galaxyTagIds [ $galaxyCluster [ 'tag_id' ]] = true ;
}
}
if ( empty ( $galaxyTagIds )) {
return ;
}
foreach ( $event [ 'Tag' ] as $k => $eventTag ) {
if ( isset ( $galaxyTagIds [ $eventTag [ 'id' ]])) {
unset ( $event [ 'Tag' ][ $k ]);
}
}
}
2021-01-18 11:23:26 +01:00
public function compareServers ()
{
list ( $servers , $overlap ) = $this -> Server -> serverEventsOverlap ();
$this -> set ( 'servers' , $servers );
$this -> set ( 'overlap' , $overlap );
$this -> set ( 'title_for_layout' , __ ( 'Server overlap analysis matrix' ));
}
2018-07-19 11:48:22 +02:00
public function filterEventIndex ( $id )
{
if ( ! $this -> _isSiteAdmin ()) {
throw new MethodNotAllowedException ( 'You are not authorised to do that.' );
}
$validFilters = $this -> Server -> validEventIndexFilters ;
$validatedFilterString = '' ;
foreach ( $this -> passedArgs as $k => $v ) {
if ( in_array ( '' . $k , $validFilters )) {
if ( $validatedFilterString != '' ) {
$validatedFilterString .= '/' ;
}
$validatedFilterString .= $k . ':' . $v ;
}
}
$this -> set ( 'id' , $id );
$this -> set ( 'validFilters' , $validFilters );
$this -> set ( 'filter' , $validatedFilterString );
}
public function add ()
{
if ( $this -> request -> is ( 'post' )) {
if ( $this -> _isRest ()) {
if ( ! isset ( $this -> request -> data [ 'Server' ])) {
$this -> request -> data = array ( 'Server' => $this -> request -> data );
}
}
if ( ! empty ( $this -> request -> data [ 'Server' ][ 'json' ])) {
$json = json_decode ( $this -> request -> data [ 'Server' ][ 'json' ], true );
} elseif ( $this -> _isRest ()) {
if ( empty ( $this -> request -> data [ 'Server' ][ 'remote_org_id' ])) {
throw new MethodNotAllowedException ( 'No remote org ID set. Please pass it as remote_org_id' );
}
}
$fail = false ;
if ( empty ( Configure :: read ( 'MISP.host_org_id' ))) {
$this -> request -> data [ 'Server' ][ 'internal' ] = 0 ;
}
// test the filter fields
2022-10-19 14:36:18 +02:00
if ( ! empty ( $this -> request -> data [ 'Server' ][ 'pull_rules' ]) && ! JsonTool :: isValid ( $this -> request -> data [ 'Server' ][ 'pull_rules' ])) {
2018-07-19 11:48:22 +02:00
$fail = true ;
$error_msg = __ ( 'The pull filter rules must be in valid JSON format.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'add' , false , array ( 'pull_rules' => $error_msg ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $error_msg );
}
}
2022-10-19 14:36:18 +02:00
if ( ! $fail && ! empty ( $this -> request -> data [ 'Server' ][ 'push_rules' ]) && ! JsonTool :: isValid ( $this -> request -> data [ 'Server' ][ 'push_rules' ])) {
2018-07-19 11:48:22 +02:00
$fail = true ;
$error_msg = __ ( 'The push filter rules must be in valid JSON format.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'add' , false , array ( 'push_rules' => $error_msg ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $error_msg );
}
}
if ( ! $fail ) {
if ( $this -> _isRest ()) {
2021-06-24 15:39:37 +02:00
$defaultPushRules = json_encode ([ " tags " => [ " OR " => [], " NOT " => []], " orgs " => [ " OR " => [], " NOT " => []]]);
2021-12-09 12:21:34 +01:00
$defaultPullRules = json_encode ([ " tags " => [ " OR " => [], " NOT " => []], " orgs " => [ " OR " => [], " NOT " => []], " type_attributes " => [ " NOT " => []], " type_objects " => [ " NOT " => []], " url_params " => " " ]);
2018-07-19 11:48:22 +02:00
$defaults = array (
'push' => 0 ,
'pull' => 0 ,
2019-11-22 21:53:51 +01:00
'push_sightings' => 0 ,
2020-05-26 15:08:24 +02:00
'push_galaxy_clusters' => 0 ,
2020-06-10 09:36:34 +02:00
'pull_galaxy_clusters' => 0 ,
2019-01-18 09:06:23 +01:00
'caching_enabled' => 0 ,
2018-07-19 11:48:22 +02:00
'json' => '[]' ,
2021-06-24 15:39:37 +02:00
'push_rules' => $defaultPushRules ,
'pull_rules' => $defaultPullRules ,
2021-06-11 18:14:29 +02:00
'self_signed' => 0 ,
'remove_missing_tags' => 0
2018-07-19 11:48:22 +02:00
);
foreach ( $defaults as $default => $dvalue ) {
if ( ! isset ( $this -> request -> data [ 'Server' ][ $default ])) {
$this -> request -> data [ 'Server' ][ $default ] = $dvalue ;
}
}
}
// force check userid and orgname to be from yourself
$this -> request -> data [ 'Server' ][ 'org_id' ] = $this -> Auth -> user ( 'org_id' );
if ( $this -> _isRest ()) {
if ( empty ( $this -> request -> data [ 'Server' ][ 'remote_org_id' ])) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'add' , false , array ( 'Organisation' => 'Remote Organisation\'s id/uuid not given (remote_org_id)' ), $this -> response -> type ());
}
if ( Validation :: uuid ( $this -> request -> data [ 'Server' ][ 'remote_org_id' ])) {
$orgCondition = array ( 'uuid' => $this -> request -> data [ 'Server' ][ 'remote_org_id' ]);
} else {
$orgCondition = array ( 'id' => $this -> request -> data [ 'Server' ][ 'remote_org_id' ]);
}
$existingOrgs = $this -> Server -> Organisation -> find ( 'first' , array (
'conditions' => $orgCondition ,
'recursive' => - 1 ,
'fields' => array ( 'id' , 'uuid' )
));
if ( empty ( $existingOrgs )) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'add' , false , array ( 'Organisation' => 'Invalid Remote Organisation' ), $this -> response -> type ());
}
} else {
if ( $this -> request -> data [ 'Server' ][ 'organisation_type' ] < 2 ) {
$this -> request -> data [ 'Server' ][ 'remote_org_id' ] = $json [ 'id' ];
} else {
$existingOrgs = $this -> Server -> Organisation -> find ( 'first' , array (
'conditions' => array ( 'uuid' => $json [ 'uuid' ]),
'recursive' => - 1 ,
'fields' => array ( 'id' , 'uuid' )
));
if ( ! empty ( $existingOrgs )) {
$fail = true ;
$this -> Flash -> error ( __ ( 'That organisation could not be created as the uuid is in use already.' ));
}
if ( ! $fail ) {
$this -> Server -> Organisation -> create ();
$orgSave = $this -> Server -> Organisation -> save ( array (
'name' => $json [ 'name' ],
'uuid' => $json [ 'uuid' ],
'local' => 0 ,
'created_by' => $this -> Auth -> user ( 'id' )
));
if ( ! $orgSave ) {
$this -> Flash -> error ( __ ( 'Couldn\'t save the new organisation, are you sure that the uuid is in the correct format? Also, make sure the organisation\'s name doesn\'t clash with an existing one.' ));
$fail = true ;
$this -> request -> data [ 'Server' ][ 'external_name' ] = $json [ 'name' ];
$this -> request -> data [ 'Server' ][ 'external_uuid' ] = $json [ 'uuid' ];
} else {
$this -> request -> data [ 'Server' ][ 'remote_org_id' ] = $this -> Server -> Organisation -> id ;
2019-09-18 14:37:42 +02:00
$this -> request -> data [ 'Server' ][ 'organisation_type' ] = 1 ;
2018-07-19 11:48:22 +02:00
}
}
}
}
if ( ! $fail ) {
if ( Configure :: read ( 'MISP.host_org_id' ) == 0 || $this -> request -> data [ 'Server' ][ 'remote_org_id' ] != Configure :: read ( 'MISP.host_org_id' )) {
$this -> request -> data [ 'Server' ][ 'internal' ] = 0 ;
}
$this -> request -> data [ 'Server' ][ 'org_id' ] = $this -> Auth -> user ( 'org_id' );
2019-03-25 17:35:02 +01:00
if ( empty ( $this -> request -> data [ 'Server' ][ 'push_rules' ])) {
2021-06-24 15:39:37 +02:00
$this -> request -> data [ 'Server' ][ 'push_rules' ] = $defaultPushRules ;
2019-03-25 17:35:02 +01:00
}
if ( empty ( $this -> request -> data [ 'Server' ][ 'pull_rules' ])) {
2021-06-24 15:39:37 +02:00
$this -> request -> data [ 'Server' ][ 'pull_rules' ] = $defaultPullRules ;
2019-03-25 17:35:02 +01:00
}
2018-07-19 11:48:22 +02:00
if ( $this -> Server -> save ( $this -> request -> data )) {
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_cert' ])) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , false );
}
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_client_cert' ])) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , true );
}
if ( $this -> _isRest ()) {
$server = $this -> Server -> find ( 'first' , array (
'conditions' => array ( 'Server.id' => $this -> Server -> id ),
'recursive' => - 1
));
return $this -> RestResponse -> viewData ( $server , $this -> response -> type ());
} else {
$this -> Flash -> success ( __ ( 'The server has been saved' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
} else {
if ( $this -> _isRest ()) {
2019-03-13 12:24:53 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'add' , false , $this -> Server -> validationErrors , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
} else {
$this -> Flash -> error ( __ ( 'The server could not be saved. Please, try again.' ));
}
}
}
}
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Servers' , 'add' , false , $this -> response -> type ());
} else {
$organisationOptions = array ( 0 => 'Local organisation' , 1 => 'External organisation' , 2 => 'New external organisation' );
2021-08-25 10:29:45 +02:00
2018-07-19 11:48:22 +02:00
$temp = $this -> Server -> Organisation -> find ( 'all' , array (
2021-08-25 10:29:45 +02:00
'fields' => array ( 'id' , 'name' , 'local' ),
'order' => array ( 'lower(Organisation.name) ASC' )
2018-07-19 11:48:22 +02:00
));
2021-08-25 10:29:45 +02:00
$allOrgs = [];
2018-07-19 11:48:22 +02:00
$localOrganisations = array ();
$externalOrganisations = array ();
foreach ( $temp as $o ) {
2021-08-25 10:29:45 +02:00
if ( $o [ 'Organisation' ][ 'local' ]) {
$localOrganisations [ $o [ 'Organisation' ][ 'id' ]] = $o [ 'Organisation' ][ 'name' ];
} else {
$externalOrganisations [ $o [ 'Organisation' ][ 'id' ]] = $o [ 'Organisation' ][ 'name' ];
}
2018-07-19 11:48:22 +02:00
$allOrgs [] = array ( 'id' => $o [ 'Organisation' ][ 'id' ], 'name' => $o [ 'Organisation' ][ 'name' ]);
}
2021-08-25 10:29:45 +02:00
2022-04-04 11:52:47 +02:00
$allTypes = $this -> Server -> getAllTypes ();
2021-12-09 12:21:34 +01:00
2018-07-19 11:48:22 +02:00
$this -> set ( 'host_org_id' , Configure :: read ( 'MISP.host_org_id' ));
$this -> set ( 'organisationOptions' , $organisationOptions );
$this -> set ( 'localOrganisations' , $localOrganisations );
$this -> set ( 'externalOrganisations' , $externalOrganisations );
$this -> set ( 'allOrganisations' , $allOrgs );
2021-12-09 12:21:34 +01:00
$this -> set ( 'allAttributeTypes' , $allTypes [ 'attribute' ]);
$this -> set ( 'allObjectTypes' , $allTypes [ 'object' ]);
2018-07-19 11:48:22 +02:00
2020-06-22 16:14:16 +02:00
$this -> set ( 'allTags' , $this -> __getTags ());
2018-07-19 11:48:22 +02:00
$this -> set ( 'host_org_id' , Configure :: read ( 'MISP.host_org_id' ));
2022-04-04 13:53:09 +02:00
$this -> set ( 'pull_scope' , 'server' );
2020-01-23 09:42:16 +01:00
$this -> render ( 'edit' );
2018-07-19 11:48:22 +02:00
}
}
2019-04-02 11:29:10 +02:00
2018-07-19 11:48:22 +02:00
public function edit ( $id = null )
{
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
$s = $this -> Server -> read ( null , $id );
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
if ( $this -> _isRest ()) {
if ( ! isset ( $this -> request -> data [ 'Server' ])) {
$this -> request -> data = array ( 'Server' => $this -> request -> data );
}
}
2021-05-11 15:03:14 +02:00
if ( empty ( Configure :: read ( 'MISP.host_org_id' ))) {
$this -> request -> data [ 'Server' ][ 'internal' ] = 0 ;
}
2018-07-19 11:48:22 +02:00
if ( isset ( $this -> request -> data [ 'Server' ][ 'json' ])) {
$json = json_decode ( $this -> request -> data [ 'Server' ][ 'json' ], true );
} else {
$json = null ;
}
$fail = false ;
// test the filter fields
2022-10-19 14:36:18 +02:00
if ( ! empty ( $this -> request -> data [ 'Server' ][ 'pull_rules' ]) && ! JsonTool :: isValid ( $this -> request -> data [ 'Server' ][ 'pull_rules' ])) {
2018-07-19 11:48:22 +02:00
$fail = true ;
$error_msg = __ ( 'The pull filter rules must be in valid JSON format.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'edit' , false , array ( 'pull_rules' => $error_msg ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $error_msg );
}
}
2022-10-19 14:36:18 +02:00
if ( ! $fail && ! empty ( $this -> request -> data [ 'Server' ][ 'push_rules' ]) && ! JsonTool :: isValid ( $this -> request -> data [ 'Server' ][ 'push_rules' ])) {
2018-07-19 11:48:22 +02:00
$fail = true ;
$error_msg = __ ( 'The push filter rules must be in valid JSON format.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'edit' , false , array ( 'push_rules' => $error_msg ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $error_msg );
}
2023-08-22 15:04:37 +02:00
}
if ( ! $fail && ! empty ( $this -> request -> data [ 'Server' ][ 'push_rules' ])) {
$pushRules = $this -> _jsonDecode ( $this -> request -> data [ 'Server' ][ 'push_rules' ]);
if ( ! empty ( $pushRules [ 'tags' ])) {
$this -> loadModel ( 'Tag' );
foreach ( $pushRules [ 'tags' ] as $operator => $list ) {
foreach ( $list as $i => $tagName ) {
if ( ! is_numeric ( $tagName )) { // tag added from freetext
$tag_id = $this -> Tag -> captureTag ([ 'name' => $tagName ], $this -> Auth -> user ());
$list [ $i ] = $tag_id ;
}
}
2021-12-10 09:31:33 +01:00
}
}
}
2023-08-22 15:04:37 +02:00
2018-07-19 11:48:22 +02:00
if ( ! $fail ) {
// say what fields are to be updated
2021-06-11 18:14:29 +02:00
$fieldList = array ( 'id' , 'url' , 'push' , 'pull' , 'push_sightings' , 'push_galaxy_clusters' , 'pull_galaxy_clusters' , 'caching_enabled' , 'unpublish_event' , 'publish_without_email' , 'remote_org_id' , 'name' , 'self_signed' , 'remove_missing_tags' , 'cert_file' , 'client_cert_file' , 'push_rules' , 'pull_rules' , 'internal' , 'skip_proxy' );
2018-07-19 11:48:22 +02:00
$this -> request -> data [ 'Server' ][ 'id' ] = $id ;
if ( isset ( $this -> request -> data [ 'Server' ][ 'authkey' ]) && " " != $this -> request -> data [ 'Server' ][ 'authkey' ]) {
$fieldList [] = 'authkey' ;
}
if ( isset ( $this -> request -> data [ 'Server' ][ 'organisation_type' ]) && isset ( $json )) {
// adds 'remote_org_id' in the fields to update
$fieldList [] = 'remote_org_id' ;
if ( $this -> request -> data [ 'Server' ][ 'organisation_type' ] < 2 ) {
$this -> request -> data [ 'Server' ][ 'remote_org_id' ] = $json [ 'id' ];
} else {
$existingOrgs = $this -> Server -> Organisation -> find ( 'first' , array (
'conditions' => array ( 'uuid' => $json [ 'uuid' ]),
'recursive' => - 1 ,
'fields' => array ( 'id' , 'uuid' )
));
if ( ! empty ( $existingOrgs )) {
$fail = true ;
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'edit' , false , array ( 'Organisation' => 'Remote Organisation\'s uuid already used' ), $this -> response -> type ());
} else {
$this -> Flash -> error ( __ ( 'That organisation could not be created as the uuid is in use already.' ));
}
}
if ( ! $fail ) {
$this -> Server -> Organisation -> create ();
$orgSave = $this -> Server -> Organisation -> save ( array (
'name' => $json [ 'name' ],
'uuid' => $json [ 'uuid' ],
'local' => 0 ,
'created_by' => $this -> Auth -> user ( 'id' )
));
if ( ! $orgSave ) {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'edit' , false , $this -> Server -> Organisation -> validationError , $this -> response -> type ());
} else {
$this -> Flash -> error ( __ ( 'Couldn\'t save the new organisation, are you sure that the uuid is in the correct format?.' ));
}
$fail = true ;
$this -> request -> data [ 'Server' ][ 'external_name' ] = $json [ 'name' ];
$this -> request -> data [ 'Server' ][ 'external_uuid' ] = $json [ 'uuid' ];
} else {
$this -> request -> data [ 'Server' ][ 'remote_org_id' ] = $this -> Server -> Organisation -> id ;
}
}
}
if ( empty ( Configure :: read ( 'MISP.host_org_id' )) || $this -> request -> data [ 'Server' ][ 'remote_org_id' ] != Configure :: read ( 'MISP.host_org_id' )) {
$this -> request -> data [ 'Server' ][ 'internal' ] = 0 ;
}
}
}
if ( ! $fail ) {
// Save the data
if ( $this -> Server -> save ( $this -> request -> data , true , $fieldList )) {
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_cert' ]) && ( ! isset ( $this -> request -> data [ 'Server' ][ 'delete_cert' ]) || ! $this -> request -> data [ 'Server' ][ 'delete_cert' ])) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , false );
} else {
if ( isset ( $this -> request -> data [ 'Server' ][ 'delete_cert' ]) && $this -> request -> data [ 'Server' ][ 'delete_cert' ]) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , false , true );
}
}
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_client_cert' ]) && ( ! isset ( $this -> request -> data [ 'Server' ][ 'delete_client_cert' ]) || ! $this -> request -> data [ 'Server' ][ 'delete_client_cert' ])) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , true );
} else {
if ( isset ( $this -> request -> data [ 'Server' ][ 'delete_client_cert' ]) && $this -> request -> data [ 'Server' ][ 'delete_client_cert' ]) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id , true , true );
}
}
if ( $this -> _isRest ()) {
$server = $this -> Server -> find ( 'first' , array (
'conditions' => array ( 'Server.id' => $this -> Server -> id ),
'recursive' => - 1
));
return $this -> RestResponse -> viewData ( $server , $this -> response -> type ());
} else {
$this -> Flash -> success ( __ ( 'The server has been saved' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
} else {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'edit' , false , $this -> Server -> validationError , $this -> response -> type ());
} else {
$this -> Flash -> error ( __ ( 'The server could not be saved. Please, try again.' ));
}
}
}
} else {
$this -> Server -> read ( null , $id );
$this -> Server -> set ( 'authkey' , '' );
$this -> request -> data = $this -> Server -> data ;
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Servers' , 'edit' , false , $this -> response -> type ());
} else {
$organisationOptions = array ( 0 => 'Local organisation' , 1 => 'External organisation' , 2 => 'New external organisation' );
2021-08-25 10:29:45 +02:00
2018-07-19 11:48:22 +02:00
$temp = $this -> Server -> Organisation -> find ( 'all' , array (
2021-08-25 10:29:45 +02:00
'fields' => array ( 'id' , 'name' , 'local' ),
'order' => array ( 'lower(Organisation.name) ASC' )
2018-07-19 11:48:22 +02:00
));
2021-08-25 10:29:45 +02:00
$allOrgs = [];
2018-07-19 11:48:22 +02:00
$localOrganisations = array ();
$externalOrganisations = array ();
foreach ( $temp as $o ) {
2021-08-25 10:29:45 +02:00
if ( $o [ 'Organisation' ][ 'local' ]) {
$localOrganisations [ $o [ 'Organisation' ][ 'id' ]] = $o [ 'Organisation' ][ 'name' ];
} else {
$externalOrganisations [ $o [ 'Organisation' ][ 'id' ]] = $o [ 'Organisation' ][ 'name' ];
}
2018-07-19 11:48:22 +02:00
$allOrgs [] = array ( 'id' => $o [ 'Organisation' ][ 'id' ], 'name' => $o [ 'Organisation' ][ 'name' ]);
}
2022-04-04 11:52:47 +02:00
$allTypes = $this -> Server -> getAllTypes ();
2021-12-09 12:21:34 +01:00
2018-07-19 11:48:22 +02:00
$oldRemoteSetting = 0 ;
if ( ! $this -> Server -> data [ 'RemoteOrg' ][ 'local' ]) {
$oldRemoteSetting = 1 ;
}
$this -> set ( 'host_org_id' , Configure :: read ( 'MISP.host_org_id' ));
$this -> set ( 'oldRemoteSetting' , $oldRemoteSetting );
$this -> set ( 'oldRemoteOrg' , $this -> Server -> data [ 'RemoteOrg' ][ 'id' ]);
$this -> set ( 'organisationOptions' , $organisationOptions );
$this -> set ( 'localOrganisations' , $localOrganisations );
$this -> set ( 'externalOrganisations' , $externalOrganisations );
$this -> set ( 'allOrganisations' , $allOrgs );
2020-06-22 16:14:16 +02:00
$this -> set ( 'allTags' , $this -> __getTags ());
2021-12-09 12:21:34 +01:00
$this -> set ( 'allAttributeTypes' , $allTypes [ 'attribute' ]);
$this -> set ( 'allObjectTypes' , $allTypes [ 'object' ]);
2018-07-19 11:48:22 +02:00
$this -> set ( 'server' , $s );
2019-02-23 12:54:54 +01:00
$this -> set ( 'id' , $id );
2018-07-19 11:48:22 +02:00
$this -> set ( 'host_org_id' , Configure :: read ( 'MISP.host_org_id' ));
2022-04-04 13:53:09 +02:00
$this -> set ( 'pull_scope' , 'server' );
2018-07-19 11:48:22 +02:00
}
}
public function delete ( $id = null )
{
if ( ! $this -> request -> is ( 'post' )) {
2019-07-29 10:23:00 +02:00
throw new MethodNotAllowedException ( __ ( 'This endpoint expects POST requests.' ));
2018-07-19 11:48:22 +02:00
}
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
$s = $this -> Server -> read ( null , $id );
if ( $this -> Server -> delete ()) {
2019-07-29 10:23:00 +02:00
$message = __ ( 'Server deleted' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'delete' , $message , $this -> response -> type ());
} else {
$this -> Flash -> success ( $message );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
}
}
$message = __ ( 'Server was not deleted' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'delete' , $id , $message , $this -> response -> type ());
} else {
$this -> Flash -> error ( $message );
2018-07-19 11:48:22 +02:00
$this -> redirect ( array ( 'action' => 'index' ));
}
}
2020-06-30 10:45:36 +02:00
public function eventBlockRule ()
{
$this -> AdminSetting = ClassRegistry :: init ( 'AdminSetting' );
$setting = $this -> AdminSetting -> find ( 'first' , [
'conditions' => [ 'setting' => 'eventBlockRule' ],
'recursive' => - 1
]);
if ( empty ( $setting )) {
$setting = [ 'setting' => 'eventBlockRule' ];
if ( $this -> request -> is ( 'post' )) {
$this -> AdminSetting -> create ();
}
}
if ( $this -> request -> is ( 'post' )) {
if ( ! empty ( $this -> request -> data [ 'Server' ])) {
$this -> request -> data = $this -> request -> data [ 'Server' ];
}
$setting [ 'AdminSetting' ][ 'setting' ] = 'eventBlockRule' ;
$setting [ 'AdminSetting' ][ 'value' ] = $this -> request -> data [ 'value' ];
$result = $this -> AdminSetting -> save ( $setting );
if ( $result ) {
$message = __ ( 'Settings saved' );
} else {
$message = __ ( 'Could not save the settings. Invalid input.' );
}
if ( $this -> _isRest ()) {
if ( $result ) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'eventBlockRule' , false , $message , $this -> response -> type ());
} else {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'eventBlockRule' , $message , $this -> response -> type ());
}
} else {
if ( $result ) {
$this -> Flash -> success ( $message );
$this -> redirect ( '/' );
} else {
$this -> Flash -> error ( $message );
}
}
}
$this -> set ( 'setting' , $setting );
}
2018-07-19 11:48:22 +02:00
/**
* Pull one or more events with attributes from a remote instance .
* Set $technique to
2019-02-10 13:08:12 +01:00
* full - download everything
* incremental - only new events
* < int > - specific id of the event to pull
2018-07-19 11:48:22 +02:00
*/
2021-09-30 23:19:29 +02:00
public function pull ( $id = null , $technique = 'full' )
2018-07-19 11:48:22 +02:00
{
2021-09-30 23:19:29 +02:00
if ( empty ( $id )) {
if ( ! empty ( $this -> request -> data [ 'id' ])) {
$id = $this -> request -> data [ 'id' ];
} else {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2019-07-29 10:14:49 +02:00
}
2021-09-30 23:19:29 +02:00
$s = $this -> Server -> find ( 'first' , [
'conditions' => [ 'id' => $id ],
'recursive' => - 1 ,
]);
if ( empty ( $s )) {
2018-07-19 11:48:22 +02:00
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2018-11-23 14:11:33 +01:00
$error = false ;
2022-10-27 12:15:25 +02:00
2021-09-30 23:19:29 +02:00
if ( false == $s [ 'Server' ][ 'pull' ] && ( $technique === 'full' || $technique === 'incremental' )) {
2018-11-23 14:11:33 +01:00
$error = __ ( 'Pull setting not enabled for this server.' );
}
2021-09-30 23:19:29 +02:00
if ( false == $s [ 'Server' ][ 'pull_galaxy_clusters' ] && ( $technique === 'pull_relevant_clusters' )) {
2020-06-25 15:01:54 +02:00
$error = __ ( 'Pull setting not enabled for this server.' );
}
2018-11-23 14:11:33 +01:00
if ( empty ( $error )) {
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
2021-09-30 23:19:29 +02:00
$result = $this -> Server -> pull ( $this -> Auth -> user (), $technique , $s );
2018-11-23 14:11:33 +01:00
if ( is_array ( $result )) {
2021-08-09 12:14:16 +02:00
$success = __ ( 'Pull completed. %s events pulled, %s events could not be pulled, %s proposals pulled, %s sightings pulled, %s clusters pulled.' , count ( $result [ 0 ]), count ( $result [ 1 ]), $result [ 2 ], $result [ 3 ], $result [ 4 ]);
2018-11-23 14:11:33 +01:00
} else {
$error = $result ;
}
$this -> set ( 'successes' , $result [ 0 ]);
$this -> set ( 'fails' , $result [ 1 ]);
$this -> set ( 'pulledProposals' , $result [ 2 ]);
2019-11-22 21:53:51 +01:00
$this -> set ( 'pulledSightings' , $result [ 3 ]);
2018-11-23 14:11:33 +01:00
} else {
$this -> loadModel ( 'Job' );
2021-11-02 11:09:41 +01:00
$jobId = $this -> Job -> createJob (
$this -> Auth -> user (),
2021-09-30 23:19:29 +02:00
Job :: WORKER_DEFAULT ,
2021-11-02 11:09:41 +01:00
'pull' ,
'Server: ' . $id ,
__ ( 'Pulling.' )
2018-11-23 14:11:33 +01:00
);
2021-11-02 11:09:41 +01:00
$this -> Server -> getBackgroundJobsTool () -> enqueue (
BackgroundJobsTool :: DEFAULT_QUEUE ,
BackgroundJobsTool :: CMD_SERVER ,
[
'pull' ,
$this -> Auth -> user ( 'id' ),
$id ,
$technique ,
$jobId
2021-11-02 16:25:43 +01:00
],
false ,
$jobId
2021-11-02 11:09:41 +01:00
);
2021-08-09 12:14:16 +02:00
$success = __ ( 'Pull queued for background execution. Job ID: %s' , $jobId );
2018-11-23 14:11:33 +01:00
}
}
if ( $this -> _isRest ()) {
if ( ! empty ( $error )) {
2021-08-09 12:14:16 +02:00
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'pull' , $id , $error , $this -> response -> type ());
2018-11-23 14:11:33 +01:00
} else {
2021-08-09 12:14:16 +02:00
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'pull' , $id , $this -> response -> type (), $success );
2018-11-23 14:11:33 +01:00
}
} else {
if ( ! empty ( $error )) {
$this -> Flash -> error ( $error );
$this -> redirect ( array ( 'action' => 'index' ));
} else {
$this -> Flash -> success ( $success );
$this -> redirect ( $this -> referer ());
}
}
2018-07-19 11:48:22 +02:00
}
public function push ( $id = null , $technique = false )
{
2019-07-29 10:14:49 +02:00
if ( ! empty ( $id )) {
$this -> Server -> id = $id ;
} else if ( ! empty ( $this -> request -> data [ 'id' ])) {
$this -> Server -> id = $this -> request -> data [ 'id' ];
} else {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
if ( ! empty ( $this -> request -> data [ 'technique' ])) {
$technique = $this -> request -> data [ 'technique' ];
}
2018-07-19 11:48:22 +02:00
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
$s = $this -> Server -> read ( null , $id );
2022-10-27 12:15:25 +02:00
2018-07-19 11:48:22 +02:00
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
App :: uses ( 'SyncTool' , 'Tools' );
$syncTool = new SyncTool ();
2021-08-09 13:02:29 +02:00
$HttpSocket = $syncTool -> setupHttpSocket ( $s );
2018-07-19 11:48:22 +02:00
$result = $this -> Server -> push ( $id , $technique , false , $HttpSocket , $this -> Auth -> user ());
if ( $result === false ) {
2018-11-23 14:11:33 +01:00
$error = __ ( 'The remote server is too outdated to initiate a push towards it. Please notify the hosting organisation of the remote instance.' );
} elseif ( ! is_array ( $result )) {
$error = $result ;
}
if ( ! empty ( $error )) {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'push' , false , $error , $this -> response -> type ());
} else {
$this -> Flash -> info ( $error );
$this -> redirect ( array ( 'action' => 'index' ));
}
}
if ( $this -> _isRest ()) {
2021-08-09 13:02:29 +02:00
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'push' , $id , $this -> response -> type (), __ ( 'Push complete. %s events pushed, %s events could not be pushed.' , count ( $result [ 0 ]), count ( $result [ 1 ])));
2018-11-23 14:11:33 +01:00
} else {
$this -> set ( 'successes' , $result [ 0 ]);
$this -> set ( 'fails' , $result [ 1 ]);
}
2018-07-19 11:48:22 +02:00
} else {
$this -> loadModel ( 'Job' );
2021-11-02 11:09:41 +01:00
$jobId = $this -> Job -> createJob (
$this -> Auth -> user (),
Job :: WORKER_DEFAULT ,
'push' ,
'Server: ' . $id ,
__ ( 'Pushing.' )
2018-07-19 11:48:22 +02:00
);
2021-11-02 11:09:41 +01:00
$this -> Server -> getBackgroundJobsTool () -> enqueue (
BackgroundJobsTool :: DEFAULT_QUEUE ,
BackgroundJobsTool :: CMD_SERVER ,
[
'push' ,
$this -> Auth -> user ( 'id' ),
$id ,
$technique ,
$jobId
2021-11-02 16:25:43 +01:00
],
false ,
$jobId
2018-07-19 11:48:22 +02:00
);
2021-11-02 11:09:41 +01:00
2018-11-23 14:11:33 +01:00
$message = sprintf ( __ ( 'Push queued for background execution. Job ID: %s' ), $jobId );
2022-03-02 20:50:57 +01:00
2018-11-23 14:11:33 +01:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'push' , $message , $this -> response -> type ());
}
2018-08-22 17:00:13 +02:00
$this -> Flash -> success ( $message );
2018-07-19 11:48:22 +02:00
$this -> redirect ( array ( 'action' => 'index' ));
}
}
private function __saveCert ( $server , $id , $client = false , $delete = false )
{
if ( $client ) {
$subm = 'submitted_client_cert' ;
$attr = 'client_cert_file' ;
$ins = '_client' ;
} else {
$subm = 'submitted_cert' ;
$attr = 'cert_file' ;
$ins = '' ;
}
if ( ! $delete ) {
$ext = '' ;
App :: uses ( 'File' , 'Utility' );
App :: uses ( 'Folder' , 'Utility' );
App :: uses ( 'FileAccessTool' , 'Tools' );
2023-06-28 09:26:15 +02:00
App :: uses ( 'SyncTool' , 'Tools' );
2018-07-19 11:48:22 +02:00
if ( isset ( $server [ 'Server' ][ $subm ][ 'name' ])) {
if ( $this -> request -> data [ 'Server' ][ $subm ][ 'size' ] != 0 ) {
if ( ! $this -> Server -> checkFilename ( $server [ 'Server' ][ $subm ][ 'name' ])) {
2019-03-26 15:02:05 +01:00
throw new Exception ( __ ( 'Filename not allowed' ));
2018-07-19 11:48:22 +02:00
}
2023-06-28 09:26:15 +02:00
if ( ! is_uploaded_file ( $server [ 'Server' ][ $subm ][ 'tmp_name' ])) {
throw new Exception ( __ ( 'File not uploaded correctly' ));
}
$ext = pathinfo ( $server [ 'Server' ][ $subm ][ 'name' ], PATHINFO_EXTENSION );
if ( ! in_array ( $ext , SyncTool :: ALLOWED_CERT_FILE_EXTENSIONS )) {
$this -> Flash -> error ( __ ( 'Invalid extension.' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
2018-10-26 21:13:59 +02:00
if ( ! $server [ 'Server' ][ $subm ][ 'size' ] > 0 ) {
2019-03-26 15:02:05 +01:00
$this -> Flash -> error ( __ ( 'Incorrect extension or empty file.' ));
2018-07-19 11:48:22 +02:00
$this -> redirect ( array ( 'action' => 'index' ));
}
2023-06-28 09:26:15 +02:00
// read certificate file data
$certData = FileAccessTool :: readFromFile ( $server [ 'Server' ][ $subm ][ 'tmp_name' ], $server [ 'Server' ][ $subm ][ 'size' ]);
2018-07-19 11:48:22 +02:00
} else {
return true ;
}
} else {
2023-06-28 09:26:15 +02:00
$ext = 'pem' ;
$certData = base64_decode ( $server [ 'Server' ][ $subm ]);
}
// check if the file is a valid x509 certificate
try {
$cert = openssl_x509_parse ( $certData );
if ( ! $cert ) {
throw new Exception ( __ ( 'Invalid certificate.' ));
}
} catch ( Exception $e ) {
$this -> Flash -> error ( __ ( 'Invalid certificate.' ));
$this -> redirect ( array ( 'action' => 'index' ));
2018-07-19 11:48:22 +02:00
}
2023-06-28 09:26:15 +02:00
2018-07-19 11:48:22 +02:00
$destpath = APP . " files " . DS . " certs " . DS ;
$pemfile = new File ( $destpath . $id . $ins . '.' . $ext );
2023-06-28 09:26:15 +02:00
$result = $pemfile -> write ( $certData );
2018-07-19 11:48:22 +02:00
$s = $this -> Server -> read ( null , $id );
$s [ 'Server' ][ $attr ] = $s [ 'Server' ][ 'id' ] . $ins . '.' . $ext ;
if ( $result ) {
$this -> Server -> save ( $s );
}
} else {
$s = $this -> Server -> read ( null , $id );
$s [ 'Server' ][ $attr ] = '' ;
$this -> Server -> save ( $s );
}
return true ;
}
public function serverSettingsReloadSetting ( $setting , $id )
{
$pathToSetting = explode ( '.' , $setting );
2022-05-04 01:23:13 +02:00
if (
strpos ( $setting , 'Plugin.Enrichment' ) !== false ||
strpos ( $setting , 'Plugin.Import' ) !== false ||
strpos ( $setting , 'Plugin.Export' ) !== false ||
strpos ( $setting , 'Plugin.Cortex' ) !== false ||
2022-06-24 12:45:20 +02:00
strpos ( $setting , 'Plugin.Action' ) !== false ||
strpos ( $setting , 'Plugin.Workflow' ) !== false
2022-05-04 01:23:13 +02:00
) {
2018-07-19 11:48:22 +02:00
$settingObject = $this -> Server -> getCurrentServerSettings ();
} else {
$settingObject = $this -> Server -> serverSettings ;
}
foreach ( $pathToSetting as $key ) {
if ( ! isset ( $settingObject [ $key ])) {
throw new MethodNotAllowedException ();
}
$settingObject = $settingObject [ $key ];
}
$result = $this -> Server -> serverSettingReadSingle ( $settingObject , $setting , $key );
$this -> set ( 'setting' , $result );
$priorityErrorColours = array ( 0 => 'red' , 1 => 'yellow' , 2 => 'green' );
$this -> set ( 'priorityErrorColours' , $priorityErrorColours );
$priorities = array ( 0 => 'Critical' , 1 => 'Recommended' , 2 => 'Optional' , 3 => 'Deprecated' );
$this -> set ( 'priorities' , $priorities );
$this -> set ( 'k' , $id );
$this -> layout = false ;
$subGroup = 'general' ;
if ( $pathToSetting [ 0 ] === 'Plugin' ) {
$subGroup = explode ( '_' , $pathToSetting [ 1 ])[ 0 ];
}
$this -> set ( 'subGroup' , $subGroup );
$this -> render ( '/Elements/healthElements/settings_row' );
}
public function serverSettings ( $tab = false )
{
2021-02-10 22:17:09 +01:00
if ( ! $this -> request -> is ( 'get' )) {
throw new MethodNotAllowedException ( 'Just GET method is allowed.' );
}
$tabs = array (
'MISP' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 ),
'Encryption' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 ),
'Proxy' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 ),
'Security' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 ),
2021-11-09 14:19:07 +01:00
'Plugin' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 ),
'SimpleBackgroundJobs' => array ( 'count' => 0 , 'errors' => 0 , 'severity' => 5 )
2021-02-10 22:17:09 +01:00
);
2021-11-09 14:19:07 +01:00
2021-02-10 22:17:09 +01:00
$writeableErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'not found' ), 2 => __ ( 'is not writeable' ));
$readableErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'not readable' ));
$gpgErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'FAIL: settings not set' ), 2 => __ ( 'FAIL: Failed to load GnuPG' ), 3 => __ ( 'FAIL: Issues with the key/passphrase' ), 4 => __ ( 'FAIL: sign failed' ));
$proxyErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'not configured (so not tested)' ), 2 => __ ( 'Getting URL via proxy failed' ));
$zmqErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'not enabled (so not tested)' ), 2 => __ ( 'Python ZeroMQ library not installed correctly.' ), 3 => __ ( 'ZeroMQ script not running.' ));
2022-05-20 16:13:31 +02:00
$sessionErrors = array (
0 => __ ( 'OK' ),
2022-05-20 16:23:36 +02:00
1 => __ ( 'Too many expired sessions in the database, please clear the expired sessions' ),
2 => __ ( 'PHP session handler is using the default file storage. This is not recommended, please use the redis or database storage' ),
2022-05-20 16:13:31 +02:00
8 => __ ( 'Alternative setting used' ),
9 => __ ( 'Test failed' )
);
2021-02-10 22:17:09 +01:00
$moduleErrors = array ( 0 => __ ( 'OK' ), 1 => __ ( 'System not enabled' ), 2 => __ ( 'No modules found' ));
2021-11-09 14:19:07 +01:00
$backgroundJobsErrors = array (
2021-11-09 14:38:48 +01:00
0 => __ ( 'OK' ),
1 => __ ( 'Not configured (so not tested)' ),
2 => __ ( 'Error connecting to Redis.' ),
3 => __ ( 'Error connecting to Supervisor.' ),
4 => __ ( 'Error connecting to Redis and Supervisor.' )
2021-11-09 14:19:07 +01:00
);
2021-02-10 22:17:09 +01:00
$finalSettings = $this -> Server -> serverSettingsRead ();
$issues = array (
'errors' => array (
0 => array (
'value' => 0 ,
'description' => __ ( 'MISP will not operate correctly or will be unsecure until these issues are resolved.' )
2018-07-19 11:48:22 +02:00
),
2021-02-10 22:17:09 +01:00
1 => array (
'value' => 0 ,
'description' => __ ( 'Some of the features of MISP cannot be utilised until these issues are resolved.' )
),
2 => array (
'value' => 0 ,
'description' => __ ( 'There are some optional tweaks that could be done to improve the looks of your MISP instance.' )
),
),
'deprecated' => array (),
'overallHealth' => 3 ,
);
$dumpResults = array ();
$tempArray = array ();
2024-01-30 14:27:04 +01:00
foreach ( $finalSettings as $result ) {
2021-02-10 22:17:09 +01:00
if ( $result [ 'level' ] == 3 ) {
$issues [ 'deprecated' ] ++ ;
}
$tabs [ $result [ 'tab' ]][ 'count' ] ++ ;
if ( isset ( $result [ 'error' ]) && $result [ 'level' ] < 3 ) {
$issues [ 'errors' ][ $result [ 'level' ]][ 'value' ] ++ ;
if ( $result [ 'level' ] < $issues [ 'overallHealth' ]) {
$issues [ 'overallHealth' ] = $result [ 'level' ];
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
$tabs [ $result [ 'tab' ]][ 'errors' ] ++ ;
if ( $result [ 'level' ] < $tabs [ $result [ 'tab' ]][ 'severity' ]) {
$tabs [ $result [ 'tab' ]][ 'severity' ] = $result [ 'level' ];
2018-07-19 11:48:22 +02:00
}
}
2021-02-10 22:17:09 +01:00
if ( isset ( $result [ 'optionsSource' ]) && is_callable ( $result [ 'optionsSource' ])) {
$result [ 'options' ] = $result [ 'optionsSource' ]();
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
$dumpResults [] = $result ;
if ( $result [ 'tab' ] == $tab ) {
if ( isset ( $result [ 'subGroup' ])) {
$tempArray [ $result [ 'subGroup' ]][] = $result ;
} else {
$tempArray [ 'general' ][] = $result ;
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
}
}
$finalSettings = $tempArray ;
// Diagnostics portion
$diagnostic_errors = 0 ;
App :: uses ( 'File' , 'Utility' );
App :: uses ( 'Folder' , 'Utility' );
2024-01-30 14:27:04 +01:00
2022-08-03 15:44:27 +02:00
if ( $tab === 'correlations' ) {
$this -> loadModel ( 'Correlation' );
$correlation_metrics = $this -> Correlation -> collectMetrics ();
$this -> set ( 'correlation_metrics' , $correlation_metrics );
2024-01-30 14:27:04 +01:00
} else if ( $tab === 'files' ) {
2022-11-22 13:24:46 +01:00
if ( ! empty ( Configure :: read ( 'Security.disable_instance_file_uploads' ))) {
throw new MethodNotAllowedException ( __ ( 'This functionality is disabled.' ));
}
2021-02-10 22:17:09 +01:00
$files = $this -> Server -> grabFiles ();
$this -> set ( 'files' , $files );
}
2024-01-30 14:27:04 +01:00
2021-02-10 22:17:09 +01:00
// Only run this check on the diagnostics tab
if ( $tab === 'diagnostics' || $tab === 'download' || $this -> _isRest ()) {
$php_ini = php_ini_loaded_file ();
$this -> set ( 'php_ini' , $php_ini );
$attachmentTool = new AttachmentTool ();
try {
2021-11-14 21:27:53 +01:00
$advanced_attachments = $attachmentTool -> checkAdvancedExtractionStatus ();
2021-02-10 22:17:09 +01:00
} catch ( Exception $e ) {
$this -> log ( $e -> getMessage (), LOG_NOTICE );
$advanced_attachments = false ;
}
2019-10-05 15:40:34 +02:00
2021-02-10 22:17:09 +01:00
$this -> set ( 'advanced_attachments' , $advanced_attachments );
2021-11-14 09:41:58 +01:00
$gitStatus = $this -> Server -> getCurrentGitStatus ( true );
2021-02-10 22:17:09 +01:00
$this -> set ( 'branch' , $gitStatus [ 'branch' ]);
$this -> set ( 'commit' , $gitStatus [ 'commit' ]);
$this -> set ( 'latestCommit' , $gitStatus [ 'latestCommit' ]);
2021-11-14 09:41:58 +01:00
$this -> set ( 'version' , $gitStatus [ 'version' ]);
2021-02-10 22:17:09 +01:00
$phpSettings = array (
'max_execution_time' => array (
'explanation' => 'The maximum duration that a script can run (does not affect the background workers). A too low number will break long running scripts like comprehensive API exports' ,
'recommended' => 300 ,
'unit' => 'seconds' ,
),
'memory_limit' => array (
'explanation' => 'The maximum memory that PHP can consume. It is recommended to raise this number since certain exports can generate a fair bit of memory usage' ,
'recommended' => 2048 ,
'unit' => 'MB'
),
'upload_max_filesize' => array (
'explanation' => 'The maximum size that an uploaded file can be. It is recommended to raise this number to allow for the upload of larger samples' ,
'recommended' => 50 ,
'unit' => 'MB'
),
'post_max_size' => array (
'explanation' => 'The maximum size of a POSTed message, this has to be at least the same size as the upload_max_filesize setting' ,
'recommended' => 50 ,
'unit' => 'MB'
)
);
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
foreach ( $phpSettings as $setting => $settingArray ) {
$phpSettings [ $setting ][ 'value' ] = $this -> Server -> getIniSetting ( $setting );
if ( $phpSettings [ $setting ][ 'value' ] && $settingArray [ 'unit' ] && $settingArray [ 'unit' ] === 'MB' ) {
// convert basic unit to M
$phpSettings [ $setting ][ 'value' ] = ( int ) floor ( $phpSettings [ $setting ][ 'value' ] / 1024 / 1024 );
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
}
$this -> set ( 'phpSettings' , $phpSettings );
2018-07-19 11:48:22 +02:00
2021-11-14 09:53:02 +01:00
if ( $gitStatus [ 'version' ] && $gitStatus [ 'version' ][ 'upToDate' ] === 'older' ) {
2021-02-10 22:17:09 +01:00
$diagnostic_errors ++ ;
}
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
// check if the STIX and Cybox libraries are working and the correct version using the test script stixtest.py
2021-07-07 12:12:59 +02:00
$stix = $this -> Server -> stixDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
$yaraStatus = $this -> Server -> yaraDiagnostics ( $diagnostic_errors );
2019-04-30 15:36:13 +02:00
2021-02-10 22:17:09 +01:00
// if GnuPG is set up in the settings, try to encrypt a test message
$gpgStatus = $this -> Server -> gpgDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
// if the message queue pub/sub is enabled, check whether the extension works
$zmqStatus = $this -> Server -> zmqDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
// if Proxy is set up in the settings, try to connect to a test URL
$proxyStatus = $this -> Server -> proxyDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-11-09 14:19:07 +01:00
// if SimpleBackgroundJobs is set up in the settings, try to connect to Redis
$backgroundJobsStatus = $this -> Server -> backgroundJobsDiagnostics ( $diagnostic_errors );
2021-02-10 22:17:09 +01:00
// get the DB diagnostics
$dbDiagnostics = $this -> Server -> dbSpaceUsage ();
$dbSchemaDiagnostics = $this -> Server -> dbSchemaDiagnostic ();
2022-07-19 13:36:53 +02:00
$dbConfiguration = $this -> Server -> dbConfiguration ();
2019-08-21 17:01:52 +02:00
2021-02-10 22:17:09 +01:00
$redisInfo = $this -> Server -> redisInfo ();
2019-09-20 22:15:15 +02:00
2021-02-10 22:17:09 +01:00
$moduleTypes = array ( 'Enrichment' , 'Import' , 'Export' , 'Cortex' );
foreach ( $moduleTypes as $type ) {
$moduleStatus [ $type ] = $this -> Server -> moduleDiagnostics ( $diagnostic_errors , $type );
}
2018-07-19 11:48:22 +02:00
2022-05-20 16:25:38 +02:00
// get php session diagnostics
$sessionStatus = $this -> Server -> sessionDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
$this -> loadModel ( 'AttachmentScan' );
try {
$attachmentScan = [ 'status' => true , 'software' => $this -> AttachmentScan -> diagnostic ()];
} catch ( Exception $e ) {
$attachmentScan = [ 'status' => false , 'error' => $e -> getMessage ()];
}
2020-10-22 23:59:49 +02:00
2021-02-10 22:17:09 +01:00
$securityAudit = ( new SecurityAudit ()) -> run ( $this -> Server );
2020-12-11 08:54:40 +01:00
2022-07-19 13:36:53 +02:00
$view = compact ( 'gpgStatus' , 'sessionErrors' , 'proxyStatus' , 'sessionStatus' , 'zmqStatus' , 'moduleStatus' , 'yaraStatus' , 'gpgErrors' , 'proxyErrors' , 'zmqErrors' , 'stix' , 'moduleErrors' , 'moduleTypes' , 'dbDiagnostics' , 'dbSchemaDiagnostics' , 'dbConfiguration' , 'redisInfo' , 'attachmentScan' , 'securityAudit' );
2021-02-10 22:17:09 +01:00
} else {
$view = [];
}
2020-12-11 08:54:40 +01:00
2021-02-10 22:17:09 +01:00
// check whether the files are writeable
$writeableDirs = $this -> Server -> writeableDirsDiagnostics ( $diagnostic_errors );
$writeableFiles = $this -> Server -> writeableFilesDiagnostics ( $diagnostic_errors );
$readableFiles = $this -> Server -> readableFilesDiagnostics ( $diagnostic_errors );
$extensions = $this -> Server -> extensionDiagnostics ();
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
// check if the encoding is not set to utf8
$dbEncodingStatus = $this -> Server -> databaseEncodingDiagnostics ( $diagnostic_errors );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
$view = array_merge ( $view , compact ( 'diagnostic_errors' , 'tabs' , 'tab' , 'issues' , 'finalSettings' , 'writeableErrors' , 'readableErrors' , 'writeableDirs' , 'writeableFiles' , 'readableFiles' , 'extensions' , 'dbEncodingStatus' ));
$this -> set ( $view );
2018-07-19 11:48:22 +02:00
2021-02-10 22:17:09 +01:00
$workerIssueCount = 4 ;
$worker_array = array ();
if ( Configure :: read ( 'MISP.background_jobs' )) {
$workerIssueCount = 0 ;
$worker_array = $this -> Server -> workerDiagnostics ( $workerIssueCount );
}
$this -> set ( 'worker_array' , $worker_array );
if ( $tab === 'download' || $this -> _isRest ()) {
foreach ( $dumpResults as $key => $dr ) {
unset ( $dumpResults [ $key ][ 'description' ]);
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
$dump = array (
2021-11-14 09:53:02 +01:00
'version' => $gitStatus [ 'version' ],
2021-02-10 22:17:09 +01:00
'phpSettings' => $phpSettings ,
'gpgStatus' => $gpgErrors [ $gpgStatus [ 'status' ]],
'proxyStatus' => $proxyErrors [ $proxyStatus ],
'zmqStatus' => $zmqStatus ,
'stix' => $stix ,
'moduleStatus' => $moduleStatus ,
'writeableDirs' => $writeableDirs ,
'writeableFiles' => $writeableFiles ,
'readableFiles' => $readableFiles ,
'dbDiagnostics' => $dbDiagnostics ,
'dbSchemaDiagnostics' => $dbSchemaDiagnostics ,
2022-07-19 13:36:53 +02:00
'dbConfiguration' => $dbConfiguration ,
2021-02-10 22:17:09 +01:00
'redisInfo' => $redisInfo ,
'finalSettings' => $dumpResults ,
'extensions' => $extensions ,
2021-11-09 14:19:07 +01:00
'workers' => $worker_array ,
'backgroundJobsStatus' => $backgroundJobsErrors [ $backgroundJobsStatus ]
2021-02-10 22:17:09 +01:00
);
foreach ( $dump [ 'finalSettings' ] as $k => $v ) {
if ( ! empty ( $v [ 'redacted' ])) {
$dump [ 'finalSettings' ][ $k ][ 'value' ] = '*****' ;
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
}
$this -> response -> body ( json_encode ( $dump , JSON_PRETTY_PRINT ));
$this -> response -> type ( 'json' );
$this -> response -> download ( 'MISP.report.json' );
return $this -> response ;
2018-07-19 11:48:22 +02:00
}
2021-02-10 22:17:09 +01:00
$priorities = array ( 0 => 'Critical' , 1 => 'Recommended' , 2 => 'Optional' , 3 => 'Deprecated' );
$this -> set ( 'priorities' , $priorities );
$this -> set ( 'workerIssueCount' , $workerIssueCount );
$priorityErrorColours = array ( 0 => 'red' , 1 => 'yellow' , 2 => 'green' );
$this -> set ( 'priorityErrorColours' , $priorityErrorColours );
2024-01-04 17:33:26 +01:00
$this -> set ( 'phpversion' , PHP_VERSION );
2021-02-10 22:17:09 +01:00
$this -> set ( 'phpmin' , $this -> phpmin );
$this -> set ( 'phprec' , $this -> phprec );
$this -> set ( 'phptoonew' , $this -> phptoonew );
2021-07-07 12:12:59 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Diagnostics' ));
2018-07-19 11:48:22 +02:00
}
public function startWorker ( $type )
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ();
}
2021-11-02 11:09:41 +01:00
2021-11-10 16:44:02 +01:00
if ( Configure :: read ( 'SimpleBackgroundJobs.enabled' )) {
2021-11-04 11:42:17 +01:00
$message = __ ( 'Worker start signal sent' );
2021-11-10 16:36:38 +01:00
$this -> Server -> getBackgroundJobsTool () -> startWorkerByQueue ( $type );
2021-11-04 11:42:17 +01:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'startWorker' , $type , $this -> response -> type (), $message );
} else {
$this -> Flash -> info ( $message );
$this -> redirect ( '/servers/serverSettings/workers' );
}
2021-11-02 11:09:41 +01:00
}
2021-11-04 11:42:17 +01:00
// CakeResque
2019-10-01 13:36:37 +02:00
$validTypes = array ( 'default' , 'email' , 'scheduler' , 'cache' , 'prio' , 'update' );
2018-07-19 11:48:22 +02:00
if ( ! in_array ( $type , $validTypes )) {
throw new MethodNotAllowedException ( 'Invalid worker type.' );
}
2021-11-02 11:09:41 +01:00
2018-07-19 11:48:22 +02:00
$prepend = '' ;
if ( $type != 'scheduler' ) {
2019-10-01 13:36:37 +02:00
$workerIssueCount = 0 ;
$workerDiagnostic = $this -> Server -> workerDiagnostics ( $workerIssueCount );
2019-10-01 13:38:27 +02:00
if ( $type == 'update' && isset ( $workerDiagnostic [ 'update' ][ 'ok' ]) && $workerDiagnostic [ 'update' ][ 'ok' ]) {
2019-10-01 13:36:37 +02:00
$message = __ ( 'Only one `update` worker can run at a time' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'startWorker' , false , $message , $this -> response -> type ());
} else {
$this -> Flash -> error ( $message );
$this -> redirect ( '/servers/serverSettings/workers' );
}
}
2018-07-19 11:48:22 +02:00
shell_exec ( $prepend . APP . 'Console' . DS . 'cake CakeResque.CakeResque start --interval 5 --queue ' . $type . ' > /dev/null 2>&1 &' );
} else {
shell_exec ( $prepend . APP . 'Console' . DS . 'cake CakeResque.CakeResque startscheduler -i 5 > /dev/null 2>&1 &' );
}
2019-06-19 14:08:06 +02:00
$message = __ ( 'Worker start signal sent' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'startWorker' , $type , $this -> response -> type (), $message );
} else {
$this -> Flash -> info ( $message );
$this -> redirect ( '/servers/serverSettings/workers' );
}
2018-07-19 11:48:22 +02:00
}
public function stopWorker ( $pid )
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ();
}
2021-11-04 11:42:17 +01:00
2019-06-19 14:08:06 +02:00
$message = __ ( 'Worker stop signal sent' );
2021-11-04 11:42:17 +01:00
2021-11-10 16:44:02 +01:00
if ( Configure :: read ( 'SimpleBackgroundJobs.enabled' )) {
2021-11-04 11:42:17 +01:00
$this -> Server -> getBackgroundJobsTool () -> stopWorker ( $pid );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'stopWorker' , $pid , $this -> response -> type (), $message );
} else {
$this -> Flash -> info ( $message );
$this -> redirect ( '/servers/serverSettings/workers' );
}
}
// CakeResque
$this -> Server -> killWorker ( $pid , $this -> Auth -> user ());
2019-06-19 14:08:06 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'stopWorker' , $pid , $this -> response -> type (), $message );
} else {
$this -> Flash -> info ( $message );
$this -> redirect ( '/servers/serverSettings/workers' );
}
}
public function getWorkers ()
{
2020-10-01 09:28:02 +02:00
if ( Configure :: read ( 'MISP.background_jobs' )) {
$workerIssueCount = 0 ;
$worker_array = $this -> Server -> workerDiagnostics ( $workerIssueCount );
} else {
$worker_array = [ __ ( 'Background jobs not enabled' )];
}
2019-06-19 14:08:06 +02:00
return $this -> RestResponse -> viewData ( $worker_array );
2018-07-19 11:48:22 +02:00
}
2021-01-07 20:39:49 +01:00
public function idTranslator ( $localId = null )
2021-01-07 20:31:21 +01:00
{
// We retrieve the list of remote servers that we can query
$servers = $this -> Server -> find ( 'all' , [
'conditions' => [ 'OR' => [ 'pull' => true , 'push' => true ]],
'recursive' => - 1 ,
'order' => [ 'Server.priority ASC' ],
]);
2020-08-26 10:01:14 +02:00
// We generate the list of servers for the dropdown
$displayServers = array ();
2021-01-07 20:31:21 +01:00
foreach ( $servers as $s ) {
$displayServers [] = [
'name' => $s [ 'Server' ][ 'name' ],
'value' => $s [ 'Server' ][ 'id' ],
];
2020-08-26 10:01:14 +02:00
}
$this -> set ( 'servers' , $displayServers );
2021-01-07 20:39:49 +01:00
if ( $localId || $this -> request -> is ( 'post' )) {
if ( $localId && $this -> request -> is ( 'get' )) {
$this -> request -> data [ 'Event' ][ 'local' ] = 'local' ;
$this -> request -> data [ 'Event' ][ 'uuid' ] = $localId ;
}
2020-08-26 10:01:14 +02:00
$remote_events = array ();
2021-01-07 20:39:49 +01:00
if ( ! empty ( $this -> request -> data [ 'Event' ][ 'uuid' ]) && $this -> request -> data [ 'Event' ][ 'local' ] === " local " ) {
2020-08-26 10:01:14 +02:00
$local_event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $this -> request -> data [ 'Event' ][ 'uuid' ]);
2021-01-07 20:31:21 +01:00
} else if ( ! empty ( $this -> request -> data [ 'Event' ][ 'uuid' ]) && $this -> request -> data [ 'Event' ][ 'local' ] === " remote " && ! empty ( $this -> request -> data [ 'Server' ][ 'id' ])) {
2020-08-26 10:01:14 +02:00
//We check on the remote server for any event with this id and try to find a match locally
$conditions = array ( 'AND' => array ( 'Server.id' => $this -> request -> data [ 'Server' ][ 'id' ], 'Server.pull' => true ));
$remote_server = $this -> Server -> find ( 'first' , array ( 'conditions' => $conditions ));
2021-01-07 20:31:21 +01:00
if ( ! empty ( $remote_server )) {
2020-08-26 10:01:14 +02:00
try {
2021-08-11 17:58:12 +02:00
$remote_event = $this -> Event -> downloadEventMetadataFromServer ( $this -> request -> data [ 'Event' ][ 'uuid' ], $remote_server );
2020-08-26 10:01:14 +02:00
} catch ( Exception $e ) {
2021-01-12 10:46:05 +01:00
$this -> Flash -> error ( __ ( " Issue while contacting the remote server to retrieve event information " ));
2020-08-26 10:01:14 +02:00
return ;
}
2022-10-26 13:54:49 +02:00
if ( empty ( $remote_event )) {
$this -> Flash -> error ( __ ( " This event could not be found or you don't have permissions to see it. " ));
return ;
}
2021-08-11 17:58:12 +02:00
$local_event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $remote_event [ 'uuid' ]);
2021-01-12 10:46:05 +01:00
// we record it to avoid re-querying the same server in the 2nd phase
2021-01-07 20:31:21 +01:00
if ( ! empty ( $local_event )) {
2020-08-26 10:01:14 +02:00
$remote_events [] = array (
" server_id " => $remote_server [ 'Server' ][ 'id' ],
" server_name " => $remote_server [ 'Server' ][ 'name' ],
2021-08-11 17:58:12 +02:00
" url " => $remote_server [ 'Server' ][ 'url' ] . " /events/view/ " . $remote_event [ 'id' ],
" remote_id " => $remote_event [ 'id' ]
2020-08-26 10:01:14 +02:00
);
}
}
}
2021-01-07 20:39:49 +01:00
if ( empty ( $local_event )) {
2021-01-12 10:46:05 +01:00
$this -> Flash -> error ( __ ( " This event could not be found or you don't have permissions to see it. " ));
2020-08-26 10:01:14 +02:00
return ;
} else {
$this -> Flash -> success ( __ ( 'The event has been found.' ));
}
// In the second phase, we query all configured sync servers to get their info on the event
2021-01-07 20:31:21 +01:00
foreach ( $servers as $server ) {
2020-08-26 10:01:14 +02:00
// We check if the server was not already contacted in phase 1
2021-01-07 20:39:49 +01:00
if ( count ( $remote_events ) > 0 && $remote_events [ 0 ][ 'server_id' ] == $server [ 'Server' ][ 'id' ]) {
2020-08-26 10:01:14 +02:00
continue ;
}
2021-02-11 13:44:56 +01:00
$exception = null ;
2020-08-26 10:01:14 +02:00
try {
2021-08-11 17:58:12 +02:00
$remoteEvent = $this -> Event -> downloadEventMetadataFromServer ( $local_event [ 'Event' ][ 'uuid' ], $server );
2020-08-26 10:01:14 +02:00
} catch ( Exception $e ) {
2021-01-28 14:06:02 +01:00
$remoteEvent = null ;
2021-02-11 13:44:56 +01:00
$exception = $e -> getMessage ();
2021-01-28 14:06:02 +01:00
}
2021-08-11 17:58:12 +02:00
$remoteEventId = isset ( $remoteEvent [ 'id' ]) ? $remoteEvent [ 'id' ] : null ;
2020-08-26 10:01:14 +02:00
$remote_events [] = array (
2021-01-07 20:31:21 +01:00
" server_id " => $server [ 'Server' ][ 'id' ],
" server_name " => $server [ 'Server' ][ 'name' ],
2021-01-28 14:06:02 +01:00
" url " => isset ( $remoteEventId ) ? $server [ 'Server' ][ 'url' ] . " /events/view/ " . $remoteEventId : $server [ 'Server' ][ 'url' ],
2021-02-11 13:44:56 +01:00
" remote_id " => isset ( $remoteEventId ) ? $remoteEventId : false ,
" exception " => $exception ,
2020-08-26 10:01:14 +02:00
);
}
$this -> set ( 'local_event' , $local_event );
$this -> set ( 'remote_events' , $remote_events );
}
2021-01-12 10:46:05 +01:00
$this -> set ( 'title_for_layout' , __ ( 'Event ID translator' ));
2020-08-26 10:01:14 +02:00
}
2021-02-10 22:17:09 +01:00
public function getSubmodulesStatus ()
{
2019-03-18 16:17:10 +01:00
$this -> set ( 'submodules' , $this -> Server -> getSubmodulesGitStatus ());
$this -> render ( 'ajax/submoduleStatus' );
}
2022-02-26 09:58:28 +01:00
public function getSetting ( $settingName )
2019-08-15 20:01:36 +02:00
{
2022-02-26 09:58:28 +01:00
$setting = $this -> Server -> getSettingData ( $settingName );
if ( ! $setting ) {
throw new NotFoundException ( __ ( 'Setting %s is invalid.' , $settingName ));
}
2019-08-15 20:01:36 +02:00
if ( ! empty ( $setting [ " redacted " ])) {
2022-02-26 09:58:28 +01:00
throw new ForbiddenException ( __ ( 'This setting is redacted.' ));
2019-08-15 20:01:36 +02:00
}
2022-02-26 09:58:28 +01:00
if ( Configure :: check ( $settingName )) {
$setting [ 'value' ] = Configure :: read ( $settingName );
2019-08-15 20:01:36 +02:00
}
return $this -> RestResponse -> viewData ( $setting );
}
2022-02-26 09:58:28 +01:00
public function serverSettingsEdit ( $settingName , $id = false , $forceSave = false )
2018-07-19 11:48:22 +02:00
{
2019-03-13 12:24:53 +01:00
if ( ! $this -> _isRest ()) {
if ( ! isset ( $id )) {
throw new MethodNotAllowedException ();
}
$this -> set ( 'id' , $id );
}
2022-02-26 09:58:28 +01:00
$setting = $this -> Server -> getSettingData ( $settingName );
2020-11-19 19:08:14 +01:00
if ( $setting === false ) {
2022-02-26 09:58:28 +01:00
throw new NotFoundException ( __ ( 'Setting %s is invalid.' , $settingName ));
2020-11-19 19:08:14 +01:00
}
2019-06-18 09:57:27 +02:00
if ( ! empty ( $setting [ 'cli_only' ])) {
throw new MethodNotAllowedException ( __ ( 'This setting can only be edited via the CLI.' ));
}
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'get' )) {
2020-11-17 21:31:59 +01:00
$value = Configure :: read ( $setting [ 'name' ]);
if ( isset ( $value )) {
$setting [ 'value' ] = $value ;
2018-07-19 11:48:22 +02:00
}
2020-11-17 21:31:59 +01:00
$setting [ 'setting' ] = $setting [ 'name' ];
2021-01-13 14:10:13 +01:00
if ( isset ( $setting [ 'optionsSource' ]) && is_callable ( $setting [ 'optionsSource' ])) {
$setting [ 'options' ] = $setting [ 'optionsSource' ]();
2018-07-19 11:48:22 +02:00
}
2019-02-01 14:44:52 +01:00
$subGroup = explode ( '.' , $setting [ 'name' ]);
2018-07-19 11:48:22 +02:00
if ( $subGroup [ 0 ] === 'Plugin' ) {
$subGroup = explode ( '_' , $subGroup [ 1 ])[ 0 ];
} else {
$subGroup = 'general' ;
}
if ( $this -> _isRest ()) {
2022-02-26 09:58:28 +01:00
if ( ! empty ( $setting [ 'redacted' ])) {
throw new ForbiddenException ( __ ( 'This setting is redacted.' ));
}
return $this -> RestResponse -> viewData ([ $setting [ 'name' ] => $setting [ 'value' ]]);
2018-07-19 11:48:22 +02:00
} else {
$this -> set ( 'subGroup' , $subGroup );
2019-02-01 14:44:52 +01:00
$this -> set ( 'setting' , $setting );
2018-07-19 11:48:22 +02:00
$this -> render ( 'ajax/server_settings_edit' );
}
2020-11-17 21:31:59 +01:00
} else if ( $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
if ( ! isset ( $this -> request -> data [ 'Server' ])) {
$this -> request -> data = array ( 'Server' => $this -> request -> data );
}
2020-12-04 09:23:12 +01:00
if ( ! isset ( $this -> request -> data [ 'Server' ][ 'value' ]) || ! is_scalar ( $this -> request -> data [ 'Server' ][ 'value' ])) {
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'serverSettingsEdit' , false , 'Invalid input. Expected: {"value": "new_setting"}' , $this -> response -> type ());
}
}
2019-08-07 15:03:32 +02:00
if ( ! empty ( $this -> request -> data [ 'Server' ][ 'force' ])) {
$forceSave = $this -> request -> data [ 'Server' ][ 'force' ];
}
2018-07-19 11:48:22 +02:00
if ( trim ( $this -> request -> data [ 'Server' ][ 'value' ]) === '*****' ) {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'serverSettingsEdit' , false , 'No change.' , $this -> response -> type ());
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'No change.' )), 'status' => 200 , 'type' => 'json' ));
}
}
$this -> autoRender = false ;
2021-11-04 16:28:41 +01:00
if ( ! Configure :: read ( 'MISP.system_setting_db' ) && ! is_writeable ( APP . 'Config/config.php' )) {
$this -> loadModel ( 'Log' );
2018-07-19 11:48:22 +02:00
$this -> Log -> create ();
2023-12-07 15:17:58 +01:00
$this -> Log -> saveOrFailSilently ( array (
2021-11-04 16:28:41 +01:00
'org' => $this -> Auth -> user ( 'Organisation' )[ 'name' ],
'model' => 'Server' ,
'model_id' => 0 ,
'email' => $this -> Auth -> user ( 'email' ),
'action' => 'serverSettingsEdit' ,
'user_id' => $this -> Auth -> user ( 'id' ),
'title' => 'Server setting issue' ,
'change' => 'There was an issue witch changing ' . $setting [ 'name' ] . ' to ' . $this -> request -> data [ 'Server' ][ 'value' ] . '. The error message returned is: app/Config.config.php is not writeable to the apache user. No changes were made.' ,
2018-07-19 11:48:22 +02:00
));
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'serverSettingsEdit' , false , 'app/Config.config.php is not writeable to the apache user.' , $this -> response -> type ());
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'app/Config.config.php is not writeable to the apache user.' )), 'status' => 200 , 'type' => 'json' ));
}
}
2019-02-01 14:44:52 +01:00
$result = $this -> Server -> serverSettingsEditValue ( $this -> Auth -> user (), $setting , $this -> request -> data [ 'Server' ][ 'value' ], $forceSave );
if ( $result === true ) {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'serverSettingsEdit' , false , $this -> response -> type (), 'Field updated' );
2018-07-19 11:48:22 +02:00
} else {
2019-02-01 14:44:52 +01:00
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => 'Field updated.' )), 'status' => 200 , 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
}
2019-02-01 14:44:52 +01:00
} else {
2020-12-04 09:23:12 +01:00
if ( $this -> _isRest ()) {
2019-02-01 14:44:52 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'serverSettingsEdit' , false , $result , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
} else {
2019-02-01 14:44:52 +01:00
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => $result )), 'status' => 200 , 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
}
}
}
}
2020-09-22 09:15:03 +02:00
public function killAllWorkers ( $force = false )
{
2020-09-23 17:28:01 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2020-09-22 09:15:03 +02:00
throw new MethodNotAllowedException ();
}
$this -> Server -> killAllWorkers ( $this -> Auth -> user (), $force );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Server' , 'killAllWorkers' , false , $this -> response -> type (), __ ( 'Killing workers.' ));
}
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'workers' ));
}
2018-07-19 11:48:22 +02:00
public function restartWorkers ()
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ();
}
2021-11-04 11:42:17 +01:00
2021-11-10 16:44:02 +01:00
if ( Configure :: read ( 'SimpleBackgroundJobs.enabled' )) {
2021-11-04 11:42:17 +01:00
$this -> Server -> getBackgroundJobsTool () -> restartWorkers ();
} else {
// CakeResque
$this -> Server -> restartWorkers ( $this -> Auth -> user ());
}
2019-08-08 11:19:21 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Server' , 'restartWorkers' , false , $this -> response -> type (), __ ( 'Restarting workers.' ));
}
2018-07-19 11:48:22 +02:00
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'workers' ));
}
2020-03-06 14:56:35 +01:00
public function restartDeadWorkers ()
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2020-03-06 14:56:35 +01:00
throw new MethodNotAllowedException ();
}
2021-11-04 11:42:17 +01:00
2021-11-10 16:44:02 +01:00
if ( Configure :: read ( 'SimpleBackgroundJobs.enabled' )) {
2021-11-04 11:42:17 +01:00
$this -> Server -> getBackgroundJobsTool () -> restartDeadWorkers ();
} else {
// CakeResque
$this -> Server -> restartDeadWorkers ( $this -> Auth -> user ());
}
2020-03-06 14:56:35 +01:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Server' , 'restartDeadWorkers' , false , $this -> response -> type (), __ ( 'Restarting workers.' ));
}
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'workers' ));
}
2018-07-19 11:48:22 +02:00
public function deleteFile ( $type , $filename )
{
if ( $this -> request -> is ( 'post' )) {
$validItems = $this -> Server -> getFileRules ();
App :: uses ( 'File' , 'Utility' );
$existingFile = new File ( $validItems [ $type ][ 'path' ] . DS . $filename );
if ( ! $existingFile -> exists ()) {
$this -> Flash -> error ( __ ( 'File not found.' , true ), 'default' , array (), 'error' );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
}
if ( $existingFile -> delete ()) {
$this -> Flash -> success ( 'File deleted.' );
} else {
$this -> Flash -> error ( __ ( 'File could not be deleted.' , true ), 'default' , array (), 'error' );
}
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
} else {
throw new MethodNotAllowedException ( 'This action expects a POST request.' );
}
}
public function uploadFile ( $type )
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ();
}
2022-11-22 13:24:46 +01:00
if ( ! empty ( Configure :: read ( 'Security.disable_instance_file_uploads' ))) {
throw new MethodNotAllowedException ( __ ( 'Feature disabled.' ));
}
2018-07-19 11:48:22 +02:00
$validItems = $this -> Server -> getFileRules ();
// Check if there were problems with the file upload
// only keep the last part of the filename, this should prevent directory attacks
$filename = basename ( $this -> request -> data [ 'Server' ][ 'file' ][ 'name' ]);
if ( ! preg_match ( " / " . $validItems [ $type ][ 'regex' ] . " / " , $filename )) {
$this -> Flash -> error ( $validItems [ $type ][ 'regex_error' ], 'default' , array (), 'error' );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
}
if ( empty ( $this -> request -> data [ 'Server' ][ 'file' ][ 'tmp_name' ]) || ! is_uploaded_file ( $this -> request -> data [ 'Server' ][ 'file' ][ 'tmp_name' ])) {
$this -> Flash -> error ( __ ( 'Upload failed.' , true ), 'default' , array (), 'error' );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
}
// check if the file already exists
App :: uses ( 'File' , 'Utility' );
$existingFile = new File ( $validItems [ $type ][ 'path' ] . DS . $filename );
if ( $existingFile -> exists ()) {
$this -> Flash -> info ( __ ( 'File already exists. If you would like to replace it, remove the old one first.' , true ), 'default' , array (), 'error' );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
}
$result = move_uploaded_file ( $this -> request -> data [ 'Server' ][ 'file' ][ 'tmp_name' ], $validItems [ $type ][ 'path' ] . DS . $filename );
if ( $result ) {
$this -> Flash -> success ( 'File uploaded.' );
} else {
$this -> Flash -> error ( __ ( 'Upload failed.' , true ), 'default' , array (), 'error' );
}
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'files' ));
}
public function fetchServersForSG ( $idList = '{}' )
{
$id_exclusion_list = json_decode ( $idList , true );
$temp = $this -> Server -> find ( 'all' , array (
'conditions' => array (
'id !=' => $id_exclusion_list ,
),
'recursive' => - 1 ,
'fields' => array ( 'id' , 'name' , 'url' )
));
$servers = array ();
foreach ( $temp as $server ) {
$servers [] = array ( 'id' => $server [ 'Server' ][ 'id' ], 'name' => $server [ 'Server' ][ 'name' ], 'url' => $server [ 'Server' ][ 'url' ]);
}
$this -> layout = false ;
$this -> autoRender = false ;
$this -> set ( 'servers' , $servers );
$this -> render ( 'ajax/fetch_servers_for_sg' );
}
public function postTest ()
{
2021-01-06 23:38:51 +01:00
if ( ! $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ( 'Invalid request, expecting a POST request.' );
}
2021-01-06 23:38:51 +01:00
// Fix for PHP-FPM / Nginx / etc
// Fix via https://www.popmartian.com/tipsntricks/2015/07/14/howto-use-php-getallheaders-under-fastcgi-php-fpm-nginx-etc/
if ( ! function_exists ( 'getallheaders' )) {
$headers = [];
foreach ( $_SERVER as $name => $value ) {
2023-01-02 12:29:33 +01:00
$name = strtolower ( $name );
if ( substr ( $name , 0 , 5 ) === 'http_' ) {
$headers [ str_replace ( '_' , '-' , substr ( $name , 5 ))] = $value ;
2021-01-06 23:38:51 +01:00
}
}
} else {
$headers = getallheaders ();
$headers = array_change_key_case ( $headers , CASE_LOWER );
}
$result = [
'body' => $this -> request -> data ,
'headers' => [
'Content-type' => isset ( $headers [ 'content-type' ]) ? $headers [ 'content-type' ] : 0 ,
'Accept' => isset ( $headers [ 'accept' ]) ? $headers [ 'accept' ] : 0 ,
'Authorization' => isset ( $headers [ 'authorization' ]) ? 'OK' : 0 ,
],
];
2021-08-20 17:31:10 +02:00
return $this -> RestResponse -> viewData ( $result , 'json' );
2018-07-19 11:48:22 +02:00
}
2019-11-13 19:09:37 +01:00
public function getRemoteUser ( $id )
{
$user = $this -> Server -> getRemoteUser ( $id );
2021-08-03 09:38:36 +02:00
if ( $user === null ) {
throw new NotFoundException ( __ ( 'Invalid server' ));
2019-11-13 19:09:37 +01:00
}
2021-08-03 09:38:36 +02:00
return $this -> RestResponse -> viewData ( $user );
2019-11-13 19:09:37 +01:00
}
2018-07-19 11:48:22 +02:00
public function testConnection ( $id = false )
{
2020-11-12 08:21:24 +01:00
$server = $this -> Server -> find ( 'first' , [ 'conditions' => [ 'Server.id' => $id ]]);
2020-10-16 17:34:55 +02:00
if ( ! $server ) {
2018-07-19 11:48:22 +02:00
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2023-01-20 11:02:54 +01:00
@ session_write_close (); // close session to allow concurrent requests
2020-10-16 17:34:55 +02:00
$result = $this -> Server -> runConnectionTest ( $server );
2018-07-19 11:48:22 +02:00
if ( $result [ 'status' ] == 1 ) {
2020-10-16 17:34:55 +02:00
if ( isset ( $result [ 'info' ][ 'version' ]) && preg_match ( '/^[0-9]+\.+[0-9]+\.[0-9]+$/' , $result [ 'info' ][ 'version' ])) {
2021-08-20 17:31:10 +02:00
$perm_sync = isset ( $result [ 'info' ][ 'perm_sync' ]) ? $result [ 'info' ][ 'perm_sync' ] : false ;
$perm_sighting = isset ( $result [ 'info' ][ 'perm_sighting' ]) ? $result [ 'info' ][ 'perm_sighting' ] : false ;
$local_version = $this -> Server -> checkMISPVersion ();
2020-10-16 17:34:55 +02:00
$version = explode ( '.' , $result [ 'info' ][ 'version' ]);
2018-07-19 11:48:22 +02:00
$mismatch = false ;
$newer = false ;
$parts = array ( 'major' , 'minor' , 'hotfix' );
foreach ( $parts as $k => $v ) {
if ( ! $mismatch ) {
if ( $version [ $k ] > $local_version [ $v ]) {
$mismatch = $v ;
$newer = 'remote' ;
} elseif ( $version [ $k ] < $local_version [ $v ]) {
$mismatch = $v ;
$newer = 'local' ;
}
}
}
2019-07-12 16:03:08 +02:00
if ( ! $mismatch && $version [ 2 ] < 111 ) {
$mismatch = 'proposal' ;
}
2019-11-26 19:40:49 +01:00
if ( ! $perm_sync && ! $perm_sighting ) {
2018-08-03 19:20:00 +02:00
$result [ 'status' ] = 7 ;
return new CakeResponse ( array ( 'body' => json_encode ( $result ), 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
}
2019-11-26 19:40:49 +01:00
if ( ! $perm_sync && $perm_sighting ) {
$result [ 'status' ] = 8 ;
return new CakeResponse ( array ( 'body' => json_encode ( $result ), 'type' => 'json' ));
}
2021-01-19 09:35:45 +01:00
return $this -> RestResponse -> viewData ([
'status' => 1 ,
'local_version' => implode ( '.' , $local_version ),
'version' => implode ( '.' , $version ),
'mismatch' => $mismatch ,
'newer' => $newer ,
2021-08-21 11:20:33 +02:00
'post' => isset ( $result [ 'post' ]) ? $result [ 'post' ][ 'status' ] : 'too old' ,
'response_encoding' => isset ( $result [ 'post' ][ 'content-encoding' ]) ? $result [ 'post' ][ 'content-encoding' ] : null ,
2021-01-19 09:35:45 +01:00
'request_encoding' => isset ( $result [ 'info' ][ 'request_encoding' ]) ? $result [ 'info' ][ 'request_encoding' ] : null ,
'client_certificate' => $result [ 'client_certificate' ],
], 'json' );
2018-07-19 11:48:22 +02:00
} else {
$result [ 'status' ] = 3 ;
}
}
return new CakeResponse ( array ( 'body' => json_encode ( $result ), 'type' => 'json' ));
}
public function startZeroMQServer ()
{
$pubSubTool = $this -> Server -> getPubSubTool ();
$result = $pubSubTool -> restartServer ();
if ( $result === true ) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => 'ZeroMQ server successfully started.' )), 'status' => 200 , 'type' => 'json' ));
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => $result )), 'status' => 200 , 'type' => 'json' ));
}
}
public function stopZeroMQServer ()
{
$pubSubTool = $this -> Server -> getPubSubTool ();
$result = $pubSubTool -> killService ();
if ( $result === true ) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => 'ZeroMQ server successfully killed.' )), 'status' => 200 , 'type' => 'json' ));
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Could not kill the previous instance of the ZeroMQ script.' )), 'status' => 200 , 'type' => 'json' ));
}
}
public function statusZeroMQServer ()
{
$pubSubTool = $this -> Server -> getPubSubTool ();
$result = $pubSubTool -> statusCheck ();
if ( ! empty ( $result )) {
$this -> set ( 'events' , $result [ 'publishCount' ]);
2020-05-07 15:56:59 +02:00
$this -> set ( 'messages' , $result [ 'messageCount' ]);
2021-11-14 10:47:54 +01:00
$this -> set ( 'time' , $result [ 'timestamp' ]);
$this -> set ( 'time2' , $result [ 'timestampSettings' ]);
2018-07-19 11:48:22 +02:00
}
$this -> render ( 'ajax/zeromqstatus' );
}
public function purgeSessions ()
{
if ( $this -> Server -> updateDatabase ( 'cleanSessionTable' ) == false ) {
$this -> Flash -> error ( 'Could not purge the session table.' );
}
$this -> redirect ( '/servers/serverSettings/diagnostics' );
}
public function clearWorkerQueue ( $worker )
{
2021-08-25 10:29:45 +02:00
if ( ! $this -> request -> is ( 'Post' ) || $this -> request -> is ( 'ajax' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ();
}
2021-11-04 11:42:17 +01:00
2021-11-10 16:44:02 +01:00
if ( Configure :: read ( 'SimpleBackgroundJobs.enabled' )) {
2024-01-08 18:42:43 +01:00
$this -> Server -> getBackgroundJobsTool () -> clearQueue ( $worker );
2021-11-04 11:42:17 +01:00
} else {
// CakeResque
$worker_array = array ( 'cache' , 'default' , 'email' , 'prio' );
if ( ! in_array ( $worker , $worker_array )) {
throw new MethodNotAllowedException ( 'Invalid worker' );
}
$redis = Resque :: redis ();
$redis -> del ( 'queue:' . $worker );
2018-07-19 11:48:22 +02:00
}
2021-11-04 11:42:17 +01:00
2018-07-19 11:48:22 +02:00
$this -> Flash -> success ( 'Queue cleared.' );
$this -> redirect ( $this -> referer ());
}
public function getVersion ()
{
2022-10-26 13:54:49 +02:00
$user = $this -> _closeSession ();
2018-07-19 11:48:22 +02:00
$versionArray = $this -> Server -> checkMISPVersion ();
2021-01-19 09:35:45 +01:00
$response = [
2020-06-16 08:59:45 +02:00
'version' => $versionArray [ 'major' ] . '.' . $versionArray [ 'minor' ] . '.' . $versionArray [ 'hotfix' ],
2021-06-28 12:36:06 +02:00
'pymisp_recommended_version' => $this -> pyMispVersion ,
2022-10-26 13:54:49 +02:00
'perm_sync' => ( bool ) $user [ 'Role' ][ 'perm_sync' ],
'perm_sighting' => ( bool ) $user [ 'Role' ][ 'perm_sighting' ],
'perm_galaxy_editor' => ( bool ) $user [ 'Role' ][ 'perm_galaxy_editor' ],
2021-01-19 09:35:45 +01:00
'request_encoding' => $this -> CompressedRequestHandler -> supportedEncodings (),
2021-03-04 19:08:54 +01:00
'filter_sightings' => true , // check if Sightings::filterSightingUuidsForPush method is supported
2021-01-19 09:35:45 +01:00
];
2021-07-15 14:57:05 +02:00
return $this -> RestResponse -> viewData ( $response , 'json' );
2018-07-19 11:48:22 +02:00
}
2021-06-28 12:36:06 +02:00
/**
* @ deprecated Use field `pymisp_recommended_version` from getVersion instead
*/
2018-07-19 11:48:22 +02:00
public function getPyMISPVersion ()
{
$this -> set ( 'response' , array ( 'version' => $this -> pyMispVersion ));
$this -> set ( '_serialize' , 'response' );
}
public function checkout ()
{
$result = $this -> Server -> checkoutMain ();
}
2021-01-20 14:21:31 +01:00
public function update ( $branch = false )
2018-07-19 11:48:22 +02:00
{
if ( $this -> request -> is ( 'post' )) {
2021-01-20 14:21:31 +01:00
$filterData = array (
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'paramArray' => [ 'branch' ],
2021-11-14 12:11:20 +01:00
'ordered_url_params' => [],
2021-01-20 14:21:31 +01:00
'additional_delimiters' => PHP_EOL
);
$exception = false ;
$settings = $this -> _harvestParameters ( $filterData , $exception );
2018-07-19 11:48:22 +02:00
$status = $this -> Server -> getCurrentGitStatus ();
2019-09-11 16:52:14 +02:00
$raw = array ();
2020-11-17 11:15:43 +01:00
if ( empty ( $status [ 'branch' ])) { // do not try to update if you are not on branch
$msg = 'Update failed, you are not on branch' ;
$raw [] = $msg ;
$update = $msg ;
} else {
2021-01-20 16:39:10 +01:00
if ( $settings === false ) {
$settings = [];
}
2021-01-20 14:21:31 +01:00
$update = $this -> Server -> update ( $status , $raw , $settings );
2020-11-17 11:15:43 +01:00
}
2019-09-11 16:52:14 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( array ( 'results' => $raw ), $this -> response -> type ());
} else {
2020-11-17 11:15:43 +01:00
return new CakeResponse ( array ( 'body' => $update , 'type' => 'txt' ));
2019-09-11 16:52:14 +02:00
}
2018-07-19 11:48:22 +02:00
} else {
2021-11-14 12:11:20 +01:00
$this -> set ( 'isUpdatePossible' , $this -> Server -> isUpdatePossible ());
$this -> set ( 'branch' , $this -> Server -> getCurrentBranch ());
2018-07-19 11:48:22 +02:00
$this -> render ( 'ajax/update' );
}
}
2019-04-26 09:45:03 +02:00
public function ondemandAction ()
{
$this -> AdminSetting = ClassRegistry :: init ( 'AdminSetting' );
$actions = $this -> Server -> actions_description ;
$default_fields = array (
'title' => '' ,
'description' => '' ,
'liveOff' => false ,
'recommendBackup' => false ,
'exitOnError' => false ,
'requirements' => '' ,
2020-08-17 17:28:04 +02:00
'url' => $this -> baseurl . '/'
2019-04-26 09:45:03 +02:00
);
foreach ( $actions as $id => $action ) {
foreach ( $default_fields as $field => $value ) {
if ( ! isset ( $action [ $field ])) {
$actions [ $id ][ $field ] = $value ;
}
}
$done = $this -> AdminSetting -> getSetting ( $id );
2019-04-29 11:09:04 +02:00
$actions [ $id ][ 'done' ] = ( $done == '1' );
2019-04-26 09:45:03 +02:00
}
$this -> set ( 'actions' , $actions );
$this -> set ( 'updateLocked' , $this -> Server -> isUpdateLocked ());
}
2019-10-03 13:50:55 +02:00
public function updateProgress ( $ajaxHtml = false )
2019-04-26 09:45:03 +02:00
{
2019-10-03 13:50:55 +02:00
$this -> AdminSetting = ClassRegistry :: init ( 'AdminSetting' );
2019-10-29 09:57:25 +01:00
$dbVersion = $this -> AdminSetting -> getSetting ( 'db_version' );
$updateProgress = $this -> Server -> getUpdateProgress ();
$updateProgress [ 'db_version' ] = $dbVersion ;
2022-06-08 09:55:03 +02:00
$maxUpdateNumber = max ( array_keys ( Server :: DB_CHANGES ));
2019-10-29 09:57:25 +01:00
$updateProgress [ 'complete_update_remaining' ] = max ( $maxUpdateNumber - $dbVersion , 0 );
$updateProgress [ 'update_locked' ] = $this -> Server -> isUpdateLocked ();
$updateProgress [ 'lock_remaining_time' ] = $this -> Server -> getLockRemainingTime ();
$updateProgress [ 'update_fail_number_reached' ] = $this -> Server -> UpdateFailNumberReached ();
$currentIndex = $updateProgress [ 'current' ];
$currentCommand = ! isset ( $updateProgress [ 'commands' ][ $currentIndex ]) ? '' : $updateProgress [ 'commands' ][ $currentIndex ];
$lookupString = preg_replace ( '/\s{2,}/' , '' , substr ( $currentCommand , 0 , - 1 ));
$sqlInfo = $this -> Server -> query ( " SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; " );
if ( empty ( $sqlInfo )) {
$updateProgress [ 'process_list' ] = array ();
2019-04-26 09:45:03 +02:00
} else {
2019-10-04 13:02:59 +02:00
// retrieve current update process
2019-10-29 09:57:25 +01:00
foreach ( $sqlInfo as $row ) {
if ( preg_replace ( '/\s{2,}/' , '' , $row [ 'PROCESSLIST' ][ 'INFO' ]) == $lookupString ) {
$sqlInfo = $row [ 'PROCESSLIST' ];
2019-04-26 09:45:03 +02:00
break ;
}
}
2019-10-29 09:57:25 +01:00
$updateProgress [ 'process_list' ] = array ();
$updateProgress [ 'process_list' ][ 'STATE' ] = isset ( $sqlInfo [ 'STATE' ]) ? $sqlInfo [ 'STATE' ] : '' ;
$updateProgress [ 'process_list' ][ 'PROGRESS' ] = isset ( $sqlInfo [ 'PROGRESS' ]) ? $sqlInfo [ 'PROGRESS' ] : 0 ;
$updateProgress [ 'process_list' ][ 'STAGE' ] = isset ( $sqlInfo [ 'STAGE' ]) ? $sqlInfo [ 'STAGE' ] : 0 ;
$updateProgress [ 'process_list' ][ 'MAX_STAGE' ] = isset ( $sqlInfo [ 'MAX_STAGE' ]) ? $sqlInfo [ 'MAX_STAGE' ] : 0 ;
2019-04-26 09:45:03 +02:00
}
2019-10-03 13:50:55 +02:00
$this -> set ( 'ajaxHtml' , $ajaxHtml );
if ( $this -> request -> is ( 'ajax' ) && $ajaxHtml ) {
2019-10-29 09:57:25 +01:00
$this -> set ( 'updateProgress' , $updateProgress );
2019-10-03 13:50:55 +02:00
$this -> layout = false ;
2019-10-14 10:49:41 +02:00
} elseif ( $this -> request -> is ( 'ajax' ) || $this -> _isRest ()) {
2019-10-29 09:57:25 +01:00
return $this -> RestResponse -> viewData ( h ( $updateProgress ), $this -> response -> type ());
2019-04-26 09:45:03 +02:00
} else {
2019-10-29 09:57:25 +01:00
$this -> set ( 'updateProgress' , $updateProgress );
2019-04-26 09:45:03 +02:00
}
}
2019-04-05 10:46:49 +02:00
public function getSubmoduleQuickUpdateForm ( $submodule_path = false ) {
$this -> set ( 'submodule' , base64_decode ( $submodule_path ));
$this -> render ( 'ajax/submodule_quick_update_form' );
}
2019-04-02 11:29:10 +02:00
public function updateSubmodule ()
{
if ( $this -> request -> is ( 'post' )) {
$request = $this -> request -> data ;
$submodule = $request [ 'Server' ][ 'submodule' ];
2019-04-05 14:28:19 +02:00
$res = $this -> Server -> updateSubmodule ( $this -> Auth -> user (), $submodule );
2019-04-02 11:29:10 +02:00
return new CakeResponse ( array ( 'body' => json_encode ( $res ), 'type' => 'json' ));
} else {
throw new MethodNotAllowedException ();
}
}
2018-07-19 11:48:22 +02:00
public function getInstanceUUID ()
{
return $this -> RestResponse -> viewData ( array ( 'uuid' => Configure :: read ( 'MISP.uuid' )), $this -> response -> type ());
}
2018-08-08 11:29:38 +02:00
2019-01-18 09:06:23 +01:00
public function cache ( $id = 'all' )
{
if ( Configure :: read ( 'MISP.background_jobs' )) {
2021-11-02 11:09:41 +01:00
2019-01-18 09:06:23 +01:00
$this -> loadModel ( 'Job' );
2021-11-02 11:09:41 +01:00
$jobId = $this -> Job -> createJob (
$this -> Auth -> user (),
Job :: WORKER_DEFAULT ,
'cache_servers' ,
intval ( $id ) ? $id : 'all' ,
__ ( 'Starting server caching.' )
2019-01-18 09:06:23 +01:00
);
2021-11-02 11:09:41 +01:00
$this -> Server -> getBackgroundJobsTool () -> enqueue (
BackgroundJobsTool :: DEFAULT_QUEUE ,
BackgroundJobsTool :: CMD_SERVER ,
[
'cacheServer' ,
$this -> Auth -> user ( 'id' ),
$id ,
$jobId
2021-11-02 16:25:43 +01:00
],
false ,
$jobId
2019-01-18 09:06:23 +01:00
);
2021-11-02 11:09:41 +01:00
2019-01-18 09:06:23 +01:00
$message = 'Server caching job initiated.' ;
} else {
$result = $this -> Server -> cacheServerInitiator ( $this -> Auth -> user (), $id );
if ( ! $result ) {
$this -> Flash -> error ( __ ( 'Caching the servers has failed.' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
$message = __ ( 'Caching the servers has successfully completed.' );
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Server' , 'cache' , false , $this -> response -> type (), $message );
} else {
2019-01-18 16:15:22 +01:00
$this -> Flash -> info ( $message );
2019-01-18 09:06:23 +01:00
$this -> redirect ( array ( 'action' => 'index' ));
}
}
2019-04-10 10:09:25 +02:00
public function updateJSON ()
{
$results = $this -> Server -> updateJSON ();
return $this -> RestResponse -> viewData ( $results , $this -> response -> type ());
}
2019-05-30 14:42:29 +02:00
public function createSync ()
{
if ( $this -> _isSiteAdmin ()) {
throw new MethodNotAllowedException ( 'Site admin accounts cannot be used to create server sync configurations.' );
}
$baseurl = Configure :: read ( 'MISP.external_baseurl' );
if ( empty ( $baseurl )) {
$baseurl = Configure :: read ( 'MISP.baseurl' );
if ( empty ( $baseurl )) {
$baseurl = Router :: url ( '/' , true );
}
}
2019-08-12 11:51:37 +02:00
$host_org_id = Configure :: read ( 'MISP.host_org_id' );
if ( empty ( $host_org_id )) {
throw new MethodNotAllowedException ( __ ( 'Cannot create sync config - no host org ID configured for the instance.' ));
}
$this -> loadModel ( 'Organisation' );
$host_org = $this -> Organisation -> find ( 'first' , array (
'conditions' => array ( 'Organisation.id' => $host_org_id ),
'recursive' => - 1 ,
'fields' => array ( 'name' , 'uuid' )
));
if ( empty ( $host_org )) {
throw new MethodNotAllowedException ( __ ( 'Configured host org not found. Please make sure that the setting is current on the instance.' ));
}
2022-03-02 20:50:57 +01:00
if ( Configure :: read ( 'Security.advanced_authkeys' )) {
$this -> loadModel ( 'AuthKey' );
2022-09-09 14:44:22 +02:00
$authkey = $this -> AuthKey -> createnewkey ( $this -> Auth -> user ( 'id' ), null , __ ( 'Auto generated sync key - %s' , date ( 'Y-m-d H:i:s' )));
2022-03-02 20:50:57 +01:00
} else {
$this -> loadModel ( 'User' );
$authkey = $this -> User -> find ( 'column' , [
'conditions' => [ 'User.id' => $this -> Auth -> user ( 'id' )],
'recursive' => - 1 ,
'fields' => [ 'User.authkey' ]
]);
$authkey = $authkey [ 0 ];
}
2019-05-30 14:42:29 +02:00
$server = array (
'Server' => array (
'url' => $baseurl ,
'uuid' => Configure :: read ( 'MISP.uuid' ),
2022-03-02 20:50:57 +01:00
'authkey' => h ( $authkey ),
2019-05-30 14:42:29 +02:00
'Organisation' => array (
2019-08-12 11:51:37 +02:00
'name' => $host_org [ 'Organisation' ][ 'name' ],
'uuid' => $host_org [ 'Organisation' ][ 'uuid' ],
2019-05-30 14:42:29 +02:00
)
)
);
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $server , $this -> response -> type ());
} else {
$this -> set ( 'server' , $server );
}
}
public function import ()
{
if ( $this -> request -> is ( 'post' )) {
$server = $this -> request -> data ;
if ( isset ( $server [ 'Server' ])) {
$server = $server [ 'Server' ];
}
if ( isset ( $server [ 'json' ])) {
$server = json_decode ( $server [ 'json' ], true )[ 'Server' ];
}
$this -> loadModel ( 'Organisation' );
$org_id = $this -> Organisation -> captureOrg ( $server [ 'Organisation' ], $this -> Auth -> user ());
2019-05-30 14:50:51 +02:00
$toSave = array (
2019-05-30 14:42:29 +02:00
'push' => 0 ,
'pull' => 0 ,
'caching_enabled' => 0 ,
'json' => '[]' ,
'push_rules' => '[]' ,
'pull_rules' => '[]' ,
'self_signed' => 0 ,
'org_id' => $this -> Auth -> user ( 'org_id' ),
2019-05-30 15:06:51 +02:00
'remote_org_id' => $org_id ,
2019-05-30 14:50:51 +02:00
'name' => empty ( $server [ 'name' ]) ? $server [ 'url' ] : $server [ 'name' ],
'url' => $server [ 'url' ],
'uuid' => $server [ 'uuid' ],
'authkey' => $server [ 'authkey' ]
2019-05-30 14:42:29 +02:00
);
$this -> Server -> create ();
2019-05-30 14:50:51 +02:00
$result = $this -> Server -> save ( $toSave );
2019-05-30 14:42:29 +02:00
if ( $result ) {
if ( $this -> _isRest ()) {
$server = $this -> Server -> find ( 'first' , array (
'conditions' => array ( 'Server.id' => $this -> Server -> id ),
'recursive' => - 1
));
return $this -> RestResponse -> viewData ( $server , $this -> response -> type ());
} else {
$this -> Flash -> success ( __ ( 'The server has been saved' ));
2019-05-30 14:46:33 +02:00
$this -> redirect ( array ( 'action' => 'index' , $this -> Server -> id ));
2019-05-30 14:42:29 +02:00
}
} else {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'addFromJson' , false , $this -> Server -> validationErrors , $this -> response -> type ());
} else {
2024-01-04 17:59:23 +01:00
$this -> Flash -> error ( __ ( 'Could not save the server. Error: %s' , json_encode ( $this -> Server -> validationErrors )));
2019-05-30 14:42:29 +02:00
$this -> redirect ( array ( 'action' => 'index' ));
}
}
}
}
2019-09-09 13:00:21 +02:00
public function resetRemoteAuthKey ( $id )
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( __ ( 'This endpoint expects POST requests.' ));
}
$result = $this -> Server -> resetRemoteAuthkey ( $id );
if ( $result !== true ) {
if ( ! $this -> _isRest ()) {
$this -> Flash -> error ( $result );
$this -> redirect ( array ( 'action' => 'index' ));
} else {
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'resetRemoteAuthKey' , $id , $message , $this -> response -> type ());
}
} else {
$message = __ ( 'API key updated.' );
if ( ! $this -> _isRest ()) {
$this -> Flash -> success ( $message );
$this -> redirect ( array ( 'action' => 'index' ));
} else {
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'resetRemoteAuthKey' , $message , $this -> response -> type ());
}
}
}
2019-09-13 11:49:12 +02:00
2021-08-25 10:29:45 +02:00
public function changePriority ( $id = false , $direction = 'down' )
{
2019-09-13 11:49:12 +02:00
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new InvalidArgumentException ( __ ( 'ID has to be a valid server connection' ));
}
if ( $direction !== 'up' && $direction !== 'down' ) {
throw new InvalidArgumentException ( __ ( 'Invalid direction. Valid options: ' , 'up' , 'down' ));
}
$success = $this -> Server -> reprioritise ( $id , $direction );
if ( $success ) {
$message = __ ( 'Priority changed.' );
return $this -> RestResponse -> saveSuccessResponse ( 'Servers' , 'changePriority' , $message , $this -> response -> type ());
} else {
$message = __ ( 'Priority could not be changed.' );
2019-09-13 15:50:06 +02:00
return $this -> RestResponse -> saveFailResponse ( 'Servers' , 'changePriority' , $id , $message , $this -> response -> type ());
2019-09-13 11:49:12 +02:00
}
}
2019-10-10 12:02:23 +02:00
public function releaseUpdateLock ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( __ ( 'This endpoint expects POST requests.' ));
}
$this -> Server -> changeLockState ( false );
2019-10-15 11:44:34 +02:00
$this -> Server -> resetUpdateFailNumber ();
2019-10-10 12:02:23 +02:00
$this -> redirect ( array ( 'action' => 'updateProgress' ));
}
2019-11-08 13:52:00 +01:00
public function dbSchemaDiagnostic ()
{
2019-11-19 18:07:30 +01:00
$dbSchemaDiagnostics = $this -> Server -> dbSchemaDiagnostic ();
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $dbSchemaDiagnostics , $this -> response -> type ());
} else {
$this -> set ( 'checkedTableColumn' , $dbSchemaDiagnostics [ 'checked_table_column' ]);
$this -> set ( 'dbSchemaDiagnostics' , $dbSchemaDiagnostics [ 'diagnostic' ]);
2019-12-18 15:53:20 +01:00
$this -> set ( 'dbIndexDiagnostics' , $dbSchemaDiagnostics [ 'diagnostic_index' ]);
2019-11-19 18:07:30 +01:00
$this -> set ( 'expectedDbVersion' , $dbSchemaDiagnostics [ 'expected_db_version' ]);
$this -> set ( 'actualDbVersion' , $dbSchemaDiagnostics [ 'actual_db_version' ]);
$this -> set ( 'error' , $dbSchemaDiagnostics [ 'error' ]);
$this -> set ( 'remainingLockTime' , $dbSchemaDiagnostics [ 'remaining_lock_time' ]);
$this -> set ( 'updateFailNumberReached' , $dbSchemaDiagnostics [ 'update_fail_number_reached' ]);
$this -> set ( 'updateLocked' , $dbSchemaDiagnostics [ 'update_locked' ]);
2019-12-10 10:49:02 +01:00
$this -> set ( 'dataSource' , $dbSchemaDiagnostics [ 'dataSource' ]);
2019-12-17 10:54:45 +01:00
$this -> set ( 'columnPerTable' , $dbSchemaDiagnostics [ 'columnPerTable' ]);
$this -> set ( 'indexes' , $dbSchemaDiagnostics [ 'indexes' ]);
2019-11-19 18:07:30 +01:00
$this -> render ( '/Elements/healthElements/db_schema_diagnostic' );
}
2019-11-08 13:52:00 +01:00
}
2019-11-20 15:30:06 +01:00
2022-07-19 13:36:53 +02:00
public function dbConfiguration ()
{
$dbConfiguration = $this -> Server -> dbConfiguration ();
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $dbConfiguration , $this -> response -> type ());
} else {
$this -> set ( 'dbConfiguration' , $dbConfiguration );
$this -> render ( '/Elements/healthElements/db_config_diagnostic' );
}
}
2021-02-25 22:04:50 +01:00
public function cspReport ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( 'This action expects a POST request.' );
}
2022-02-23 13:43:10 +01:00
$report = JsonTool :: decode ( $this -> request -> input ());
2021-02-25 22:04:50 +01:00
if ( ! isset ( $report [ 'csp-report' ])) {
throw new RuntimeException ( " Invalid report " );
}
$message = 'CSP reported violation' ;
2021-02-27 11:13:47 +01:00
$remoteIp = $this -> _remoteIp ();
if ( $remoteIp ) {
$message .= ' from IP ' . $remoteIp ;
2021-02-25 22:04:50 +01:00
}
2022-02-23 13:43:10 +01:00
$report = JsonTool :: encode ( $report [ 'csp-report' ], true );
if ( strlen ( $report ) > 1024 * 1024 ) { // limit report to 1 kB
$report = substr ( $report , 0 , 1024 * 1024 ) . '...' ;
}
$this -> log ( " $message : $report " );
2021-02-25 22:04:50 +01:00
2022-02-23 13:43:10 +01:00
return new CakeResponse ([ 'status' => 204 ]);
2021-02-25 22:04:50 +01:00
}
2020-06-22 16:14:16 +02:00
/**
* List all tags for the rule picker .
*
* @ return array
*/
private function __getTags ()
{
$this -> loadModel ( 'Tag' );
$list = $this -> Tag -> find ( 'list' , array (
'recursive' => - 1 ,
'order' => array ( 'LOWER(TRIM(Tag.name))' => 'ASC' ),
'fields' => array ( 'name' ),
));
$allTags = array ();
foreach ( $list as $id => $name ) {
$allTags [] = array ( 'id' => $id , 'name' => trim ( $name ));
}
return $allTags ;
}
2021-04-08 15:50:45 +02:00
public function removeOrphanedCorrelations ()
{
2021-10-28 21:35:37 +02:00
$count = $this -> Server -> removeOrphanedCorrelations ();
$message = __ ( '%s orphaned correlation removed' , $count );
2021-04-08 15:50:45 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $message , $this -> response -> type ());
} else {
$this -> Flash -> success ( $message );
$this -> redirect ( array ( 'action' => 'serverSettings' , 'diagnostics' ));
}
}
2021-04-20 10:46:43 +02:00
public function queryAvailableSyncFilteringRules ( $serverID )
{
if ( ! $this -> _isRest ()) {
throw new MethodNotAllowedException ( __ ( 'This method can only be access via REST' ));
}
$server = $this -> Server -> find ( 'first' , [ 'conditions' => [ 'Server.id' => $serverID ]]);
if ( ! $server ) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
$syncFilteringRules = $this -> Server -> queryAvailableSyncFilteringRules ( $server );
return $this -> RestResponse -> viewData ( $syncFilteringRules );
}
public function getAvailableSyncFilteringRules ()
{
if ( ! $this -> _isRest ()) {
throw new MethodNotAllowedException ( __ ( 'This method can only be access via REST' ));
}
$syncFilteringRules = $this -> Server -> getAvailableSyncFilteringRules ( $this -> Auth -> user ());
return $this -> RestResponse -> viewData ( $syncFilteringRules );
}
2021-06-03 17:49:36 +02:00
2021-09-26 12:23:23 +02:00
public function pruneDuplicateUUIDs ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
$this -> loadModel ( 'Attribute' );
$duplicates = $this -> Attribute -> find ( 'all' , array (
'fields' => array ( 'Attribute.uuid' , 'count(*) as occurance' ),
'recursive' => - 1 ,
'group' => array ( 'Attribute.uuid HAVING COUNT(*) > 1' ),
));
$counter = 0 ;
foreach ( $duplicates as $duplicate ) {
$attributes = $this -> Attribute -> find ( 'all' , array (
'recursive' => - 1 ,
'conditions' => array ( 'uuid' => $duplicate [ 'Attribute' ][ 'uuid' ])
));
foreach ( $attributes as $k => $attribute ) {
if ( $k > 0 ) {
$this -> Attribute -> delete ( $attribute [ 'Attribute' ][ 'id' ]);
$counter ++ ;
}
}
}
$this -> Server -> updateDatabase ( 'makeAttributeUUIDsUnique' );
$this -> Flash -> success ( 'Done. Deleted ' . $counter . ' duplicate attribute(s).' );
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
}
public function removeDuplicateEvents ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
$this -> loadModel ( 'Event' );
$duplicates = $this -> Event -> find ( 'all' , array (
'fields' => array ( 'Event.uuid' , 'count(*) as occurance' ),
'recursive' => - 1 ,
'group' => array ( 'Event.uuid HAVING COUNT(*) > 1' ),
));
$counter = 0 ;
// load this so we can remove the blocklist item that will be created, this is the one case when we do not want it.
if ( Configure :: read ( 'MISP.enableEventBlocklisting' ) !== false ) {
$this -> EventBlocklist = ClassRegistry :: init ( 'EventBlocklist' );
}
foreach ( $duplicates as $duplicate ) {
$events = $this -> Event -> find ( 'all' , array (
'recursive' => - 1 ,
'conditions' => array ( 'uuid' => $duplicate [ 'Event' ][ 'uuid' ])
));
foreach ( $events as $k => $event ) {
if ( $k > 0 ) {
$uuid = $event [ 'Event' ][ 'uuid' ];
$this -> Event -> delete ( $event [ 'Event' ][ 'id' ]);
$counter ++ ;
// remove the blocklist entry that we just created with the event deletion, if the feature is enabled
// We do not want to block the UUID, since we just deleted a copy
if ( Configure :: read ( 'MISP.enableEventBlocklisting' ) !== false ) {
$this -> EventBlocklist -> deleteAll ( array ( 'EventBlocklist.event_uuid' => $uuid ));
}
}
}
}
$this -> Server -> updateDatabase ( 'makeEventUUIDsUnique' );
$this -> Flash -> success ( 'Done. Removed ' . $counter . ' duplicate events.' );
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
}
public function upgrade2324 ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
$this -> Server -> upgrade2324 ( $this -> Auth -> user ( 'id' ));
$this -> Flash -> success ( 'Done. For more details check the audit logs.' );
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
} else {
2021-11-02 11:09:41 +01:00
$this -> loadModel ( 'Job' );
$jobId = $this -> Job -> createJob (
$this -> Auth -> user (),
Job :: WORKER_DEFAULT ,
'upgrade_24' ,
'Old database' ,
__ ( 'Job created.' )
2021-09-26 12:23:23 +02:00
);
2021-11-02 11:09:41 +01:00
$this -> Server -> getBackgroundJobsTool () -> enqueue (
BackgroundJobsTool :: DEFAULT_QUEUE ,
BackgroundJobsTool :: CMD_ADMIN ,
[
'jobUpgrade24' ,
$jobId ,
$this -> Auth -> user ( 'id' ),
],
2021-11-02 16:25:43 +01:00
true ,
$jobId
2021-09-26 12:23:23 +02:00
);
2021-11-02 11:09:41 +01:00
2021-09-26 12:23:23 +02:00
$this -> Flash -> success ( __ ( 'Job queued. You can view the progress if you navigate to the active jobs view (administration -> jobs).' ));
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
}
}
public function cleanModelCaches ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
$this -> Server -> cleanCacheFiles ();
$this -> Flash -> success ( 'Caches cleared.' );
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'serverSettings' , 'diagnostics' ));
}
public function updateDatabase ( $command )
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
if ( is_numeric ( $command )) {
$command = intval ( $command );
}
$this -> Server -> updateDatabase ( $command );
$this -> Flash -> success ( 'Done.' );
if ( $liveOff ) {
$this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'updateProgress' ));
} else {
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
}
}
2022-03-10 13:41:22 +01:00
2022-03-10 13:47:27 +01:00
public function ipUser ( $input = false )
2022-03-10 13:41:22 +01:00
{
$params = $this -> IndexFilter -> harvestParameters ([ 'ip' ]);
if ( ! empty ( $params [ 'ip' ])) {
2022-03-10 13:47:27 +01:00
$input = $params [ 'ip' ];
2022-03-10 13:41:22 +01:00
}
$redis = $this -> Server -> setupRedis ();
2022-03-10 13:47:27 +01:00
if ( ! is_array ( $input )) {
$input = [ $input ];
2022-03-10 13:41:22 +01:00
}
2022-03-10 13:47:27 +01:00
$users = [];
foreach ( $input as $ip ) {
if ( ! filter_var ( $ip , FILTER_VALIDATE_IP )) {
continue ;
}
$user_id = $redis -> get ( 'misp:ip_user:' . $ip );
if ( empty ( $user_id )) {
continue ;
}
$this -> loadModel ( 'User' );
$user = $this -> User -> find ( 'first' , [
'recursive' => - 1 ,
'conditions' => [ 'User.id' => $user_id ],
'contain' => [ 'Organisation.name' ]
]);
if ( empty ( $user )) {
throw new NotFoundException ( __ ( 'User not found (perhaps it has been removed?).' ));
}
$users [ $ip ] = [
'id' => $user [ 'User' ][ 'id' ],
'email' => $user [ 'User' ][ 'email' ],
];
2022-03-10 13:41:22 +01:00
}
2022-03-10 13:47:27 +01:00
return $this -> RestResponse -> viewData ( $users , $this -> response -> type ());
2022-03-10 13:41:22 +01:00
}
2022-04-10 10:18:28 +02:00
/**
* @ deprecated
* @ return void
*/
public function rest ()
{
$this -> redirect ([ 'controller' => 'api' , 'action' => 'rest' ]);
}
2013-05-22 10:52:03 +02:00
}