2013-05-22 10:52:03 +02:00
< ? php
App :: uses ( 'AppController' , 'Controller' );
App :: uses ( 'Xml' , 'Utility' );
/**
* Servers Controller
*
* @ property Server $Server
*
* @ throws ConfigureException // TODO Exception
*/
class ServersController extends AppController {
public $components = array ( 'Security' , 'RequestHandler' ); // XXX ACL component
public $paginate = array (
'limit' => 60 ,
'maxLimit' => 9999 , // LATER we will bump here on a problem once we have more than 9999 events
'order' => array (
'Server.url' => 'ASC'
)
);
public $uses = array ( 'Server' , 'Event' );
public function beforeFilter () {
parent :: beforeFilter ();
// Disable this feature if the sync configuration option is not active
2014-02-14 10:27:09 +01:00
if ( 'true' != Configure :: read ( 'MISP.sync' ))
2013-05-22 10:52:03 +02:00
throw new ConfigureException ( " The sync feature is not active in the configuration. " );
// permit reuse of CSRF tokens on some pages.
switch ( $this -> request -> params [ 'action' ]) {
case 'push' :
case 'pull' :
$this -> Security -> csrfUseOnce = false ;
}
}
/**
* index method
*
* @ return void
*/
public function index () {
$this -> Server -> recursive = 0 ;
2013-10-24 16:41:42 +02:00
if ( $this -> _isSiteAdmin ()) {
2013-05-22 10:52:03 +02:00
$this -> paginate = array (
'conditions' => array (),
);
} else {
2013-10-24 16:41:42 +02:00
if ( ! $this -> userRole [ 'perm_sync' ] && ! $this -> userRole [ 'perm_admin' ]) $this -> redirect ( array ( 'controller' => 'events' , 'action' => 'index' ));
2013-05-22 10:52:03 +02:00
$conditions [ 'Server.org LIKE' ] = $this -> Auth -> user ( 'org' );
$this -> paginate = array (
'conditions' => array ( $conditions ),
);
}
$this -> set ( 'servers' , $this -> paginate ());
}
/**
* add method
*
* @ return void
*/
public function add () {
2014-01-21 16:41:32 +01:00
if ( ! $this -> _isAdmin ()) $this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
2013-05-22 10:52:03 +02:00
if ( $this -> request -> is ( 'post' )) {
// force check userid and orgname to be from yourself
$this -> request -> data [ 'Server' ][ 'org' ] = $this -> Auth -> user ( 'org' );
if ( $this -> Server -> save ( $this -> request -> data )) {
2014-01-21 16:41:32 +01:00
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_cert' ])) {
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id );
2014-01-16 08:47:25 +01:00
}
2013-05-22 10:52:03 +02:00
$this -> Session -> setFlash ( __ ( 'The server has been saved' ));
$this -> redirect ( array ( 'action' => 'index' ));
} else {
$this -> Session -> setFlash ( __ ( 'The server could not be saved. Please, try again.' ));
}
}
}
/**
* edit method
*
* @ param string $id
* @ return void
* @ throws NotFoundException
*/
public function edit ( $id = null ) {
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2014-01-21 16:41:32 +01:00
$s = $this -> Server -> read ( null , $id );
if ( ! $this -> _isSiteAdmin () && ! ( $s [ 'Server' ][ 'org' ] == $this -> Auth -> user ( 'org' ) && $this -> _isAdmin ())) $this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
2013-05-22 10:52:03 +02:00
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
// say what fields are to be updated
2014-02-17 11:40:44 +01:00
$fieldList = array ( 'id' , 'url' , 'push' , 'pull' , 'organization' , 'self_signed' , 'cert_file' );
2014-01-07 11:08:21 +01:00
$this -> request -> data [ 'Server' ][ 'id' ] = $id ;
2013-05-22 10:52:03 +02:00
if ( " " != $this -> request -> data [ 'Server' ][ 'authkey' ])
$fieldList [] = 'authkey' ;
// Save the data
if ( $this -> Server -> save ( $this -> request -> data , true , $fieldList )) {
2014-01-29 15:52:09 +01:00
if ( isset ( $this -> request -> data [ 'Server' ][ 'submitted_cert' ]) && $this -> request -> data [ 'Server' ][ 'submitted_cert' ][ 'size' ] != 0 ) {
2014-01-21 16:41:32 +01:00
$this -> __saveCert ( $this -> request -> data , $this -> Server -> id );
}
2013-05-22 10:52:03 +02:00
$this -> Session -> setFlash ( __ ( 'The server has been saved' ));
$this -> redirect ( array ( 'action' => 'index' ));
} else {
$this -> Session -> setFlash ( __ ( '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 ;
}
}
/**
* delete method
*
* @ param string $id
* @ return void
* @ throws MethodNotAllowedException
* @ throws NotFoundException
*/
public function delete ( $id = null ) {
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2014-01-21 16:41:32 +01:00
$s = $this -> Server -> read ( null , $id );
2014-01-24 10:43:07 +01:00
if ( ! $this -> _isSiteAdmin () && ! ( $s [ 'Server' ][ 'org' ] == $this -> Auth -> user ( 'org' ) && $this -> _isAdmin ())) $this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
2013-05-22 10:52:03 +02:00
if ( $this -> Server -> delete ()) {
$this -> Session -> setFlash ( __ ( 'Server deleted' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
$this -> Session -> setFlash ( __ ( 'Server was not deleted' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
2013-06-19 12:13:45 +02:00
/**
* Pull one or more events with attributes from a remote instance .
* Set $technique to
* full - download everything
* incremental - only new events
* < int > - specific id of the event to pull
* For example to download event 10 from server 2 to / servers / pull / 2 / 5
* @ param int $id The id of the server
* @ param unknown_type $technique
* @ throws MethodNotAllowedException
* @ throws NotFoundException
*/
public function pull ( $id = null , $technique = false ) {
2013-05-22 10:52:03 +02:00
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2014-01-05 21:30:39 +01:00
$s = $this -> Server -> read ( null , $id );
2014-01-24 10:43:07 +01:00
if ( ! $this -> _isSiteAdmin () && ! ( $s [ 'Server' ][ 'org' ] == $this -> Auth -> user ( 'org' ) && $this -> _isAdmin ())) $this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
2014-01-21 16:41:32 +01:00
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2013-05-22 10:52:03 +02:00
if ( false == $this -> Server -> data [ 'Server' ][ 'pull' ]) {
$this -> Session -> setFlash ( __ ( 'Pull setting not enabled for this server.' ));
$this -> redirect ( array ( 'action' => 'index' ));
}
2014-01-06 05:15:47 +01:00
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
$result = $this -> Server -> pull ( $this -> Auth -> user (), $id , $technique , $s );
// error codes
if ( is_numeric ( $result )) {
switch ( $result ) {
case '1' :
$this -> Session -> setFlash ( __ ( 'Not authorised. This is either due to an invalid auth key, or due to the sync user not having authentication permissions enabled on the remote server.' ));
$this -> redirect ( array ( 'action' => 'index' ));
break ;
case '2' :
$this -> Session -> setFlash ( $eventIds );
$this -> redirect ( array ( 'action' => 'index' ));
break ;
case '3' :
throw new NotFoundException ( 'Sorry, this is not yet implemented' );
break ;
case '4' :
$this -> redirect ( array ( 'action' => 'index' ));
break ;
}
} else {
$this -> set ( 'successes' , $result [ 0 ]);
$this -> set ( 'fails' , $result [ 1 ]);
$this -> set ( 'pulledProposals' , $result [ 2 ]);
$this -> set ( 'lastpulledid' , $result [ 3 ]);
2013-05-22 10:52:03 +02:00
}
2013-07-17 14:06:24 +02:00
} else {
2014-01-06 05:15:47 +01:00
$this -> loadModel ( 'Job' );
$this -> Job -> create ();
$data = array (
'worker' => 'default' ,
'job_type' => 'pull' ,
'job_input' => 'Server: ' . $id ,
'status' => 0 ,
'retries' => 0 ,
'org' => $this -> Auth -> user ( 'org' ),
'message' => 'Pulling.' ,
);
$this -> Job -> save ( $data );
$jobId = $this -> Job -> id ;
$process_id = CakeResque :: enqueue (
'default' ,
'ServerShell' ,
array ( 'pull' , $this -> Auth -> user ( 'id' ), $id , $technique , $jobId )
);
$this -> Job -> saveField ( 'process_id' , $process_id );
$this -> Session -> setFlash ( 'Pull queued for background execution.' );
2013-07-17 14:06:24 +02:00
$this -> redirect ( array ( 'action' => 'index' ));
2013-06-19 12:13:45 +02:00
}
2013-05-22 10:52:03 +02:00
}
2013-06-19 12:13:45 +02:00
public function push ( $id = null , $technique = false ) {
2013-05-22 10:52:03 +02:00
$this -> Server -> id = $id ;
if ( ! $this -> Server -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid server' ));
}
2014-01-21 16:41:32 +01:00
$s = $this -> Server -> read ( null , $id );
2014-01-24 10:43:07 +01:00
if ( ! $this -> _isSiteAdmin () && ! ( $s [ 'Server' ][ 'org' ] == $this -> Auth -> user ( 'org' ) && $this -> _isAdmin ())) $this -> redirect ( array ( 'controller' => 'servers' , 'action' => 'index' ));
2014-01-06 05:15:47 +01:00
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
2014-01-16 08:47:25 +01:00
$server = $this -> Server -> read ( null , $id );
App :: uses ( 'SyncTool' , 'Tools' );
$syncTool = new SyncTool ();
$HttpSocket = $syncTool -> setupHttpSocket ( $server );
2014-01-06 05:15:47 +01:00
$result = $this -> Server -> push ( $id , $technique , false , $HttpSocket );
$this -> set ( 'successes' , $result [ 0 ]);
$this -> set ( 'fails' , $result [ 1 ]);
2013-07-17 14:06:24 +02:00
} else {
2014-01-06 05:15:47 +01:00
$this -> loadModel ( 'Job' );
$this -> Job -> create ();
$data = array (
'worker' => 'default' ,
'job_type' => 'push' ,
'job_input' => 'Server: ' . $id ,
'status' => 0 ,
'retries' => 0 ,
'org' => $this -> Auth -> user ( 'org' ),
'message' => 'Pushing.' ,
2013-07-17 14:27:51 +02:00
);
2014-01-06 05:15:47 +01:00
$this -> Job -> save ( $data );
$jobId = $this -> Job -> id ;
$process_id = CakeResque :: enqueue (
'default' ,
'ServerShell' ,
array ( 'push' , $id , $technique , $jobId )
);
$this -> Job -> saveField ( 'process_id' , $process_id );
$this -> Session -> setFlash ( 'Push queued for background execution.' );
$this -> redirect ( array ( 'action' => 'index' ));
2013-05-22 10:52:03 +02:00
}
}
2014-01-21 16:41:32 +01:00
public function __saveCert ( $server , $id ) {
$ext = '' ;
App :: uses ( 'File' , 'Utility' );
2014-02-17 11:40:44 +01:00
App :: uses ( 'Folder' , 'Utility' );
2014-01-21 16:41:32 +01:00
$file = new File ( $server [ 'Server' ][ 'submitted_cert' ][ 'name' ]);
$ext = $file -> ext ();
if (( $ext != 'pem' ) || ! $server [ 'Server' ][ 'submitted_cert' ][ 'size' ] > 0 ) {
$this -> Session -> setFlash ( 'Incorrect extension of empty file.' );
$this -> redirect ( array ( 'action' => 'index' ));
}
$pemData = fread ( fopen ( $server [ 'Server' ][ 'submitted_cert' ][ 'tmp_name' ], " r " ),
$server [ 'Server' ][ 'submitted_cert' ][ 'size' ]);
$destpath = APP . " files " . DS . " certs " . DS ;
2014-02-17 11:40:44 +01:00
$dir = new Folder ( APP . " files " . DS . " certs " , true );
2014-01-21 16:41:32 +01:00
if ( ! preg_match ( '@^[\w-,\s,\.]+\.[A-Za-z0-9_]{2,4}$@' , $server [ 'Server' ][ 'submitted_cert' ][ 'name' ])) throw new Exception ( 'Filename not allowed' );
$pemfile = new File ( $destpath . $id . '.' . $ext );
2014-02-17 11:40:44 +01:00
$result = $pemfile -> write ( $pemData );
2014-01-21 16:41:32 +01:00
$s = $this -> Server -> read ( null , $id );
$s [ 'Server' ][ 'cert_file' ] = $s [ 'Server' ][ 'id' ] . '.' . $ext ;
if ( $result ) $this -> Server -> save ( $s );
}
2013-05-22 10:52:03 +02:00
}