MISP/app/Controller/ServersController.php

279 lines
9.4 KiB
PHP
Raw Normal View History

<?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
if ('true' != Configure::read('CyDefSIG.sync'))
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;
if ($this->_isSiteAdmin()) {
$this->paginate = array(
'conditions' => array(),
);
} else {
if (!$this->userRole['perm_sync'] && !$this->userRole['perm_admin']) $this->redirect(array('controller' => 'events', 'action' => 'index'));
$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() {
if ((!$this->_IsSiteAdmin()) && !($this->Server->organization == $this->Auth->user('org') && $this->userRole['perm_sync'])) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
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)) {
if (isset($this->data['Server']['submitted_cert'])) {
$ext = '';
App::uses('File', 'Utility');
$file = new File($this->data['Server']['submitted_cert']['name']);
$ext = $file->ext();
if (($ext != 'pem') || !$this->data['Server']['submitted_cert']['size'] > 0) {
$this->Session->setFlash('Incorrect extension of empty file.');
$this->redirect(array('action' => 'index'));
}
}
if (isset($this->data['Server']['submitted_cert']) && ($ext != 'pem') && $this->data['Server']['submitted_cert']['size'] > 0 &&
is_uploaded_file($this->data['Event']['submittedgfi']['tmp_name'])) {
$this->Session->setFlash(__('You may only upload GFI Sandbox zip files.'));
} else {
$pemData = fread(fopen($this->data['Server']['submitted_cert']['tmp_name'], "r"),
$this->data['Server']['submitted_cert']['size']);
$destpath = APP . "files" . DS . "certs" . DS;
if (!preg_match('@^[\w-,\s,\.]+\.[A-Za-z0-9_]{2,4}$@', $this->data['Server']['submitted_cert']['name'])) throw new Exception ('Filename not allowed');
$pemfile = new File ($destpath . $this->Server->id . '.' . $ext);
$result = $pemfile->write($pemData);
$s = $this->Server->read(null, $this->Server->id);
$s['Server']['cert_file'] = $s['Server']['id'] . '.' . $ext;
if ($result) $this->Server->save($s);
}
$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) {
if (!$this->_IsSiteAdmin() && !($this->Server->organization == $this->Auth->user('org') && $this->userRole['perm_sync'])) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
$this->Server->id = $id;
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
if ($this->request->is('post') || $this->request->is('put')) {
// say what fields are to be updated
$fieldList = array('id', 'url', 'push', 'pull', 'organization');
$this->request->data['Server']['id'] = $id;
if ("" != $this->request->data['Server']['authkey'])
$fieldList[] = 'authkey';
// Save the data
if ($this->Server->save($this->request->data, true, $fieldList)) {
$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->_IsSiteAdmin() && !($this->Server->id == $this->Auth->user('org') && $this->userRole['perm_sync'])) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this->Server->id = $id;
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
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'));
}
/**
* 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) {
if (!$this->_isSiteAdmin() && !($this->Server->organization == $this->Auth->user('org') && $this->userRole['perm_sync'])) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
$this->Server->id = $id;
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
$s = $this->Server->read(null, $id);
if (false == $this->Server->data['Server']['pull']) {
$this->Session->setFlash(__('Pull setting not enabled for this server.'));
$this->redirect(array('action' => 'index'));
}
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]);
}
} else {
$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.');
$this->redirect(array('action' => 'index'));
}
}
public function push($id = null, $technique=false) {
if (!$this->_isSiteAdmin() && !($this->Server->organization == $this->Auth->user('org') && $this->userRole['perm_sync'])) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
$this->Server->id = $id;
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
if (!Configure::read('MISP.background_jobs')) {
$server = $this->Server->read(null, $id);
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$result = $this->Server->push($id, $technique, false, $HttpSocket);
$this->set('successes', $result[0]);
$this->set('fails', $result[1]);
} else {
$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
);
$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'));
}
}
}