Further updates to the sync

pull/195/head
iglocska 2013-08-12 17:23:32 +02:00
parent d8b61d90ab
commit 285ff481a5
4 changed files with 94 additions and 46 deletions

View File

@ -104,6 +104,9 @@ class AttributesController extends AppController {
// remove the published flag from the event
$this->Event->recursive = -1;
$this->Event->read(null, $this->request->data['Attribute']['event_id']);
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException('You do not have permission to do that.');
}
$this->Event->set('timestamp', $date->getTimestamp());
$this->Event->set('published', 0);
$this->Event->save($this->Event->data, array('fieldList' => array('published', 'timestamp', 'info')));
@ -277,6 +280,12 @@ class AttributesController extends AppController {
//$ssdeep = null;
if ($this->request->is('post')) {
$this->loadModel('Event');
$this->Event->id = $this->request->data['Attribute']['event_id'];
$this->Event->recursive = -1;
$this->Event->read();
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException('You do not have permission to do that.');
}
// 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['Attribute']['value']['name']);
@ -440,6 +449,14 @@ class AttributesController extends AppController {
*/
public function add_threatconnect($eventId = null) {
if ($this->request->is('post')) {
$this->loadModel('Event');
$this->Event->id = $eventId;
$this->Event->recursive = -1;
$this->Event->read();
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException('You do not have permission to do that.');
}
//
// File upload
//
@ -489,21 +506,14 @@ class AttributesController extends AppController {
// import attributes
//
$attributes = array(); // array with all the attributes we're going to save
$this->loadModel('Event');
$this->Event->recursive = -1;
$this->Event->read(null, $eventId);
foreach($entries as $entry) {
$attribute = array();
$attribute['event_id'] = $this->request->data['Attribute']['event_id'];
$attribute['value'] = $entry['Value'];
$attribute['to_ids'] = ($entry['Confidence'] > 51) ? 1 : 0; // To IDS if high confidence
$attribute['distribution'] = '3'; // 'All communities'
$attribute['distribution'] = 3; // 'All communities'
if (Configure::read('MISP.default_attribute_distribution') != null) {
if (Configure::read('MISP.default_attribute_distribution') === 'event') {
$attribute['distribution'] = $this->Event->data['Event']['distribution'];
} else {
$attribute['distribution'] = Configure::read('MISP.default_attribute_distribution');
}
$attribute['distribution'] = Configure::read('MISP.default_attribute_distribution');
}
switch($entry['Type']) {
case 'Address':
@ -615,8 +625,12 @@ class AttributesController extends AppController {
$uuid = $this->Attribute->data['Attribute']['uuid'];
}
if (!$this->_isSiteAdmin()) {
// check for non-private and re-read
if (($this->Attribute->data['Event']['org'] != $this->Auth->user('org')) || (($this->Attribute->data['Event']['org'] == $this->Auth->user('org')) && ($this->Attribute->data['Event']['user_id'] != $this->Auth->user('id')) && (!$this->userRole['perm_modify'] || !$this->userRole['perm_modify_org']))) {
//
if ($this->Attribute->data['Event']['orgc'] == $this->Auth->user('org')
&& (($this->userRole['perm_modify'] && $this->Attribute->data['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
} else {
$this->Session->setFlash(__('Invalid attribute.'));
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
@ -741,6 +755,20 @@ class AttributesController extends AppController {
$uuid = $result['Attribute']['uuid'];
}
// check for permissions
if (!$this->_isSiteAdmin()) {
$this->Attribute->read();
if ($this->Attribute->data['Event']['locked']) {
if ($this->_checkOrg() != $this->Attribute->data['Event']['org'] || !$this->userRole['perm_sync']) {
throw new MethodNotAllowedException();
}
} else {
if ($this->_checkOrg() != $this->Attribute->data['Event']['orgc']) {
throw new MethodNotAllowedException();
}
}
}
// attachment will be deleted with the beforeDelete() function in the Model
if ($this->Attribute->delete()) {
// delete the attribute from remote servers

View File

@ -446,6 +446,11 @@ class EventsController extends AppController {
}
public function addIOC($id) {
$this->Event->recursive = -1;
$this->Event->read(null, $id);
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException('You do not have permission to do that.');
}
if ($this->request->is('post')) {
if (!empty($this->data)) {
$ext = '';
@ -484,8 +489,6 @@ class EventsController extends AppController {
// set the id
$this->set('id', $id);
$this->Event->recursive = -1;
$this->Event->read(null, $id);
// set whether it is published or not
$this->set('published', $this->Event->data['Event']['published']);
@ -550,11 +553,7 @@ class EventsController extends AppController {
}
// FIXME chri: validate the necessity for all these fields...impact on security !
$fieldList = array(
'Event' => array('orgc', 'date', 'risk', 'analysis', 'info', 'published', 'uuid'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision')
);
$fieldList = array(
'Event' => array('org', 'orgc', 'date', 'risk', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution'),
'Event' => array('org', 'orgc', 'date', 'risk', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution', 'locked'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'timestamp', 'distribution')
);
$saveResult = $this->Event->saveAssociated($data, array('validate' => true, 'fieldList' => $fieldList));
@ -582,6 +581,9 @@ class EventsController extends AppController {
} else {
return 'Event exists and is the same or newer.';
}
if (!$this->Event->data['Event']['locked']) {
return 'Event originated on this instance, any changes to it have to be done locally.';
}
$fieldList = array(
'Event' => array('date', 'risk', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp')
@ -627,14 +629,14 @@ class EventsController extends AppController {
// check for if private and user not authorised to edit, go away
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (($this->Event->data['Event']['org'] != $this->_checkOrg()) || !($this->userRole['perm_modify'])) {
$this->Session->setFlash(__('You are not authorised to do that.'));
$this->Session->setFlash(__('You are not authorised to do that. Please considering using the propose attribute feature.'));
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->_isRest()) {
$saveEvent = true;
$saveEvent = false;
// Workaround for different structure in XML/array than what CakePHP expects
$this->Event->cleanupEventArrayFromXML($this->request->data);
@ -642,7 +644,6 @@ class EventsController extends AppController {
// LATER do this with $this->validator()->remove('event_id');
unset($this->Event->Attribute->validate['event_id']);
unset($this->Event->Attribute->validate['value']['unique']); // otherwise gives bugs because event_id is not set
// http://book.cakephp.org/2.0/en/models/saving-your-data.html
// Creating or updating is controlled by the models id field.
// If $Model->id is set, the record with this primary key is updated.
@ -650,18 +651,23 @@ class EventsController extends AppController {
// reposition to get the event.id with given uuid
$existingEvent = $this->Event->findByUuid($this->request->data['Event']['uuid']);
// If the event exists...
if (count($existingEvent)) {
$this->request->data['Event']['id'] = $existingEvent['Event']['id'];
if (isset($this->request->data['Event']['timestamp'])) {
if ($this->request->data['Event']['timestamp'] > $existingEvent['Event']['timestamp']) {
// Consider shadow attributes?
} else {
$saveEvent = false;
// Conditions affecting all:
// user.org == event.org
// edit timestamp newer than existing event timestamp
if (isset($this->request->data['Event']['timestamp']) && $this->request->data['Event']['timestamp'] > $existingEvent['Event']['timestamp']) {
// If the above is true, we have two more options:
// For users that are of the creating org of the event, always allow the edit
// For users that are sync users, only allow the edit if the event is locked
if ($existingEvent['Event']['orgc'] === $this->_checkOrg()
|| ($this->userRole['perm_sync'] && $existingEvent['Event']['locked'])) {
// Only allow an edit if this is true!
$saveEvent = true;
}
}
}
$fieldList = array(
'Event' => array('date', 'risk', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp')
@ -691,11 +697,7 @@ class EventsController extends AppController {
if ($saveEvent) {
$saveResult = $this->Event->saveAssociated($this->request->data, array('validate' => true, 'fieldList' => $fieldList));
} else {
$message = 'This would be a downgrade...';
$this->set('event', $existingEvent);
$this->view($existingEvent['Event']['id']);
$this->render('view');
return true;
throw new MethodNotAllowedException();
}
if ($saveResult) {
// TODO RESTfull: we now need to compare attributes, to see if we need to do a RESTfull attribute delete
@ -798,7 +800,7 @@ class EventsController extends AppController {
}
if (!$this->_isSiteAdmin()) {
$this->Event->read();
if (!$this->Event->data['Event']['org'] == $this->_checkOrg()) {
if (!$this->Event->data['Event']['orgc'] == $this->_checkOrg()) {
throw new MethodNotAllowedException();
}
}
@ -834,6 +836,7 @@ class EventsController extends AppController {
$this->Event->id = $id;
$this->Event->recursive = 1;
$this->Event->read();
$this->Event->data['Event']['locked'] = 1;
// get a list of the servers
$this->loadModel('Server');
@ -1414,8 +1417,8 @@ class EventsController extends AppController {
// $conditions['AND'][] = array('Event.published =' => 1);
// do not expose all the data ...
$fields = array('Event.id', 'Event.org', 'Event.date', 'Event.risk', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.orgc', 'Event.user_id');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution');
$fields = array('Event.id', 'Event.org', 'Event.date', 'Event.risk', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.orgc', 'Event.user_id', 'Event.locked');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp');
$fieldsShadowAtt = array('ShadowAttribute.id', 'ShadowAttribute.type', 'ShadowAttribute.category', 'ShadowAttribute.value', 'ShadowAttribute.to_ids', 'ShadowAttribute.uuid', 'ShadowAttribute.event_id', 'ShadowAttribute.old_id');
$params = array('conditions' => $conditions,

View File

@ -202,6 +202,8 @@ class ServersController extends AppController {
$this->Server->data);
if (null != $event) {
// we have an Event array
// The event came from a pull, so it should be locked.
$event['Event']['locked'] = true;
if (!isset($event['Event']['distribution'])) { // version 1
$event['Event']['distribution'] = '1';
}
@ -278,7 +280,7 @@ class ServersController extends AppController {
}
} else {
$result = $eventsController->_edit($event, $existingEvent['Event']['id']);
if ($result === 'success') $successes[] = $eventId;
if ($result === 'Success') $successes[] = $eventId;
else $fails[$eventId] = $result;
}
} else {
@ -330,7 +332,7 @@ class ServersController extends AppController {
} else {
$this->redirect(array('action' => 'index'));
}
if (!$eventIds) {
if (!isset($eventIds)) {
$findParams = array(
'conditions' => array(
$eventid_conditions_key => $eventid_conditions_value,
@ -343,6 +345,7 @@ class ServersController extends AppController {
);
$eventIds = $this->Event->find('all', $findParams);
}
//debug($eventIds);
// now process the $eventIds to pull each of the events sequentially
if (!empty($eventIds)) {
$successes = array();
@ -352,12 +355,13 @@ class ServersController extends AppController {
foreach ($eventIds as $eventId) {
$this->Event->recursive=1;
$event = $this->Event->findById($eventId['Event']['id']);
$event['Event']['locked'] = true;
unset($event['User']);
$result = $this->Event->uploadEventToServer(
$event,
$this->Server->data,
$HttpSocket);
if (true == $result) {
if ('Success' === $result) {
$successes[] = $event['Event']['id'];
} else {
$fails[$event['Event']['id']] = $result;
@ -371,8 +375,12 @@ class ServersController extends AppController {
$lastpushedid = max($successes);
}
// increment lastid based on the highest ID seen
$this->Server->saveField('lastpushedid', $lastpushedid);
// Save the entire Server data instead of just a single field, so that the logger can be fed with the extra fields.
$this->Server->data['Server']['lastpushedid'] = $lastpushedid;
$this->Server->save($this->Server->data);
}
if (!isset($successes)) $successes = null;
if (!isset($fails)) $fails = null;
$this->set('successes', $successes);
$this->set('fails', $fails);
}

View File

@ -420,12 +420,15 @@ class Event extends AppModel {
$newLocation = $newTextBody = '';
$result = $this->restfullEventToServer($event, $server, null, $newLocation, $newTextBody, $HttpSocket);
if ($result === 403) {
return false;
return 'The distribution level of this event blocks it from being pushed.';
}
if (strlen($newLocation) || $result) { // HTTP/1.1 200 OK or 302 Found and Location: http://<newLocation>
if (strlen($newLocation)) { // HTTP/1.1 302 Found and Location: http://<newLocation>
//$updated = true;
$result = $this->restfullEventToServer($event, $server, $newLocation, $newLocation, $newTextBody, $HttpSocket);
if ($result === 405) {
return 'You do not have permission to edit this event or the event is up to date.';
}
}
try { // TODO Xml::build() does not throw the XmlException
$xml = Xml::build($newTextBody);
@ -442,7 +445,6 @@ class Event extends AppModel {
}
}
}
// get the new attribute uuids in an array
$newerUuids = array();
foreach ($event['Attribute'] as $attribute) {
@ -461,8 +463,7 @@ class Event extends AppModel {
}
}
}
//if($updated)return false;
return true;
return 'Success';
}
/**
@ -563,14 +564,22 @@ class Event extends AppModel {
}
break;
case '302': // Found
case '404': // Not Found
$newLocation = $response->headers['Location'];
$newTextBody = $response->body();
return true;
//return isset($urlPath) ? $response->body() : $response->headers['Location'];
break;
case '403': //not authorised
case '404': // Not Found
$newLocation = $response->headers['Location'];
$newTextBody = $response->body();
return 404;
break;
case '405':
return 405;
break;
case '403': // Not authorised
return 403;
break;
}
}