Merge branch 'feature/disable_correlation' into 2.4

pull/1784/head
iglocska 2016-12-22 21:02:35 +01:00
commit e28cf5c17a
20 changed files with 479 additions and 43 deletions

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":57}
{"major":2, "minor":4, "hotfix":58}

View File

@ -15,6 +15,17 @@ class AdminShell extends AppShell
$this->Job->saveField('status', 4);
}
public function jobPurgeCorrelation() {
$jobId = $this->args[0];
$this->loadModel('Job');
$this->Job->id = $jobId;
$this->loadModel('Attribute');
$this->Attribute->purgeCorrelations();
$this->Job->saveField('progress', 100);
$this->Job->saveField('message', 'Job done.');
$this->Job->saveField('status', 4);
}
public function jobGenerateShadowAttributeCorrelation() {
$jobId = $this->args[0];
$this->loadModel('Job');

View File

@ -46,7 +46,7 @@ class AppController extends Controller {
public $helpers = array('Utility');
private $__jsVersion = '2.4.52';
private $__jsVersion = '2.4.58';
public $phpmin = '5.5.9';
public $phprec = '5.6.0';

View File

@ -2486,4 +2486,52 @@ class AttributesController extends AppController {
$this->response->type('json');
$this->render('/Servers/json/simple');
}
public function toggleCorrelation($id) {
if (!$this->_isSiteAdmin() && Configure.read('MISP.allow_disabling_correlation')) {
throw new MethodNotAllowedException('Disabling the correlation is not permitted on this instance.');
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
throw new NotFoundException('Invalid Attribute.');
}
if (!$this->Auth->user('Role')['perm_modify']) {
throw new MethodNotAllowedException('You don\'t have permission to do that.');
}
$conditions = array('Attribute.id' => $id);
if (!$this->_isSiteAdmin()) {
$conditions['Event.orgc_id'] = $this->Auth->user('org_id');
}
$attribute = $this->Attribute->find('first', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Event')
));
if (empty($attribute)) {
throw new NotFoundException('Invalid Attribute.');
}
if (!$this->Auth->user('Role')['perm_modify_org'] && $this->Auth->user('id') != $attribute['Event']['user_id']) {
throw new MethodNotAllowedException('You don\'t have permission to do that.');
}
if ($this->request->is('post')) {
if ($attribute['Attribute']['disable_correlation']) {
$attribute['Attribute']['disable_correlation'] = 0;
$this->Attribute->save($attribute);
$this->Attribute->__afterSaveCorrelation($attribute['Attribute'], false, $attribute);
} else {
$attribute['Attribute']['disable_correlation'] = 1;
$this->Attribute->save($attribute);
$this->Attribute->purgeCorrelations($attribute['Event']['id'], $attribute['Attribute']['id']);
}
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('attributes', 'toggleCorrelation', $id, false, 'Correlation ' . ($attribute['Attribute']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
} else {
$this->Session->setFlash('Correlation ' . ($attribute['Attribute']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
$this->redirect(array('controller' => 'events', 'action' => 'view', $attribute['Event']['id']));
}
} else {
$this->set('attribute', $attribute);
$this->render('ajax/toggle_correlation');
}
}
}

View File

@ -58,6 +58,7 @@ class ACLComponent extends Component {
'rpz' => array('*'),
'search' => array('*'),
'searchAlternate' => array('*'),
'toggleCorrelation' => array('perm_add'),
'text' => array('*'),
'updateAttributeValues' => array('perm_add'),
'view' => array('*'),
@ -81,6 +82,7 @@ class ACLComponent extends Component {
'add_misp_export' => array('perm_modify'),
'alert' => array('perm_publish'),
'automation' => array('perm_auth'),
'checkPublishedStatus' => array('*'),
'checkuuid' => array('perm_sync'),
'contact' => array('*'),
'create_dummy_event' => array(),
@ -112,6 +114,7 @@ class ACLComponent extends Component {
'saveFreeText' => array('perm_add'),
'stix' => array('*'),
'strposarray' => array(),
'toggleCorrelation' => array('perm_add'),
'updateGraph' => array('*'),
'upload_sample' => array('perm_auth'),
'view' => array('*'),

View File

@ -2900,7 +2900,7 @@ class EventsController extends AppController {
$tag_id = $tag['Tag']['id'];
}
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $id);
$event = $this->Event->read(array(), $id);
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
@ -2927,9 +2927,13 @@ class EventsController extends AppController {
if (!empty($found)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag is already attached to this event.')), 'status'=>200));
$this->Event->EventTag->create();
if ($this->Event->EventTag->save(array('event_id' => $id, 'tag_id' => $tag_id))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag added.')), 'status'=>200));
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag added.', 'check_publish' => true)), 'status'=>200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be added.')),'status'=>200));
}
@ -2958,7 +2962,7 @@ class EventsController extends AppController {
}
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution'), $id);
$event = $this->Event->read(array(), $id);
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id']) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')),'status'=>200));
@ -2978,9 +2982,13 @@ class EventsController extends AppController {
'fields' => array('Tag.name')
));
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.')), 'status'=>200));
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.', 'check_publish' => true)), 'status'=>200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
}
@ -4060,4 +4068,65 @@ class EventsController extends AppController {
$this->response->download('misp.event.' . $id . '.' . $module . '.export.' . $result['extension']);
return $this->response;
}
public function toggleCorrelation($id) {
if (!$this->_isSiteAdmin() && Configure.read('MISP.allow_disabling_correlation')) {
throw new MethodNotAllowedException('Disabling the correlation is not permitted on this instance.');
}
$this->Event->id = $id;
if (!$this->Event->exists()) {
throw new NotFoundException('Invalid Event.');
}
if (!$this->Auth->user('Role')['perm_modify']) {
throw new MethodNotAllowedException('You don\'t have permission to do that.');
}
$conditions = array('Event.id' => $id);
if (!$this->_isSiteAdmin()) {
$conditions['Event.orgc_id'] = $this->Auth->user('org_id');
}
$event = $this->Event->find('first', array(
'conditions' => $conditions,
'recursive' => -1
));
if (empty($event)) {
throw new NotFoundException('Invalid Event.');
}
if (!$this->Auth->user('Role')['perm_modify_org'] && $this->Auth->user('id') != $event['Event']['user_id']) {
throw new MethodNotAllowedException('You don\'t have permission to do that.');
}
if ($this->request->is('post')) {
if ($event['Event']['disable_correlation']) {
$event['Event']['disable_correlation'] = 0;
$this->Event->save($event);
$attributes = $this->Event->Attribute->find('all', array(
'conditions' => array('Attribute.event_id' => $id),
'recursive' => -1
));
foreach ($attributes as $attribute) {
$this->Event->Attribute->__afterSaveCorrelation($attribute['Attribute'], false, $event);
}
} else {
$event['Event']['disable_correlation'] = 1;
$this->Event->save($event);
$this->Event->Attribute->purgeCorrelations($id);
}
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('events', 'toggleCorrelation', $id, false, 'Correlation ' . ($event['Event']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
} else {
$this->Session->setFlash('Correlation ' . ($event['Event']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
$this->redirect(array('controller' => 'events', 'action' => 'view', $id));
}
} else {
$this->set('event', $event);
$this->render('ajax/toggle_correlation');
}
}
public function checkPublishedStatus($id) {
$event = $this->Event->fetchEvent($this->Auth->user(), array('metadata' => 1, 'eventid' => $id));
if (empty($event)) {
throw new NotFoundException('Invalid event');
}
return new CakeResponse(array('body'=> h($event[0]['Event']['published']), 'status'=>200));
}
}

View File

@ -101,6 +101,11 @@ class GalaxiesController extends AppController {
$cluster_id = $this->request->data['Galaxy']['target_id'];
$cluster = $this->Galaxy->GalaxyCluster->find('first', array('recursive' => -1, 'conditions' => array('id' => $cluster_id), 'fields' => array('tag_name')));
$this->loadModel('Tag');
$event = $this->Tag->EventTag->Event->fetchEvent($this->Auth->user(), array('eventid' => $event_id, 'metadata' => 1));
if (empty($event)) {
throw new NotFoundException('Invalid event.');
}
$event = $event[0];
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1), $this->Auth->user());
if ($tag_id === false) {
throw new MethodNotAllowedException('Could not attach cluster.');
@ -113,6 +118,10 @@ class GalaxiesController extends AppController {
}
$result = $this->Tag->EventTag->save(array('event_id' => $event_id, 'tag_id' => $tag_id));
if ($result) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Tag->EventTag->Event->save($event);
$this->Session->setFlash('Cluster attached');
$this->redirect($this->referer());
} else {

View File

@ -44,7 +44,7 @@ class GalaxyClustersController extends AppController {
$this->render('ajax/index');
}
}
public function view($id) {
$cluster = $this->GalaxyCluster->find('first', array(
'recursive' => -1,
@ -65,16 +65,16 @@ class GalaxyClustersController extends AppController {
if (!empty($tag)) {
$cluster['GalaxyCluster']['tag_count'] = count($tag['EventTag']);
$cluster['GalaxyCluster']['tag_id'] = $tag['Tag']['id'];
}
}
}
$this->set('cluster', $cluster);
}
public function attachToEvent($event_id, $tag_name) {
$this->loadModel('Event');
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $event_id);
$event = $this->Event->read(array(), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
@ -95,18 +95,22 @@ class GalaxyClustersController extends AppController {
if (empty($existingEventTag)) {
$this->Event->EventTag->create();
$this->Event->EventTag->save(array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id));
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$this->Session->setFlash('Galaxy attached.');
} else {
$this->Session->setFlash('Galaxy already attached.');
}
$this->redirect($this->referer());
}
public function detachFromEvent($event_id, $tag_id) {
$this->loadModel('Event');
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $event_id);
$event = $this->Event->read(array(), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
@ -120,6 +124,10 @@ class GalaxyClustersController extends AppController {
$this->Session->setFlash('Galaxy not attached.');
} else {
$this->Event->EventTag->delete($existingEventTag['EventTag']['id']);
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$this->Session->setFlash('Galaxy successfully detached.');
}
$this->redirect($this->referer());

View File

@ -117,7 +117,6 @@ class WarninglistsController extends AppController {
public function enableWarninglist($id, $enable = false) {
$this->Warninglist->id = $id;
debug($id);
if (!$this->Warninglist->exists()) throw new NotFoundException('Invalid Warninglist.');
// DBMS interoperability: convert boolean false to integer 0 so cakephp doesn't try to insert an empty string into the database
if ($enable === false) $enable = 0;

View File

@ -100,6 +100,33 @@ class FinancialTool {
return true;
}
/**
*
* alternative to bcmod from: http://au2.php.net/manual/en/function.bcmod.php#38474
*
* my_bcmod - get modulus (substitute for bcmod)
* string my_bcmod ( string left_operand, int modulus )
* left_operand can be really big, but be carefull with modulus :(
* by Andrius Baranauskas and Laurynas Butkus :) Vilnius, Lithuania
**/
private function my_bcmod( $x, $y )
{
// how many numbers to take at once? carefull not to exceed (int)
$take = 5;
$mod = '';
do
{
$a = (int)$mod.substr( $x, 0, $take );
$x = substr( $x, $take );
$mod = $a % $y;
}
while ( strlen($x) );
return (int)$mod;
}
// validating using method described on wikipedia @ https://en.wikipedia.org/wiki/International_Bank_Account_Number#Algorithms
public function validateIBAN($iban) {
if (strlen($iban) < 15 || strlen($iban) > 32) return false;
@ -109,7 +136,11 @@ class FinancialTool {
if (is_numeric($temp[$i])) $temp2 .= $temp[$i];
else $temp2 .= ord(strtolower($temp[$i])) - 87;
}
$temp = bcmod($temp2, 97);
if (function_exists('bcmod')) {
$temp = bcmod($temp2, 97);
} else {
$temp = $this->my_bcmod($temp2, 97);
}
return intval($temp)===1 ? true : false;
}

View File

@ -40,7 +40,8 @@ class AppModel extends Model {
18 => false, 19 => false, 20 => false, 25 => false, 27 => false,
32 => false, 33 => true, 38 => true, 39 => true, 40 => false,
42 => false, 44 => false, 45 => false, 49 => true, 50 => false,
51 => false, 52 => false, 55 => true, 56 => true, 57 => true
51 => false, 52 => false, 55 => true, 56 => true, 57 => true,
58 => false
)
)
);
@ -537,6 +538,10 @@ class AppModel extends Model {
$sqlArray[] = 'ALTER TABLE `threads` DROP `org`;';
$sqlArray[] = 'ALTER TABLE `users` DROP `org`;';
break;
case '2.4.58':
$sqlArray[] = "ALTER TABLE `events` ADD `disable_correlation` tinyint(1) NOT NULL DEFAULT 0;";
$sqlArray[] = "ALTER TABLE `attributes` ADD `disable_correlation` tinyint(1) NOT NULL DEFAULT 0;";
break;
default:
return false;
break;

View File

@ -1258,11 +1258,14 @@ class Attribute extends AppModel {
if (!$event) {
$event = $this->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.distribution', 'Event.id', 'Event.info', 'Event.org_id', 'Event.date', 'Event.sharing_group_id'),
'fields' => array('Event.distribution', 'Event.id', 'Event.info', 'Event.org_id', 'Event.date', 'Event.sharing_group_id', 'Event.disable_correlation'),
'conditions' => array('id' => $a['event_id']),
'order' => array(),
));
}
if ($event['Event']['disable_correlation']) {
return true;
}
$this->Correlation = ClassRegistry::init('Correlation');
$correlatingValues = array($a['value1']);
if (!empty($a['value2'])) $correlatingValues[] = $a['value2'];
@ -1275,6 +1278,8 @@ class Attribute extends AppModel {
'Attribute.value2' => $cV
),
'Attribute.type !=' => $this->nonCorrelatingTypes,
'Attribute.disable_correlation' => 0,
'Event.disable_correlation' => 0
),
'Attribute.deleted' => 0
),
@ -1668,11 +1673,15 @@ class Attribute extends AppModel {
return $export->export($attributes, $orgs, $valueField, $whitelist, $instanceString);
}
public function generateCorrelation($jobId = false, $startPercentage = 0) {
public function generateCorrelation($jobId = false, $startPercentage = 0, $eventId = false, $attributeId = false) {
$this->Correlation = ClassRegistry::init('Correlation');
$this->Correlation->deleteAll(array('id !=' => 0), false);
$this->purgeCorrelations($eventId);
// get all attributes..
$eventIds = $this->Event->find('list', array('recursive' => -1, 'fields' => array('Event.id')));
if (!$eventId) {
$eventIds = $this->Event->find('list', array('recursive' => -1, 'fields' => array('Event.id')));
} else {
$eventIds = array($eventId);
}
$attributeCount = 0;
if (Configure::read('MISP.background_jobs') && $jobId) {
$this->Job = ClassRegistry::init('Job');
@ -1681,16 +1690,24 @@ class Attribute extends AppModel {
}
foreach (array_values($eventIds) as $j => $id) {
if ($jobId && Configure::read('MISP.background_jobs')) {
$this->Job->saveField('message', 'Correlating Event ' . $id);
if ($attributeId) {
$this->Job->saveField('message', 'Correlating Attribute ' . $attributeId);
} else {
$this->Job->saveField('message', 'Correlating Event ' . $id);
}
$this->Job->saveField('progress', ($startPercentage + ($j / $eventCount * (100 - $startPercentage))));
}
$event = $this->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.distribution', 'Event.id', 'Event.info', 'Event.org_id', 'Event.date', 'Event.sharing_group_id'),
'fields' => array('Event.distribution', 'Event.id', 'Event.info', 'Event.org_id', 'Event.date', 'Event.sharing_group_id', 'Event.disable_correlation'),
'conditions' => array('id' => $id),
'order' => array()
));
$attributes = $this->find('all', array('recursive' => -1, 'conditions' => array('Attribute.event_id' => $id, 'Attribute.deleted' => 0), 'order' => array()));
$attributeConditions = array('Attribute.event_id' => $id, 'Attribute.deleted' => 0);
if ($attributeId) {
$attributeConditions['Attribute.id'] = $attributeId;
}
$attributes = $this->find('all', array('recursive' => -1, 'conditions' => $attributeConditions, 'order' => array()));
foreach ($attributes as $k => $attribute) {
$this->__afterSaveCorrelation($attribute['Attribute'], true, $event);
$attributeCount++;
@ -1700,6 +1717,23 @@ class Attribute extends AppModel {
return $attributeCount;
}
public function purgeCorrelations($eventId = false, $attributeId = false) {
if (!$eventId) {
$this->query('TRUNCATE TABLE correlations;');
} else if (!$attributeId) {
$this->Correlation = ClassRegistry::init('Correlation');
$this->Correlation->deleteAll(array('OR' => array(
'Correlation.1_event_id' => $eventId,
'Correlation.event_id' => $eventId))
);
} else {
$this->Correlation->deleteAll(array('OR' => array(
'Correlation.1_attribute_id' => $attributeId,
'Correlation.attribute_id' => $attributeId))
);
}
}
public function reportValidationIssuesAttributes($eventId) {
$conditions = array();
if ($eventId && is_numeric($eventId)) $conditions = array('event_id' => $eventId);

View File

@ -1252,8 +1252,8 @@ class Event extends AppModel {
// $conditions['AND'][] = array('Event.published =' => 1);
// do not expose all the data ...
$fields = array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.date', 'Event.threat_level_id', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.user_id', 'Event.locked', 'Event.publish_timestamp', 'Event.sharing_group_id');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp', 'Attribute.comment', 'Attribute.sharing_group_id', 'Attribute.deleted');
$fields = array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.date', 'Event.threat_level_id', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.user_id', 'Event.locked', 'Event.publish_timestamp', 'Event.sharing_group_id', 'Event.disable_correlation');
$fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp', 'Attribute.comment', 'Attribute.sharing_group_id', 'Attribute.deleted', 'Attribute.disable_correlation');
$fieldsShadowAtt = array('ShadowAttribute.id', 'ShadowAttribute.type', 'ShadowAttribute.category', 'ShadowAttribute.value', 'ShadowAttribute.to_ids', 'ShadowAttribute.uuid', 'ShadowAttribute.event_uuid', 'ShadowAttribute.event_id', 'ShadowAttribute.old_id', 'ShadowAttribute.comment', 'ShadowAttribute.org_id', 'ShadowAttribute.proposal_to_delete', 'ShadowAttribute.timestamp');
$fieldsOrg = array('id', 'name', 'uuid');
$fieldsServer = array('id', 'url', 'name');

View File

@ -697,7 +697,35 @@ class Server extends AppModel {
'test' => 'testBool',
'type' => 'boolean',
'null' => false
)
),
'completely_disable_correlation' => array(
'level' => 0,
'description' => '*WARNING* This setting will completely disable the correlation on this instance and remove any existing saved correlations. Enabling this will trigger a full recorrelation of all data which is an extremely long and costly procedure. Only enable this if you know what you\'re doing.',
'value' => false,
'errorMessage' => '',
'test' => 'testBoolFalse',
'type' => 'boolean',
'null' => true,
'afterHook' => 'correlationAfterHook',
),
'allow_disabling_correlation' => array(
'level' => 0,
'description' => '*WARNING* This setting will give event creators the possibility to disable the correlation of individual events / attributes that they have created.',
'value' => false,
'errorMessage' => '',
'test' => 'testBoolFalse',
'type' => 'boolean',
'null' => true
),
'showCorrelationsOnIndex' => array(
'level' => 1,
'description' => 'When enabled, the number of correlations visible to the currently logged in user will be visible on the event index UI. This comes at a performance cost but can be very useful to see correlating events at a glance.',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
),
),
'GnuPG' => array(
'branch' => 1,
@ -2099,6 +2127,17 @@ class Server extends AppModel {
return true;
}
public function testBoolFalse($value) {
if (!$this->testBool($value)) {
return $this->testBool($value);
}
if ($value !== false) {
return 'It is highly recommended that this setting is disabled. Make sure you understand the impact of having this setting turned on.';
} else {
return true;
}
}
public function testSalt($value) {
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
if (strlen($value) < 32) return 'The salt has to be an at least 32 byte long string.';
@ -2214,6 +2253,45 @@ class Server extends AppModel {
return true;
}
public function correlationAfterHook($setting, $value) {
if (!Configure::read('MISP.background_jobs')) {
$this->Attribute = ClassRegistry::init('Attribute');
if ($value) {
$k = $this->Attribute->purgeCorrelations();
} else {
$k = $this->Attribute->generateCorrelation();
}
} else {
$job = ClassRegistry::init('Job');
$job->create();
if ($value == true) {
$jobType = 'jobPurgeCorrelation';
$jobTypeText = 'purge correlations';
} else {
$jobType = 'jobGenerateCorrelation';
$jobTypeText = 'generate correlation';
}
$data = array(
'worker' => 'default',
'job_type' => $jobTypeText,
'job_input' => 'All attributes',
'status' => 0,
'retries' => 0,
'org' => 'ADMIN',
'message' => 'Job created.',
);
$job->save($data);
$jobId = $job->id;
$process_id = CakeResque::enqueue(
'default',
'AdminShell',
array($jobType, $jobId),
true
);
$job->saveField('process_id', $process_id);
}
}
public function ipLogBeforeHook($setting, $value) {
if ($setting == 'MISP.log_client_ip') {
if ($value == true) {

View File

@ -0,0 +1,33 @@
<div class="confirmation">
<?php
echo $this->Form->create('Attribute', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/attributes/toggleCorrelation/' . $attribute['Attribute']['id']));
$extraTitle = "";
?>
<legend>Toggle Correlation <?php echo $attribute['Event']['disable_correlation'] ? 'on' : 'off'?></legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<p>
<?php
if ($attribute['Attribute']['disable_correlation']) {
echo 'Re-enable the correlation for this attribute.';
} else {
echo 'This will remove all correlations that already exist for this attribute and prevents any attributes to be related as long as this setting is disabled. Make sure you understand the downasides of disabling correlations.';
}
?>
</p>
<table>
<tr>
<td style="vertical-align:top">
<span id="PromptYesButton" class="btn btn-primary" onClick="submitPublish();">Yes</span>
</td>
<td style="width:540px;">
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();">No</span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
</div>

View File

@ -1,6 +1,7 @@
<?php
$mayModify = ($isSiteAdmin || ($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
$mayChangeCorrelation = !Configure::read('MISP.completely_disable_correlation') && ($isSiteAdmin || ($mayModify && Configure::read('MISP.allow_disabling_correlation')));
$possibleAction = 'Proposal';
if ($mayModify) $possibleAction = 'Attribute';
$all = false;
@ -169,6 +170,13 @@
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
<th><?php echo $this->Paginator->sort('comment');?></th>
<?php
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
?>
<th>Correlate</th>
<?php
endif;
?>
<th>Related Events</th>
<th title="<?php echo $attrDescriptions['signature']['desc'];?>"><?php echo $this->Paginator->sort('to_ids', 'IDS');?></th>
<th title="<?php echo $attrDescriptions['distribution']['desc'];?>"><?php echo $this->Paginator->sort('distribution');?></th>
@ -348,6 +356,19 @@
<?php echo nl2br(h($object['comment'])); ?>&nbsp;
</div>
</td>
<?php
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
if ($object['objectType'] == 0):
?>
<td class="short" style="padding-top:3px;">
<input class="correlation-toggle" type="checkbox" data-attribute-id="<?php echo h($object['id']); ?>" <?php echo $object['disable_correlation'] ? '' : 'checked'; ?>>
</td>
<?php
else:
echo '&nbsp;';
endif;
endif;
?>
<td class="shortish <?php echo $extra; ?>">
<ul class="inline" style="margin:0px;">
<?php
@ -547,7 +568,8 @@ attributes or the appropriate distribution level. If you think there is a mistak
$(document).ready(function(){
setContextFields();
popoverStartup();
$('input:checkbox').removeAttr('checked');
$('.select_attribute').removeAttr('checked');
$('.select_proposal').removeAttr('checked');
$('.mass-select').hide();
$('.mass-proposal-select').hide();
$('.select_attribute').click(function(e) {
@ -572,6 +594,11 @@ attributes or the appropriate distribution level. If you think there is a mistak
attributeListAnyAttributeCheckBoxesChecked();
attributeListAnyProposalCheckBoxesChecked();
});
$('.correlation-toggle').click(function() {
var attribute_id = $(this).data('attribute-id');
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
return false;
});
});
</script>
<?php

View File

@ -3,6 +3,9 @@
<?php
switch ($menuList) {
case 'event':
?>
<div id="hiddenSideMenuData" class="hidden" data-event-id="<?php echo isset($event['Event']['id']) ? $event['Event']['id'] : 0; ?>"></div>
<?php
if ($menuItem === 'addAttribute' ||
$menuItem === 'addAttachment' ||
$menuItem === 'addIOC' ||
@ -49,8 +52,8 @@
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
if (isset($event['Event']['published']) && $event['Event']['published']) $exportButtons = "";
?>
<li<?php echo $publishButtons; ?> class="publishButtons"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
<li<?php echo $publishButtons; ?> class="publishButtons"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
<?php if (Configure::read('MISP.delegation')):?>
<?php if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))): ?>
<li id='lidelegateEvent'><a href="#" onClick="delegatePopup('<?php echo h($event['Event']['id']); ?>');">Delegate Publishing</a></li>
@ -321,7 +324,7 @@
case 'news': ?>
<li id='liindex'><a href="<?php echo $baseurl;?>/news/index">View News</a></li>
<?php
if ($isSiteAdmin):
if ($isSiteAdmin):
?>
<li id='liadd'><a href="<?php echo $baseurl;?>/news/add">Add News Item</a></li>
<?php if ($menuItem === 'edit'): ?>
@ -329,25 +332,25 @@
<?php endif;
endif;
break;
case 'galaxies':
case 'galaxies':
?>
<li id='liindex'><a href="<?php echo $baseurl;?>/galaxies/index">List Galaxies</a></li>
<?php
if ($isSiteAdmin):
if ($isSiteAdmin):
?>
<li><?php echo $this->Form->postLink('Update Galaxies', array('controller' => 'galaxies', 'action' => 'update'), null, __('Are you sure you want to reimport all galaxies from the submodule?')); ?></li>
<?php
endif;
if ($menuItem === 'view'):
<?php
endif;
if ($menuItem === 'view'):
?>
<li class="active"><a href="#">View Galaxy</a></li>
<?php
endif;
if ($menuItem === 'view_cluster'):
if ($menuItem === 'view_cluster'):
?>
<li class="active"><a href="#">View Cluster</a></li>
<?php
<?php
endif;
break;
}

View File

@ -0,0 +1,33 @@
<div class="confirmation">
<?php
echo $this->Form->create('Event', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/events/toggleCorrelation/' . $event['Event']['id']));
$extraTitle = "";
?>
<legend>Toggle Correlation <?php echo $event['Event']['disable_correlation'] ? 'on' : 'off'?></legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<p>
<?php
if ($event['Event']['disable_correlation']) {
echo 'Re-enable the correlation for this event. This will automatically recorrelate all contained attributes.';
} else {
echo 'This will remove all correlations that already exist for the event and prevent any events to be related via correlations as long as this setting is disabled. Make sure you understand the downasides of disabling correlations.';
}
?>
</p>
<table>
<tr>
<td style="vertical-align:top">
<span id="PromptYesButton" class="btn btn-primary" onClick="submitPublish();">Yes</span>
</td>
<td style="width:540px;">
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();">No</span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
</div>

View File

@ -158,8 +158,11 @@
<?php echo nl2br(h($event['Event']['info'])); ?>
&nbsp;
</dd>
<dt class="<?php echo ($event['Event']['published'] == 0) ? (($isAclPublish && $me['org_id'] == $event['Event']['orgc_id']) ? 'background-red bold' : 'bold') : 'bold'; ?>">Published</dt>
<dd class="<?php echo ($event['Event']['published'] == 0) ? (($isAclPublish && $me['org_id'] == $event['Event']['orgc_id']) ? 'background-red bold' : 'red bold') : 'green bold'; ?>"><?php echo ($event['Event']['published'] == 0) ? 'No' : 'Yes'; ?></dd>
<dt class="hidden"></dt><dd class="hidden"></dd>
<dt class="background-red bold not-published <?php echo ($event['Event']['published'] == 0) ? '' : 'hidden'; ?>">Published</dt>
<dd class="background-red bold not-published <?php echo ($event['Event']['published'] == 0) ? '' : 'hidden'; ?>">No</dd>
<dt class="bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>">Published</dt>
<dd class="green bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>">Yes</dd>
<?php if (Configure::read('Plugin.Sightings_enable') !== false): ?>
<dt>Sightings</dt>
<dd style="word-wrap: break-word;">
@ -180,6 +183,28 @@
<dt class="background-red bold">Delegation request</dt>
<dd class="background-red bold"><?php echo h($subject);?> requested that <?php echo h($target)?> take over this event. (<a href="#" style="color:white;" onClick="genericPopup('<?php echo $baseurl;?>/eventDelegations/view/<?php echo h($delegationRequest['EventDelegation']['id']);?>', '#confirmation_box');">View request details</a>)</dd>
<?php endif;?>
<?php
if (!Configure::read('MISP.completely_disable_correlation')):
?>
<dt <?php echo $event['Event']['disable_correlation'] ? 'class="background-red bold"' : '';?>>Correlation</dt>
<dd <?php echo $event['Event']['disable_correlation'] ? 'class="background-red bold"' : '';?>>
<?php
if ($mayModify):
if ($event['Event']['disable_correlation']):
?>
Disabled (<a onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'events', 'toggleCorrelation', '', '#confirmation_box');" style="color:white;cursor:pointer;" style="font-weight:normal;">enable</a>)
<?php
else:
?>
Enabled (<a onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'events', 'toggleCorrelation', '', '#confirmation_box');" style="cursor:pointer;" style="font-weight:normal;">disable</a>)
<?php
endif;
endif;
?>
</dd>
<?php
endif;
?>
</dl>
</div>
<div class="related span4">

View File

@ -442,6 +442,9 @@ function handleAjaxEditResponse(data, name, type, id, field, event) {
if (type == 'ShadowAttribute') {
updateIndex(event, 'event');
}
if ('undefined' != responseArray['check_publish']) {
checkAndSetPublishedInfo();
}
}
function handleGenericAjaxResponse(data) {
@ -452,6 +455,9 @@ function handleGenericAjaxResponse(data) {
}
if (responseArray.saved) {
showMessage('success', responseArray.success);
if ('undefined' != responseArray['check_publish']) {
checkAndSetPublishedInfo();
}
return true;
} else {
showMessage('fail', responseArray.errors);
@ -999,13 +1005,14 @@ function templateElementFileCategoryChange(category) {
}
}
function getPopup(id, context, target, admin) {
function getPopup(id, context, target, admin, popupType) {
$("#gray_out").fadeIn();
var url = "";
if (typeof admin !== 'undefined') url+= "/admin";
if (typeof admin !== 'undefined' && admin != '') url+= "/admin";
if (context != '') url += "/" + context;
if (target != '') url += "/" + target;
if (id != '') url += "/" + id;
if (popupType == '' || typeof popupType == 'undefined') popupType = '#popover_form';
$.ajax({
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
@ -1014,8 +1021,8 @@ function getPopup(id, context, target, admin) {
cache: false,
success:function (data, textStatus) {
$(".loading").hide();
$("#popover_form").html(data);
$("#popover_form").fadeIn();
$(popupType).html(data);
$(popupType).fadeIn();
},
url: url,
//url:"/templates/templateChoices/" + id,
@ -2711,3 +2718,16 @@ function quickSubmitGalaxyForm(event_id, cluster_id) {
$('#GalaxySelectClusterForm').submit();
return false;
}
function checkAndSetPublishedInfo() {
var id = $('#hiddenSideMenuData').data('event-id');
$.get( "/events/checkPublishedStatus/" + id, function(data) {
if (data == 1) {
$('.published').show();
$('.not-published').hide();
} else {
$('.published').hide();
$('.not-published').show();
}
});
}