Merge remote-tracking branch 'origin/develop' into tomking2_feature/propagate_tag_deletion

pull/8568/head
Sami Mokaddem 2022-09-01 11:07:35 +02:00
commit 646d921d67
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
395 changed files with 105208 additions and 24130 deletions

2
.gitignore vendored
View File

@ -50,6 +50,8 @@ app/Lib/EventWarning/Custom/*
!/app/files/misp-objects/*
!/app/files/misp-decaying-models
!/app/files/misp-decaying-models/*
!/app/files/misp-workflow-blueprints
!/app/files/misp-workflow-blueprints/*
/app/files/scripts/*.pyc
/app/files/scripts/*.py~
/app/files/scripts/__pycache__

3
.gitmodules vendored
View File

@ -48,3 +48,6 @@
[submodule "app/files/scripts/python-maec"]
path = app/files/scripts/python-maec
url = https://github.com/MAECProject/python-maec
[submodule "app/files/misp-workflow-blueprints"]
path = app/files/misp-workflow-blueprints
url = https://github.com/MISP/misp-workflow-blueprints

View File

@ -3593,6 +3593,7 @@ x86_64-debian-buster
x86_64-ubuntu-bionic
x86_64-ubuntu-focal
x86_64-ubuntu-hirsute
x86_64-ubuntu-jammy
x86_64-kali-2021.4
x86_64-kali-2022.1
x86_64-kali-2022.2
@ -3640,6 +3641,12 @@ if [[ "${FLAVOUR}" == "ubuntu" ]]; then
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
installSupported PHP="7.4" && exit || exit
fi
if [[ "${RELEASE}" == "22.04" ]]; then
echo "Install on Ubuntu 22.04 LTS fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
upgradeToPHP74
installSupported PHP="7.4" && exit || exit
fi
if [[ "${RELEASE}" == "18.10" ]]; then
echo "Install on Ubuntu 18.10 partially supported, bye."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"

View File

@ -1,5 +1,5 @@
; Generated by RHash v1.3.9 on 2021-12-25 at 14:54.47
; Generated by RHash v1.4.2 on 2022-05-23 at 12:45.34
; Written by Kravchenko Aleksey (Akademgorodok) - http://rhash.sf.net/
;
; 161158 14:54.46 2021-12-25 INSTALL.sh
INSTALL.sh A1EEC205071442B2C9B145E7B5A054FF24728EF4 DAF55446860994E3AE8589FB6F8EE33B015DBC454ADFC8D7F3E0B2F28AA8BBBD 4F6F43B200D0F9B35C53186B4AD26A1CCFEBB6FC961B19369E3D13A053C046340B6BF1673D14793B0FE7233ECA86993D D38C7FAF648C60DCEA4D9C64AB5EB4AE262B3F1625106670DC837D1AEC9AB302BCB21811CEE5B14845D841BCDCBF420FA800BDCDCA44B5F58196667022BBD94D
; 160126 12:45.34 2022-05-23 INSTALL.sh
INSTALL.sh 4296D40B11B3002DF3FDFD69A508ED5ECACB8C13 D32E5A4B0F37F4C937CD4F85927E998D917BCBE89E4E0E864FFD7EA09E29ADEF BD093D8018C351E3D3722646E269C4B60E6DA19F42150338CE6FD72FEE293B8B89AA69D48A84B19D3EFDDAE25EC9E646 ECACC3071E130058C3DDECC86E1CBF27DD4F11389D10F43B14293B1915F7A24F02D0DA51E299706A38C00F2D2A7505B0FE46E33B705E53594383CE65461F2B08

View File

@ -1 +1 @@
c14654d71a2a369fb5852987b69ecd7774b7111d INSTALL.sh
4296d40b11b3002df3fdfd69a508ed5ecacb8c13 INSTALL.sh

View File

@ -1 +1 @@
621dd7fc21cc25631248a685a00d506a3aa1c2e29c11539870cf4efde499dcc9 INSTALL.sh
d32e5a4b0f37f4c937cd4f85927e998d917bcbe89e4e0e864ffd7ea09e29adef INSTALL.sh

View File

@ -1 +1 @@
f348d5c019fea3c339b6076596ede2e55ea173cd1c25158d7e3d2cbb4d2d90950ac84ab3597bbaa50f199fd9850831db INSTALL.sh
bd093d8018c351e3d3722646e269c4b60e6da19f42150338ce6fd72fee293b8b89aa69d48a84b19d3efddae25ec9e646 INSTALL.sh

View File

@ -1 +1 @@
499e82451509739bbd5117a942f8a39f847310301c9e4dc0428eaa31560ff6b08bafa958fd22c01a3241afad7fcfedfeb7ae88d25f5fce299e921b49a4d644c1 INSTALL.sh
ecacc3071e130058c3ddecc86e1cbf27dd4f11389d10f43b14293b1915f7a24f02d0da51e299706a38c00f2d2a7505b0fe46e33b705e53594383ce65461f2b08 INSTALL.sh

View File

@ -849,6 +849,7 @@ x86_64-debian-buster
x86_64-ubuntu-bionic
x86_64-ubuntu-focal
x86_64-ubuntu-hirsute
x86_64-ubuntu-jammy
x86_64-kali-2021.4
x86_64-kali-2022.1
x86_64-kali-2022.2
@ -896,6 +897,12 @@ if [[ "${FLAVOUR}" == "ubuntu" ]]; then
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
installSupported PHP="7.4" && exit || exit
fi
if [[ "${RELEASE}" == "22.04" ]]; then
echo "Install on Ubuntu 22.04 LTS fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
upgradeToPHP74
installSupported PHP="7.4" && exit || exit
fi
if [[ "${RELEASE}" == "18.10" ]]; then
echo "Install on Ubuntu 18.10 partially supported, bye."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"

2
PyMISP

@ -1 +1 @@
Subproject commit b1892efb6a078d1370cee51c9103f3a591c628d2
Subproject commit 3ca8717e6c7780718cd20328040799261a39a281

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":158}
{"major":2, "minor":4, "hotfix":161}

View File

@ -71,6 +71,7 @@ $config = array(
'enableOrgBlocklisting' => true,
'log_client_ip' => false,
'log_auth' => false,
'store_api_access_time' => false,
'disableUserSelfManagement' => false,
'disable_user_login_change' => false,
'disable_user_password_change' => false,

View File

@ -7,18 +7,35 @@ App::uses('JsonTool', 'Tools');
/**
* @property Server $Server
* @property Feed $Feed
* @property Warninglist $warninglist
* @property AdminSetting $AdminSetting
* @property Taxonomy $Taxonomy
* @property Warninglist $Warninglist
* @property Attribute $Attribute
* @property Job $Job
*/
class AdminShell extends AppShell
{
public $uses = array('Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Allowedlist', 'Server', 'Organisation', 'AdminSetting', 'Galaxy', 'Taxonomy', 'Warninglist', 'Noticelist', 'ObjectTemplate', 'Bruteforce', 'Role', 'Feed', 'SharingGroupBlueprint');
public $uses = [
'Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Allowedlist', 'Server', 'Organisation',
'AdminSetting', 'Galaxy', 'Taxonomy', 'Warninglist', 'Noticelist', 'ObjectTemplate', 'Bruteforce',
'Role', 'Feed', 'SharingGroupBlueprint', 'Correlation', 'OverCorrelatingValue'
];
public $tasks = ['ConfigLoad'];
public function getOptionParser()
{
$parser = parent::getOptionParser();
$parser->addSubcommand('updateJSON', array(
'help' => __('Update the JSON definitions of MISP.'),
));
$parser->addSubcommand('updateWarningLists', array(
'help' => __('Update the JSON definition of warninglists.'),
));
$parser->addSubcommand('updateTaxonomies', array(
'help' => __('Update the JSON definition of taxonomies.'),
));
$parser->addSubcommand('setSetting', [
'help' => __('Set setting in PHP config file.'),
'parser' => [
@ -94,30 +111,29 @@ class AdminShell extends AppShell
}
$jobId = $this->args[0];
$this->loadModel('Job');
$this->Job->id = $jobId;
$this->loadModel('Attribute');
$this->Attribute->generateCorrelation($jobId, 0);
$this->Job->saveField('progress', 100);
$this->Job->saveField('message', 'Job done.');
$this->Job->saveField('status', 4);
$this->Attribute->generateCorrelation($jobId);
}
public function jobGenerateOccurrences()
{
$this->ConfigLoad->execute();
if (empty($this->args[0])) {
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Generate over-correlation occurrences'] . PHP_EOL);
}
$jobId = $this->args[0];
$this->OverCorrelatingValue->generateOccurrences($jobId);
}
public function jobPurgeCorrelation()
{
$this->ConfigLoad->execute();
if (empty($this->args[0])) {
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Purge correlation'] . PHP_EOL);
}
$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);
$this->Job->saveStatus($jobId);
}
public function jobGenerateShadowAttributeCorrelation()
@ -278,22 +294,27 @@ class AdminShell extends AppShell
public function updateTaxonomies()
{
$this->ConfigLoad->execute();
$result = $this->Taxonomy->update();
$successes = count(!empty($result['success']) ? $result['success'] : []);
$fails = count(!empty($result['fails']) ? $result['fails'] : []);
$message = '';
if ($successes == 0 && $fails == 0) {
$message = __('All taxonomies are up to date already.');
} elseif ($successes == 0 && $fails > 0) {
$successes = empty($result['success']) ? 0 : count($result['success']);
$fails = empty($result['fails']) ? 0 : count($result['fails']);
if ($successes === 0 && $fails === 0) {
$message = __('All taxonomies are up to date already.');
} elseif ($successes === 0 && $fails > 0) {
$message = __('Could not update any of the taxonomies.');
} elseif ($successes > 0 ) {
} else {
$message = __('Successfully updated %s taxonomies.', $successes);
if ($fails != 0) {
if ($fails !== 0) {
$message .= __(' However, could not update %s taxonomies.', $fails);
}
}
echo $message . PHP_EOL;
$this->out($message);
if ($fails) {
$this->out(__('Fails:'));
foreach ($result['fails'] as $fail) {
$this->out("{$fail['namespace']}: {$fail['fail']}");
}
}
}
public function enableTaxonomyTags()
@ -312,11 +333,16 @@ class AdminShell extends AppShell
public function updateWarningLists()
{
$this->ConfigLoad->execute();
$result = $this->Warninglist->update();
$success = count($result['success']);
$fails = count($result['fails']);
echo "$success warninglists updated, $fails fails" . PHP_EOL;
$this->out("$success warninglists updated, $fails fails");
if ($fails) {
$this->out(__('Fails:'));
foreach ($result['fails'] as $fail) {
$this->out("{$fail['name']}: {$fail['fail']}");
}
}
}
public function updateNoticeLists()
@ -1178,4 +1204,38 @@ class AdminShell extends AppShell
);
$this->out($message);
}
public function truncateTable()
{
$this->ConfigLoad->execute();
if (!isset($this->args[0])) {
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Truncate table correlation'] . PHP_EOL);
}
$userId = $this->args[0];
if ($userId) {
$user = $this->User->getAuthUser($userId);
} else {
$user = [
'id' => 0,
'email' => 'SYSTEM',
'Organisation' => [
'name' => 'SYSTEM'
]
];
}
if (empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Truncate table correlation'] . PHP_EOL);
}
if (!empty($this->args[2])) {
$jobId = $this->args[2];
}
$table = trim($this->args[1]);
$this->Correlation->truncate($user, $table);
if ($jobId) {
$this->Job->id = $jobId;
$this->Job->saveField('progress', 100);
$this->Job->saveField('date_modified', date("Y-m-d H:i:s"));
$this->Job->saveField('message', __('Database truncated: ' . $table));
}
}
}

View File

@ -10,6 +10,7 @@ require_once 'AppShell.php';
* @property Job $Job
* @property Tag $Tag
* @property Server $Server
* @property Correlation $Correlation
*/
class EventShell extends AppShell
{
@ -39,11 +40,17 @@ class EventShell extends AppShell
'event_id' => ['help' => __('Event ID'), 'required' => true],
'user_id' => ['help' => __('User ID'), 'required' => true],
],
'options' => [
'send' => ['help' => __('Send email to given user'), 'boolean' => true],
],
],
]);
$parser->addSubcommand('duplicateTags', [
'help' => __('Show duplicate tags'),
]);
$parser->addSubcommand('generateTopCorrelations', [
'help' => __('Generate top correlations'),
]);
$parser->addSubcommand('mergeTags', [
'help' => __('Merge tags'),
'parser' => [
@ -603,6 +610,7 @@ class EventShell extends AppShell
public function testEventNotificationEmail()
{
list($eventId, $userId) = $this->args;
$send = $this->param('send');
$user = $this->getUser($userId);
$eventForUser = $this->Event->fetchEvent($user, [
@ -622,10 +630,16 @@ class EventShell extends AppShell
App::uses('SendEmail', 'Tools');
App::uses('GpgTool', 'Tools');
$sendEmail = new SendEmail(GpgTool::initializeGpg());
$sendEmail->setTransport('Debug');
if (!$send) {
$sendEmail->setTransport('Debug');
}
$result = $sendEmail->sendToUser(['User' => $user], null, $emailTemplate);
echo $result['contents']['headers'] . "\n\n" . $result['contents']['message'] . "\n";
if ($send) {
var_dump($result);
} else {
echo $result['contents']['headers'] . "\n\n" . $result['contents']['message'] . "\n";
}
}
/**
@ -644,17 +658,20 @@ class EventShell extends AppShell
public function generateTopCorrelations()
{
$this->ConfigLoad->execute();
$jobId = $this->args[0];
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 1;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Generating top correlations list.');
$this->Job->save($job);
$result = $this->Correlation->generateTopCorrelations($jobId);
$job['Job']['progress'] = 100;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Job done.');
$this->Job->save($job);
$jobId = $this->args[0] ?? null;
if ($jobId) {
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 1;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Generating top correlations list.');
$this->Job->save($job);
}
$this->Correlation->generateTopCorrelations($jobId);
if ($jobId) {
$job['Job']['progress'] = 100;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Job done.');
$this->Job->save($job);
}
}
}

View File

@ -52,6 +52,55 @@ class Ls22Shell extends AppShell
),
),
]);
$parser->addSubcommand('checkSyncConnections', [
'help' => __('Check the given sync connection(s) for the given server(s).'),
'parser' => array(
'options' => array(
'instances' => [
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
'short' => 'i',
'required' => true
],
'misp_url_filter' => [
'help' => 'The url of the instance to execute changes on. If not set, all are updated.',
'short' => 'm',
'required' => false
],
'synced_misp_url_filter' => [
'help' => 'The sync connection to modify on each valid instance (as selected by the misp_url_filter). If not set, all sync connections on the selected instances will be updated.',
'short' => 's',
'required' => false
]
),
),
]);
$parser->addSubcommand('modifySyncConnection', [
'help' => __('Modify sync connection(s).'),
'parser' => array(
'options' => array(
'instances' => [
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
'short' => 'i',
'required' => true
],
'misp_url_filter' => [
'help' => 'The url of the instance to execute changes on. If not set, all are updated.',
'short' => 'm',
'required' => false
],
'synced_misp_url_filter' => [
'help' => 'The sync connection to modify on each valid instance (as selected by the misp_url_filter). If not set, all sync connections on the selected instances will be updated.',
'short' => 's',
'required' => false
],
'json' => [
'help' => 'JSON delta to push (such as \'{"push": 1}\').',
'short' => 'j',
'required' => true
]
),
),
]);
$parser->addSubcommand('addWarninglist', [
'help' => __('Inject warninglist'),
'parser' => array(
@ -104,6 +153,11 @@ class Ls22Shell extends AppShell
'help' => 'Upper bound of the date. Accepts timestamp or date distance (such as 1d or 5h). Defaults to unbounded.',
'short' => 't',
'required' => false
],
'org' => [
'help' => 'Name the org that should be evaluated. If not set, all will be included.',
'short' => 'o',
'required' => false
]
),
),
@ -111,6 +165,103 @@ class Ls22Shell extends AppShell
return $parser;
}
public function checkSyncConnections()
{
$this->__getInstances($this->param('instances'));
$results = [];
$instanceFilter = $this->param('misp_url_filter');
$syncedInstanceFilter = $this->param('synced_misp_url_filter');
foreach ($this->__servers as $server) {
if (!empty($instanceFilter) && strtolower(trim($server['Server']['url'])) !== strtolower(trim($instanceFilter))) {
continue;
}
$HttpSocket = $this->Server->setupHttpSocket($server, null);
$request = $this->Server->setupSyncRequest($server, 'Server');
$start_time = microtime(true);
$response = $HttpSocket->get($server['Server']['url'] . '/servers/index', false, $request);
$baseline = round((microtime(true) - $start_time) * 1000);
if (!$response->isOk()) {
$this->out($server['Server']['url'] . ': ' . '<error>Connection or auth failed</error>', 1, Shell::NORMAL);
continue;
}
$synced_servers = json_decode($response->body, true);
foreach ($synced_servers as $synced_server) {
$success = false;
if (empty($syncedInstanceFilter) || strtolower($synced_server['Server']['url']) === strtolower($syncedInstanceFilter)) {
$start_time = microtime(true);
$response = $HttpSocket->get($server['Server']['url'] . '/servers/testConnection/' . $synced_server['Server']['id'], '{}', $request);
$execution_time = round((microtime(true) - $start_time) * 1000) - $baseline;
if ($response->isOk()) {
$success = true;
}
$this->out(
sprintf(
'%s connection to %s: %s (%sms)',
$server['Server']['url'],
$synced_server['Server']['url'],
sprintf(
'<%s>%s</%s>',
$success ? 'info' : 'error',
$success ? 'Success' : 'Failed',
$success ? 'info' : 'error'
),
$execution_time
),
1,
Shell::NORMAL
);
}
}
}
}
public function modifySyncConnection()
{
$this->__getInstances($this->param('instances'));
$results = [];
$instanceFilter = $this->param('misp_url_filter');
$syncedInstanceFilter = $this->param('synced_misp_url_filter');
$json = $this->param('json');
foreach ($this->__servers as $server) {
if (!empty($instanceFilter) && strtolower(trim($server['Server']['url'])) !== strtolower(trim($instanceFilter))) {
continue;
}
$HttpSocket = $this->Server->setupHttpSocket($server, null);
$request = $this->Server->setupSyncRequest($server, 'Server');
$response = $HttpSocket->get($server['Server']['url'] . '/servers/index', false, $request);
if (!$response->isOk()) {
$this->out($server['Server']['url'] . ': ' . '<error>Connection or auth failed</error>', 1, Shell::NORMAL);
}
$synced_servers = json_decode($response->body, true);
$success = false;
foreach ($synced_servers as $synced_server) {
if (empty($syncedInstanceFilter) || strtolower($synced_server['Server']['url']) === strtolower($syncedInstanceFilter)) {
debug($json);
$response = $HttpSocket->post($server['Server']['url'] . '/servers/edit/' . $synced_server['Server']['id'], $json, $request);
debug($response->body);
if ($response->isOk()) {
$success = true;
}
$this->out(
sprintf(
'%s connection to %s: %s',
$server['Server']['url'],
$synced_server['Server']['url'],
sprintf(
'<%s>%s</%s>',
$success ? 'info' : 'error',
$success ? 'Success' : 'Failed',
$success ? 'info' : 'error'
)
),
1,
Shell::NORMAL
);
}
}
}
}
public function enableTaxonomy()
{
$taxonomyToEnable = $this->param('taxonomy');
@ -162,16 +313,29 @@ class Ls22Shell extends AppShell
$HttpSocket = $this->Server->setupHttpSocket($server, null);
$request = $this->Server->setupSyncRequest($server, 'Server');
$start_time = microtime(true);
$response = $HttpSocket->get($server['Server']['url'] . '/users/view/me', false, $request);
$execution_time = round((microtime(true) - $start_time) * 1000);
$statusWrapped = sprintf(
'<%s>%s</%s>',
$response->isOk() ? 'info' : 'error',
$response->isOk() ? 'OK (' . $execution_time . 'ms)' : 'Failed. (' . $response->code . ')',
$response->isOk() ? 'info' : 'error'
);
$fatal_error = false;
try {
$response = $HttpSocket->get($server['Server']['url'] . '/users/view/me', false, $request);
} catch (Exception $e) {
$fatal_error = true;
echo "\x07";
$statusWrapped = sprintf(
'<error>%s %s: %s</error>',
'Something went wrong while trying to reach',
$server['Server']['url'],
$e->getMessage()
);
}
if (!$fatal_error) {
$execution_time = round((microtime(true) - $start_time) * 1000);
$statusWrapped = sprintf(
'<%s>%s</%s>',
$response->isOk() ? 'info' : 'error',
$response->isOk() ? 'OK (' . $execution_time . 'ms)' : 'Failed. (' . $response->code . ')',
$response->isOk() ? 'info' : 'error'
);
}
$this->out($server['Server']['url'] . ': ' . $statusWrapped, 1, Shell::NORMAL);
$results[$server['Server']['url']] = $response->isOk() ? $execution_time : false;
}
}
@ -215,28 +379,30 @@ class Ls22Shell extends AppShell
}
$HttpSocket = $this->Server->setupHttpSocket($server, null);
$request = $this->Server->setupSyncRequest($server);
$response = $HttpSocket->get($server['Server']['url'] . '/organisations/index', false, $request);
$response = $HttpSocket->get($server['Server']['url'] . '/organisations/index/scope:all', false, $request);
$orgs = json_decode($response->body(), true);
$this->out(__('Organisations fetched. %d found.', count($orgs)), 1, Shell::VERBOSE);
$org_mapping = [];
foreach ($orgs as $org) {
$name = explode(' ', $org['Organisation']['name']);
if ($name[0] !== 'BT') {
if (!empty($this->param('org')) && $org['Organisation']['name'] !== $this->param('org')) {
continue;
}
if ($org['Organisation']['name'] === 'YT') {
continue;
}
$org_mapping[$org['Organisation']['name']] = $org['Organisation']['id'];
}
if (!empty($this->param['from'])) {
$time_range[] = $this->param['from'];
}
if (!empty($this->param['to'])) {
if (empty($time_range)) {
$time_range[] = '365d';
}
$time_range[] = $this->param['to'];
}
foreach ($org_mapping as $org_name => $org_id) {
$time_range = [];
if (!empty($this->param['from'])) {
$time_range[] = $this->param['from'];
}
if (!empty($this->param['to'])) {
if (empty($time_range)) {
$time_range[] = '365d';
}
$time_range[] = $this->param['to'];
}
$params = [
'org' => $org_id
];
@ -256,7 +422,8 @@ class Ls22Shell extends AppShell
'other' => 0,
'attribute_attack' => 0,
'attribute_other' => 0,
'score' => 0
'score' => 0,
'warnings' => 0
];
foreach ($events['response'] as $event) {
if (!empty($event['Event']['Tag'])) {
@ -290,6 +457,9 @@ class Ls22Shell extends AppShell
}
}
}
if (!empty($attribute['warnings'])) {
$result[$org_name]['warnings'] += 1;
}
}
$results[$org_name]['attribute_count'] += count($event['Event']['Attribute']);
if (!empty($event['Event']['Object'])) {
@ -319,11 +489,18 @@ class Ls22Shell extends AppShell
foreach ($results as $k => $result) {
$totalCount = $result['attribute_count'] + $result['object_count'];
if ($totalCount) {
if (empty($result['warnings'])) {
$results[$k]['metrics']['warnings'] = 100;
} else if (100 * $result['warnings'] < $result['attribute_count']) {
$results[$k]['metrics']['warnings'] = 50;
} else {
$results[$k]['metrics']['warnings'] = 0;
}
$results[$k]['metrics']['connectedness'] = 100 * ($result['connected_elements'] / ($result['attribute_count'] + $result['object_count']));
$results[$k]['metrics']['attack_weight'] = 100 * (2*($result['attack']) + $result['attribute_attack']) / ($result['attribute_count'] + $result['object_count']);
$results[$k]['metrics']['other_weight'] = 100 * (2*($result['other']) + $result['attribute_other']) / ($result['attribute_count'] + $result['object_count']);
}
foreach (['connectedness', 'attack_weight', 'other_weight'] as $metric) {
foreach (['connectedness', 'attack_weight', 'other_weight', 'warnings'] as $metric) {
if (empty($results[$k]['metrics'][$metric])) {
$results[$k]['metrics'][$metric] = 0;
}
@ -331,8 +508,17 @@ class Ls22Shell extends AppShell
$results[$k]['metrics'][$metric] = 100;
}
}
$results[$k]['score'] = round(40 * $results[$k]['metrics']['connectedness'] + 40 * $results[$k]['metrics']['attack_weight'] + 20 * $results[$k]['metrics']['other_weight']) / 100;
$scores[$k] = $results[$k]['score'];
$results[$k]['score'] = round(
20 * $results[$k]['metrics']['warnings'] +
20 * $results[$k]['metrics']['connectedness'] +
40 * $results[$k]['metrics']['attack_weight'] +
20 * $results[$k]['metrics']['other_weight']
) / 100;
$scores[$k]['total'] = $results[$k]['score'];
$scores[$k]['warnings'] = round(20 * $results[$k]['metrics']['warnings']);
$scores[$k]['connectedness'] = round(20 * $results[$k]['metrics']['connectedness']);
$scores[$k]['attack_weight'] = round(40 * $results[$k]['metrics']['attack_weight']);
$scores[$k]['other_weight'] = round(20 * $results[$k]['metrics']['other_weight']);
}
arsort($scores, SORT_DESC);
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
@ -344,18 +530,34 @@ class Ls22Shell extends AppShell
), 1, Shell::NORMAL);
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
foreach ($scores as $org => $score) {
$score_string = str_repeat('█', round($score));
$score_string[0] = str_repeat('█', round($score['warnings']/100));
$score_string[1] = str_repeat('█', round($score['connectedness']/100));
$score_string[2] = str_repeat('█', round($score['attack_weight']/100));
$score_string[3] = str_repeat('█', round($score['other_weight']/100));
$this->out(sprintf(
'| %s | %s | %s |',
str_pad($org, 10, ' ', STR_PAD_RIGHT),
sprintf(
'<info>%s</info>%s',
$score_string,
str_repeat(' ', 100 - mb_strlen($score_string))
'<error>%s</error><warning>%s</warning><question>%s</question><info>%s</info>%s',
$score_string[0],
$score_string[1],
$score_string[2],
$score_string[3],
str_repeat(' ', 100 - mb_strlen(implode('', $score_string)))
),
str_pad($score . '%', 8, ' ', STR_PAD_RIGHT)
str_pad($score['total'] . '%', 8, ' ', STR_PAD_RIGHT)
), 1, Shell::NORMAL);
}
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
$this->out(sprintf(
'| Legend: %s %s %s %s %s |',
'<error>█: Warnings</error>',
'<warning>█: Connectedness</warning>',
'<question>█: ATT&CK context</question>',
'<info>█: Other Context</info>',
str_repeat(' ', 52)
), 1, Shell::NORMAL);
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
file_put_contents(APP . 'tmp/report.json', json_encode($results, JSON_PRETTY_PRINT));
}
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
require_once 'AppShell.php';
class WorkflowShell extends AppShell {
public $uses = ['Job', 'Workflow'];
public $tasks = ['ConfigLoad'];
public function executeWorkflowForTrigger()
{
$this->ConfigLoad->execute();
if (empty($this->args[0]) || empty($this->args[1]) || empty($this->args[2]) || empty($this->args[3])) {
die(__('Invalid number of arguments.'));
}
$trigger_id = $this->args[0];
$data = JsonTool::decode($this->args[1]);
$logging = JsonTool::decode($this->args[2]);
$jobId = $this->args[3];
$blockingErrors = [];
$executionSuccess = $this->Workflow->executeWorkflowForTrigger($trigger_id, $data, $blockingErrors);
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 100;
$job['Job']['status'] = Job::STATUS_COMPLETED;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
if ($executionSuccess) {
$job['Job']['message'] = __('Workflow for trigger `%s` completed execution', $trigger_id);
} else {
$errorMessage = implode(', ', $blockingErrors);
$message = __('Error while executing workflow for trigger `%s`: %s. %s%s', $trigger_id, $logging['message'], PHP_EOL . __('Returned message: %s', $errorMessage));
$job['Job']['message'] = $message;
}
$this->Job->save($job);
}
public function walkGraph()
{
$this->ConfigLoad->execute();
if (empty($this->args[0]) || empty($this->args[1]) || empty($this->args[2]) || empty($this->args[3])) {
die(__('Invalid number of arguments.'));
}
$workflow_id = (int)$this->args[0];
$workflow = $this->Workflow->fetchWorkflow($workflow_id);
$node_id_to_exec = (int)$this->args[1];
$roamingData = JsonTool::decode($this->args[2]);
$for_path = $this->args[3];
$jobId = $this->args[4];
$concurrentErrors = [];
$walkResult = [];
$executionSuccess = $this->Workflow->walkGraph(
$workflow,
$node_id_to_exec,
$for_path,
$roamingData,
$concurrentErrors,
$walkResult
);
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 100;
$job['Job']['status'] = Job::STATUS_COMPLETED;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
if ($executionSuccess) {
$job['Job']['message'] = __('Workflow concurrent task executed %s nodes starting from node %s.', count($walkResult['executed_nodes']), $node_id_to_exec);
} else {
$message = __('Error while executing workflow concurrent task. %s', PHP_EOL . implode(', ', $concurrentErrors));
$this->Workflow->logExecutionError($workflow, $message);
$job['Job']['message'] = $message;
}
$this->Job->save($job);
}
}

View File

@ -4,6 +4,7 @@ App::uses('Controller', 'Controller');
App::uses('File', 'Utility');
App::uses('RequestRearrangeTool', 'Tools');
App::uses('BlowfishConstantPasswordHasher', 'Controller/Component/Auth');
App::uses('BetterCakeEventManager', 'Tools');
/**
* Application Controller
@ -34,8 +35,8 @@ class AppController extends Controller
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
private $__queryVersion = '139';
public $pyMispVersion = '2.4.157';
private $__queryVersion = '144';
public $pyMispVersion = '2.4.160';
public $phpmin = '7.2';
public $phprec = '7.4';
public $phptoonew = '8.0';
@ -434,6 +435,10 @@ class AppController extends Controller
);
$this->Log->save($log);
}
$storeAPITime = Configure::read('MISP.store_api_access_time');
if (!empty($storeAPITime) && $storeAPITime) {
$this->User->updateAPIAccessTime($user);
}
$this->Session->renew();
$this->Session->write(AuthComponent::$sessionKey, $user);
$this->isApiAuthed = true;
@ -810,8 +815,8 @@ class AppController extends Controller
ConnectionManager::create('default', $db->config);
}
$dataSource = $dataSourceConfig['datasource'];
if (!in_array($dataSource, array('Database/Mysql', 'Database/Postgres', 'Database/MysqlObserver'))) {
throw new Exception('datasource not supported: ' . $dataSource);
if (!in_array($dataSource, ['Database/Mysql', 'Database/Postgres', 'Database/MysqlObserver', 'Database/MysqlExtended'], true)) {
throw new Exception('Datasource not supported: ' . $dataSource);
}
}
@ -908,11 +913,11 @@ class AppController extends Controller
/**
* generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params
* @param array $options
* @param $exception
* @param CakeResponse $exception
* @param array $data
* @return array|false|mixed
* @return array|false
*/
protected function _harvestParameters($options, &$exception = null, $data = array())
protected function _harvestParameters($options, &$exception = null, $data = [])
{
$request = $options['request'] ?? $this->request;
if ($request->is('post')) {
@ -958,14 +963,15 @@ class AppController extends Controller
}
}
}
foreach ($data as $k => $v) {
if (!is_array($data[$k])) {
$data[$k] = trim($data[$k]);
if (strpos($data[$k], '||')) {
$data[$k] = explode('||', $data[$k]);
foreach ($data as &$v) {
if (is_string($v)) {
$v = trim($v);
if (strpos($v, '||')) {
$v = explode('||', $v);
}
}
}
unset($v);
if (!empty($options['additional_delimiters'])) {
if (!is_array($options['additional_delimiters'])) {
$options['additional_delimiters'] = array($options['additional_delimiters']);
@ -975,6 +981,7 @@ class AppController extends Controller
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
break;
}
}
if ($found) {
@ -1257,17 +1264,17 @@ class AppController extends Controller
]);
}
}
/** @var TmpFileTool $final */
$final = $model->restSearch($user, $returnFormat, $filters, false, false, $elementCounter, $renderView);
if (!empty($renderView) && !empty($final)) {
if ($renderView) {
$this->layout = false;
$final = json_decode($final->intoString(), true);
foreach ($final as $key => $data) {
$this->set($key, $data);
}
$this->set($final);
$this->render('/Events/module_views/' . $renderView);
} else {
$filename = $this->RestSearch->getFilename($filters, $scope, $responseType);
return $this->RestResponse->viewData($final, $responseType, false, true, $filename, array('X-Result-Count' => $elementCounter, 'X-Export-Module-Used' => $returnFormat, 'X-Response-Format' => $responseType));
$headers = ['X-Result-Count' => $elementCounter, 'X-Export-Module-Used' => $returnFormat, 'X-Response-Format' => $responseType];
return $this->RestResponse->viewData($final, $responseType, false, true, $filename, $headers);
}
}
@ -1293,21 +1300,24 @@ class AppController extends Controller
* Returns true if user can modify given event.
*
* @param array $event
* @param array|null $user If empty, currently logged user will be used
* @return bool
*/
protected function __canModifyEvent(array $event)
protected function __canModifyEvent(array $event, $user = null)
{
if (!isset($event['Event'])) {
throw new InvalidArgumentException('Passed object does not contain an Event.');
}
if ($this->userRole['perm_site_admin']) {
$user = $user ?: $this->Auth->user();
if ($user['Role']['perm_site_admin']) {
return true;
}
if ($this->userRole['perm_modify_org'] && $event['Event']['orgc_id'] == $this->Auth->user()['org_id']) {
if ($user['Role']['perm_modify_org'] && $event['Event']['orgc_id'] == $user['org_id']) {
return true;
}
if ($this->userRole['perm_modify'] && $event['Event']['user_id'] == $this->Auth->user()['id']) {
if ($user['Role']['perm_modify'] && $event['Event']['user_id'] == $user['id']) {
return true;
}
return false;
@ -1438,6 +1448,27 @@ class AppController extends Controller
return parent::_getViewObject();
}
public function getEventManager()
{
if (empty($this->_eventManager)) {
$this->_eventManager = new BetterCakeEventManager();
$this->_eventManager->attach($this->Components);
$this->_eventManager->attach($this);
}
return $this->_eventManager;
}
/**
* Close session without writing changes to them and return current user.
* @return array
*/
protected function _closeSession()
{
$user = $this->Auth->user();
session_abort();
return $user;
}
/**
* Decode JSON with proper error handling.
* @param string $dataToDecode
@ -1446,18 +1477,34 @@ class AppController extends Controller
protected function _jsonDecode($dataToDecode)
{
try {
if (defined('JSON_THROW_ON_ERROR')) {
// JSON_THROW_ON_ERROR is supported since PHP 7.3
return json_decode($dataToDecode, true, 512, JSON_THROW_ON_ERROR);
} else {
$decoded = json_decode($dataToDecode, true);
if ($decoded === null) {
throw new UnexpectedValueException('Could not parse JSON: ' . json_last_error_msg(), json_last_error());
}
return $decoded;
}
return JsonTool::decode($dataToDecode);
} catch (Exception $e) {
throw new HttpException('Invalid JSON input. Make sure that the JSON input is a correctly formatted JSON string. This request has been blocked to avoid an unfiltered request.', 405, $e);
}
}
/**
* Mimics what PaginateComponent::paginate() would do, when Model::paginate() is not called
*
* @param integer $page
* @param integer $limit
* @param integer $current
* @param string $type
* @return void
*/
protected function __setPagingParams(int $page, int $limit, int $current, string $type = 'named')
{
$this->request->params['paging'] = [
'Correlation' => [
'page' => $page,
'limit' => $limit,
'current' => $current,
'pageCount' => 0,
'prevPage' => $page > 1,
'nextPage' => $current >= $limit,
'options' => [],
'paramType' => $type
]
];
}
}

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,7 @@ class AuditLogsController extends AppController
'GalaxyClusterRelation',
'News',
'Warninglist',
'Workflow',
];
public $paginate = [
@ -67,9 +68,9 @@ class AuditLogsController extends AppController
],
];
public function __construct($id = false, $table = null, $ds = null)
public function __construct($request = null, $response = null)
{
parent::__construct($id, $table, $ds);
parent::__construct($request, $response);
$this->actions = [
AuditLog::ACTION_ADD => __('Add'),
AuditLog::ACTION_EDIT => __('Edit'),
@ -99,7 +100,22 @@ class AuditLogsController extends AppController
$this->paginate['fields'][] = 'request_id';
}
$this->paginate['conditions'] = $this->__searchConditions();
$params = $this->IndexFilter->harvestParameters([
'ip',
'user',
'request_id',
'authkey_id',
'model',
'model_id',
'event_id',
'model_title',
'action',
'org',
'created',
'request_type',
]);
$this->paginate['conditions'] = $this->__searchConditions($params);
$list = $this->paginate();
if ($this->_isRest()) {
@ -133,32 +149,27 @@ class AuditLogsController extends AppController
public function eventIndex($eventId, $org = null)
{
$this->loadModel('Event');
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
$event = $this->AuditLog->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
if (empty($event)) {
throw new NotFoundException('Invalid event.');
}
$this->paginate['conditions'] = $this->__createEventIndexConditions($event);
$params = $this->IndexFilter->harvestParameters(['created', 'org']);
if ($org) {
$org = $this->AuditLog->Organisation->fetchOrg($org);
if ($org) {
$this->paginate['conditions']['AND']['org_id'] = $org['id'];
} else {
$this->paginate['conditions']['AND']['org_id'] = -1;
}
$params['org'] = $org;
}
$this->paginate['conditions'][] = $this->__searchConditions($params);
$list = $this->paginate();
if (!$this->_isSiteAdmin()) {
// Remove all user info about users from different org
$this->loadModel('User');
$orgUserIds = $this->User->find('column', array(
$orgUserIds = $this->User->find('column', [
'conditions' => ['User.org_id' => $this->Auth->user('org_id')],
'fields' => ['User.id'],
));
]);
foreach ($list as $k => $item) {
if ($item['AuditLog']['user_id'] == 0) {
continue;
@ -199,15 +210,13 @@ class AuditLogsController extends AppController
public function returnDates($org = 'all')
{
if (!$this->Auth->user('Role')['perm_sharing_group'] && !empty(Configure::read('Security.hide_organisation_index_from_users'))) {
if ($org !== 'all' && $org !== $this->Auth->user('Organisation')['name']) {
$user = $this->_closeSession();
if (!$user['Role']['perm_sharing_group'] && !empty(Configure::read('Security.hide_organisation_index_from_users'))) {
if ($org !== 'all' && $org !== $user['Organisation']['name']) {
throw new MethodNotAllowedException('Invalid organisation.');
}
}
// Fetching dates can be slow, so to allow concurrent requests, we can close sessions to release session lock
session_write_close();
$data = $this->AuditLog->returnDates($org);
return $this->RestResponse->viewData($data, $this->response->type());
}
@ -215,23 +224,8 @@ class AuditLogsController extends AppController
/**
* @return array
*/
private function __searchConditions()
private function __searchConditions(array $params)
{
$params = $this->IndexFilter->harvestParameters([
'ip',
'user',
'request_id',
'authkey_id',
'model',
'model_id',
'event_id',
'model_title',
'action',
'org',
'created',
'request_type',
]);
$qbRules = [];
foreach ($params as $key => $value) {
if ($key === 'model' && strpos($value, ':') !== false) {
@ -351,7 +345,7 @@ class AuditLogsController extends AppController
return ['event_id' => $event['Event']['id']];
}
$event = $this->Event->fetchEvent($this->Auth->user(), [
$event = $this->AuditLog->Event->fetchEvent($this->Auth->user(), [
'eventid' => $event['Event']['id'],
'sgReferenceOnly' => 1,
'deleted' => [0, 1],

View File

@ -125,7 +125,7 @@ class CerebratesController extends AppController
$this->set('title', __('Sync organisation information'));
$this->set('question', __('Are you sure you want to download and add / update the remote organisations from the Cerebrate node?'));
$this->set('actionName', __('Pull all'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}
@ -165,7 +165,7 @@ class CerebratesController extends AppController
$this->set('title', __('Sync sharing group information'));
$this->set('question', __('Are you sure you want to download and add / update the remote sharing group from the Cerebrate node?'));
$this->set('actionName', __('Pull all'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}
@ -237,7 +237,7 @@ class CerebratesController extends AppController
$this->set('title', __('Download organisation information'));
$this->set('question', __('Are you sure you want to download and add / update the remote organisation?'));
$this->set('actionName', __('Download'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}
@ -309,7 +309,7 @@ class CerebratesController extends AppController
$this->set('title', __('Download sharing group information'));
$this->set('question', __('Are you sure you want to download and add / update the remote sharing group?'));
$this->set('actionName', __('Download'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}

View File

@ -97,8 +97,12 @@ class ACLComponent extends Component
'view' => []
],
'correlations' => [
'generateOccurrences' => [],
'generateTopCorrelations' => [],
'top' => []
'overCorrelations' => [],
'switchEngine' => [],
'top' => [],
'truncate' => []
],
'cryptographicKeys' => [
'add' => ['perm_add'],
@ -232,7 +236,6 @@ class ACLComponent extends Component
'getEventGraphTags' => array('*'),
'getEventGraphGeneric' => array('*'),
'getEventTimeline' => array('*'),
'genDistributionGraph' => array('*'),
'getDistributionGraph' => array('*'),
'getReferenceData' => array('*'),
'getReferences' => array('*'),
@ -340,7 +343,6 @@ class ACLComponent extends Component
),
'galaxyClusters' => array(
'add' => array('perm_galaxy_editor'),
'attachToEvent' => array('perm_tagger'),
'delete' => array('perm_galaxy_editor'),
'detach' => array('perm_tagger'),
'edit' => array('perm_galaxy_editor'),
@ -501,6 +503,7 @@ class ACLComponent extends Component
'servers' => array(
'add' => array(),
'dbSchemaDiagnostic' => array(),
'dbConfiguration' => array(),
'cache' => array(),
'changePriority' => array(),
'checkout' => array(),
@ -671,6 +674,7 @@ class ACLComponent extends Component
'view' => array('*'),
'unhideTag' => array('perm_tagger'),
'hideTag' => array('perm_tagger'),
'normalizeCustomTagsToTaxonomyFormat' => [],
),
'templateElements' => array(
'add' => array('perm_template'),
@ -740,6 +744,7 @@ class ACLComponent extends Component
'verifyGPG' => array(),
'view' => array('*'),
'getGpgPublicKey' => array('*'),
'unsubscribe' => ['*'],
),
'userSettings' => array(
'index' => array('*'),
@ -764,6 +769,32 @@ class ACLComponent extends Component
'export' => ['*'],
'import' => ['perm_warninglist'],
),
'workflows' => [
'index'=> [],
'rebuildRedis'=> [],
'edit'=> [],
'delete'=> [],
'view'=> [],
'editor'=> [],
'triggers'=> [],
'moduleIndex'=> [],
'moduleView'=> [],
'toggleModule'=> [],
'checkGraph'=> [],
'executeWorkflow'=> [],
'debugToggleField'=> [],
'massToggleField'=> [],
],
'workflowBlueprints' => [
'add' => [],
'delete' => [],
'edit' => [],
'export' => [],
'import' => [],
'index' => [],
'update' => [],
'view' => [],
],
'allowedlists' => array(
'admin_add' => array('perm_regexp_access'),
'admin_delete' => array('perm_regexp_access'),
@ -981,6 +1012,8 @@ class ACLComponent extends Component
private function __findAllFunctions()
{
$functionsToIgnore = ['beforeFilter', 'afterFilter', 'beforeRender', 'getEventManager'];
$functionFinder = '/function[\s\n]+(\S+)[\s\n]*\(/';
$dir = new Folder(APP . 'Controller');
$files = $dir->find('.*\.php');
@ -991,11 +1024,11 @@ class ACLComponent extends Component
$controllerName = '*';
}
$functionArray = array();
$fileContents = file_get_contents(APP . 'Controller' . DS . $file);
$fileContents = FileAccessTool::readFromFile(APP . 'Controller' . DS . $file);
$fileContents = preg_replace('/\/\*[^\*]+?\*\//', '', $fileContents);
preg_match_all($functionFinder, $fileContents, $functionArray);
foreach ($functionArray[1] as $function) {
if ($function[0] !== '_' && $function !== 'beforeFilter' && $function !== 'afterFilter' && $function !== 'beforeRender') {
if ($function[0] !== '_' && !in_array($function, $functionsToIgnore, true)) {
$results[$controllerName][] = $function;
}
}
@ -1016,8 +1049,7 @@ class ACLComponent extends Component
$missing = array();
foreach ($results as $controller => $functions) {
foreach ($functions as $function) {
if (!isset(self::ACL_LIST[$controller])
|| !in_array($function, array_keys(self::ACL_LIST[$controller]))) {
if (!isset(self::ACL_LIST[$controller]) || !in_array($function, array_keys(self::ACL_LIST[$controller]))) {
$missing[$controller][] = $function;
}
}

View File

@ -1,8 +1,21 @@
<?php
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
App::uses('AbstractPasswordHasher', 'Controller/Component/Auth');
class BlowfishConstantPasswordHasher extends BlowfishPasswordHasher
class BlowfishConstantPasswordHasher extends AbstractPasswordHasher
{
/**
* @param string $password
* @return string
*/
public function hash($password)
{
$hash = password_hash($password, PASSWORD_BCRYPT);
if ($hash === false) {
throw new RuntimeException('Could not generate hashed password');
}
return $hash;
}
/**
* @param string $password
* @param string $hashedPassword
@ -10,6 +23,6 @@ class BlowfishConstantPasswordHasher extends BlowfishPasswordHasher
*/
public function check($password, $hashedPassword)
{
return hash_equals($hashedPassword, Security::hash($password, 'blowfish', $hashedPassword));
return password_verify($password, $hashedPassword);
}
}

View File

@ -10,27 +10,29 @@ class IndexFilterComponent extends Component
public $Controller;
public $isRest = null;
public function initialize(Controller $controller) {
public function initialize(Controller $controller)
{
$this->Controller = $controller;
}
// generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params
public function harvestParameters($paramArray, &$exception = array())
public function harvestParameters($paramArray, &$exception = [])
{
$data = array();
if (!empty($this->Controller->request->is('post'))) {
if (empty($this->Controller->request->data)) {
$request = $this->Controller->request;
$data = [];
if ($request->is('post')) {
if (empty($request->data)) {
$exception = $this->Controller->RestResponse->throwException(
400,
__('Either specify the search terms in the url, or POST a json with the filter parameters.'),
'/' . $this->Controller->request->params['controller'] . '/' . $this->Controller->action
'/' . $request->params['controller'] . '/' . $this->Controller->action
);
return false;
} else {
if (isset($this->Controller->request->data['request'])) {
$data = $this->Controller->request->data['request'];
if (isset($request->data['request'])) {
$data = $request->data['request'];
} else {
$data = $this->Controller->request->data;
$data = $request->data;
}
}
}
@ -43,19 +45,20 @@ class IndexFilterComponent extends Component
$data[$p] = $options['ordered_url_params'][$p];
$data[$p] = str_replace(';', ':', $data[$p]);
}
if (isset($this->Controller->params['named'][$p])) {
$data[$p] = str_replace(';', ':', $this->Controller->params['named'][$p]);
if (isset($request->params['named'][$p])) {
$data[$p] = str_replace(';', ':', $request->params['named'][$p]);
}
}
}
foreach ($data as $k => $v) {
if (!is_array($data[$k])) {
$data[$k] = trim($data[$k]);
if (strpos($data[$k], '||')) {
$data[$k] = explode('||', $data[$k]);
foreach ($data as &$v) {
if (is_string($v)) {
$v = trim($v);
if (strpos($v, '||')) {
$v = explode('||', $v);
}
}
}
unset($v);
if (!empty($options['additional_delimiters'])) {
if (!is_array($options['additional_delimiters'])) {
$options['additional_delimiters'] = array($options['additional_delimiters']);
@ -65,6 +68,7 @@ class IndexFilterComponent extends Component
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
break;
}
}
if ($found) {

View File

@ -479,39 +479,70 @@ class RestResponseComponent extends Component
return [];
}
public function saveFailResponse($controller, $action, $id = false, $validationErrors, $format = false, $data = null)
/**
* @param string $controller
* @param string $action
* @param int|false $id
* @param mixed $validationErrors
* @param string|false $format
* @param mixed $data
* @return CakeResponse
* @throws Exception
*/
public function saveFailResponse($controller, $action, $id, $validationErrors, $format = false, $data = null)
{
$response = array();
$action = $this->__dissectAdminRouting($action);
$stringifiedAction = $action['action'];
if (isset(self::CONVERT_ACTION_TO_MESSAGE[$controller][$action['action']])) {
$stringifiedAction = self::CONVERT_ACTION_TO_MESSAGE[$controller][$action['action']];
if (isset(self::CONVERT_ACTION_TO_MESSAGE[$controller][$stringifiedAction])) {
$stringifiedAction = self::CONVERT_ACTION_TO_MESSAGE[$controller][$stringifiedAction];
}
$response['saved'] = false;
$response['name'] = 'Could not ' . $stringifiedAction . ' ' . Inflector::singularize($controller);
$response['message'] = $response['name'];
$message = 'Could not ' . $stringifiedAction . ' ' . Inflector::singularize($controller);
$response = [
'saved' => false,
'name' => $message,
'message' => $message,
'url' => $this->__generateURL($action, $controller, $id),
'errors' => $validationErrors,
];
if ($data !== null) {
$response['data'] = $data;
}
$response['url'] = $this->__generateURL($action, $controller, $id);
$response['errors'] = $validationErrors;
if ($id) {
$response['id'] = $id;
}
return $this->__sendResponse($response, 403, $format);
}
/**
* @param string $controller
* @param string $action
* @param int|false $id
* @param string|false $format
* @param string|false $message
* @param mixed $data
* @return CakeResponse
* @throws Exception
*/
public function saveSuccessResponse($controller, $action, $id = false, $format = false, $message = false, $data = null)
{
$action = $this->__dissectAdminRouting($action);
if (!$message) {
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) == 'e') ? 'd' : 'ed');
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) === 'e') ? 'd' : 'ed');
}
$response['saved'] = true;
$response['success'] = true;
$response['name'] = $message;
$response['message'] = $response['name'];
$response = [
'saved' => true,
'success' => true,
'name' => $message,
'message' => $message,
'url' => $this->__generateURL($action, $controller, $id),
];
if ($data !== null) {
$response['data'] = $data;
}
$response['url'] = $this->__generateURL($action, $controller, $id);
if ($id) {
$response['id'] = $id;
}
return $this->__sendResponse($response, 200, $format);
}
@ -527,7 +558,7 @@ class RestResponseComponent extends Component
*/
private function __sendResponse($response, $code, $format = false, $raw = false, $download = false, $headers = array())
{
$format = strtolower($format);
$format = !empty($format) ? strtolower($format) : 'json';
if ($format === 'application/xml' || $format === 'xml') {
if (!$raw) {
if (isset($response[0])) {
@ -550,11 +581,7 @@ class RestResponseComponent extends Component
} elseif ($format === 'csv' || $format === 'text/csv') {
$type = 'csv';
} else {
if (empty($format)) {
$type = 'json';
} else {
$type = $format;
}
$type = $format;
$dumpSql = !empty($this->Controller->sql_dump) && Configure::read('debug') > 1;
if (!$raw) {
if (is_string($response)) {
@ -601,10 +628,16 @@ class RestResponseComponent extends Component
}
if ($response instanceof TmpFileTool) {
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = '"' . $response->hash('sha1') . '"';
if ($_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
return new CakeResponse(['status' => 304]);
}
$headers['ETag'] = $etag;
}
if ($this->signContents) {
$this->CryptographicKey = ClassRegistry::init('CryptographicKey');
$data = $response->intoString();
$headers['x-pgp-signature'] = base64_encode($this->CryptographicKey->signWithInstanceKey($data));
$headers['x-pgp-signature'] = $this->sign($data);
$cakeResponse = new CakeResponse(['body' => $data, 'status' => $code, 'type' => $type]);
} else {
App::uses('CakeResponseFile', 'Tools');
@ -612,9 +645,18 @@ class RestResponseComponent extends Component
$cakeResponse->file($response);
}
} else {
$cakeResponse = new CakeResponse(array('body' => $response, 'status' => $code, 'type' => $type));
// Check if resource was changed when `If-None-Match` header is send and return 304 Not Modified
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = '"' . sha1($response) . '"';
if ($_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
return new CakeResponse(['status' => 304]);
}
// Generate etag just when HTTP_IF_NONE_MATCH is set
$headers['ETag'] = $etag;
}
$cakeResponse = new CakeResponse(['body' => $response, 'status' => $code, 'type' => $type]);
if ($this->signContents) {
$headers['x-pgp-signature'] = base64_encode($this->CryptographicKey->signWithInstanceKey($response));
$headers['x-pgp-signature'] = $this->sign($response);
}
}
@ -639,6 +681,25 @@ class RestResponseComponent extends Component
return $cakeResponse;
}
/**
* @param string $response
* @return string Signature as base64 encoded string
* @throws Crypt_GPG_BadPassphraseException
* @throws Crypt_GPG_Exception
* @throws Crypt_GPG_KeyNotFoundException
* @throws Exception
*/
private function sign($response)
{
/** @var CryptographicKey $cryptographicKey */
$cryptographicKey = ClassRegistry::init('CryptographicKey');
$signature = $cryptographicKey->signWithInstanceKey($response);
if (!$signature) {
throw new Exception('Could not sign data.');
}
return base64_encode($signature);
}
/**
* Detect if request comes from automatic tool (like other MISP instance or PyMISP) or AJAX
* @return bool

View File

@ -122,8 +122,8 @@ class CorrelationExclusionsController extends AppController
} else {
$this->set('title', __('Clean up correlations'));
$this->set('question', __('Execute the cleaning of all correlations that are at odds with the exclusion rules? This will delete all matching correlations.'));
$this->set('actionName', 'clean');
$this->layout = 'ajax';
$this->set('actionName', __('Clean'));
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}

View File

@ -44,6 +44,9 @@ class CorrelationsController extends AppController
}
}
}
$this->__setPagingParams($query['page'], $query['limit'], count($data), 'named');
$this->set('age', $age);
$this->set('age_unit', $unit);
$this->set('data', $data);
@ -72,4 +75,147 @@ class CorrelationsController extends AppController
$this->redirect(['controller' => 'correlations', 'action' => 'top']);
}
}
public function overCorrelations()
{
$query = [
'limit' => 50,
'page' => 1,
'order' => 'occurrence desc'
];
foreach (array_keys($query) as $custom_param) {
if (isset($this->params['named'][$custom_param])) {
$query[$custom_param] = $this->params['named'][$custom_param];
}
}
if (isset($this->params['named']['scope'])) {
$limit = $this->Correlation->OverCorrelatingValue->getLimit();
if ($this->params['named']['scope'] === 'over_correlating') {
$query['conditions'][] = ['occurrence >=' => $limit];
} else if ($this->params['named']['scope'] === 'not_over_correlating') {
$query['conditions'][] = ['occurrence <' => $limit];
}
}
$data = $this->Correlation->OverCorrelatingValue->getOverCorrelations($query);
$data = $this->Correlation->attachExclusionsToOverCorrelations($data);
if ($this->_isRest()) {
return $this->RestResponse->viewData($data, 'json');
} else {
$this->__setPagingParams($query['page'], $query['limit'], count($data), 'named');
$this->set('data', $data);
$this->set('title_for_layout', __('Index of over correlating values'));
$this->set('menuData', [
'menuList' => 'correlationExclusions',
'menuItem' => 'over'
]);
}
}
public function switchEngine(string $engine)
{
$this->loadModel('Server');
if (!isset($this->Correlation->validEngines[$engine])) {
throw new MethodNotAllowedException(__('Not a valid engine choice. Please make sure you pass one of the following: ', implode(', ', array_keys($this->Correlation->validEngines))));
}
if ($this->request->is('post')) {
$setting = $this->Server->getSettingData('MISP.correlation_engine');
$result = $this->Server->serverSettingsEditValue($this->Auth->user(), $setting, $engine);
if ($result === true) {
$message = __('Engine switched.');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Correlations', 'switchEngine', false, $this->response->type(), $message);
} else {
$this->Flash->success($message);
$this->redirect(['controller' => 'servers', 'action' => 'serverSettings', 'correlations']);
}
} else {
$message = __('Couldn\'t switch to the requested engine.');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Correlations', 'switchEngine', false, $message, $this->response->type());
} else {
$this->Flash->error($message);
$this->redirect(['controller' => 'servers', 'action' => 'serverSettings', 'correlations']);
}
}
} else {
$this->set('engine', $engine);
$this->render('ajax/switch_engine_confirmation');
}
}
public function truncate(string $engine)
{
if (!isset($this->Correlation->validEngines[$engine])) {
throw new MethodNotAllowedException(__('Not a valid engine choice. Please make sure you pass one of the following: ', implode(', ', array_keys($this->Correlation->validEngines))));
}
if ($this->request->is('post')) {
if (!Configure::read('MISP.background_jobs')) {
$result = $this->Correlation->truncate($this->Auth->user(), $engine);
$message = $result ? __('Table truncated.') : __('Could not truncate table');
if ($this->_isRest()) {
if ($result) {
$this->RestResponse->saveSuccessResponse('Correlations', 'truncate', false, $this->response->type(), $message);
} else {
$this->RestResponse->saveFailResponse('Correlations', 'truncate', false, $message, $this->response->type());
}
} else {
$this->Flash->{$result ? 'success' : 'error'}($message);
$this->redirect(['controller' => 'servers', 'action' => 'serverSettings', 'correlations']);
}
} else {
$job = ClassRegistry::init('Job');
$jobId = $job->createJob(
'SYSTEM',
Job::WORKER_DEFAULT,
'truncate table',
$this->Correlation->validEngines[$engine],
'Job created.'
);
$this->Correlation->Attribute->getBackgroundJobsTool()->enqueue(
BackgroundJobsTool::DEFAULT_QUEUE,
BackgroundJobsTool::CMD_ADMIN,
[
'truncateTable',
$this->Auth->user('id'),
$engine,
$jobId
],
true,
$jobId
);
$message = __('Job queued. You can view the progress if you navigate to the active jobs view (Administration -> Jobs).');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Correlations', 'truncate', false, $this->response->type(), $message);
} else {
$this->Flash->success($message);
$this->redirect(['controller' => 'servers', 'action' => 'serverSettings', 'correlations']);
}
}
} else {
$this->set('engine', $engine);
$this->set('table_name', $this->Correlation->validEngines[$engine]);
$this->render('ajax/truncate_confirmation');
}
}
public function generateOccurrences()
{
$this->loadModel('OverCorrelatingValue');
$this->OverCorrelatingValue->generateOccurrencesRouter();
$message = __('Job queued.');
if (Configure::read('MISP.background_jobs')) {
$message = __('Job queued.');
} else {
$message = __('Over-correlations counted successfully.');
}
if (!$this->_isRest()) {
$this->Flash->info($message);
$this->redirect(['controller' => 'correlations', 'action' => 'overCorrelations']);
} else {
return $this->RestResponse->saveSuccessResponse('Correlations', 'generateOccurrences', false, $this->response->type(), $message);
}
}
}

View File

@ -95,7 +95,7 @@ class CryptographicKeysController extends AppController
nl2br(h($key['CryptographicKey']['key_data']))
)
);
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/display');
}
}

View File

@ -12,17 +12,20 @@ class DashboardsController extends AppController
public function beforeFilter()
{
parent::beforeFilter();
$this->Security->unlockedActions = array_merge(array('renderWidget', 'getForm'), $this->Security->unlockedActions);
$this->Security->unlockedActions[] = 'renderWidget';
$this->Security->unlockedActions[] = 'getForm';
if ($this->request->action === 'renderWidget') {
$this->Security->doNotGenerateToken = true;
}
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999
'limit' => 60,
'maxLimit' => 9999
);
public function index($template_id = false)
{
$this->loadModel('UserSetting');
if (empty($template_id)) {
$params = array(
'conditions' => array(
@ -30,7 +33,7 @@ class DashboardsController extends AppController
'UserSetting.setting' => 'dashboard'
)
);
$userSettings = $this->UserSetting->find('first', $params);
$userSettings = $this->User->UserSetting->find('first', $params);
} else {
$dashboardTemplate = $this->Dashboard->getDashboardTemplate($this->Auth->user(), $template_id);
if (empty($dashboardTemplate)) {
@ -80,7 +83,6 @@ class DashboardsController extends AppController
// continue, we just don't load the widget
}
}
$this->layout = 'dashboard';
$this->set('widgets', $widgets);
}
@ -112,22 +114,20 @@ class DashboardsController extends AppController
public function updateSettings()
{
if ($this->request->is('post')) {
$this->UserSetting = ClassRegistry::init('UserSetting');
if (!isset($this->request->data['Dashboard']['value'])) {
throw new InvalidArgumentException(__('No setting data found.'));
}
$data = array(
'UserSetting' => array(
'user_id' => $this->Auth->user('id'),
'setting' => 'dashboard',
'value' => $this->request->data['Dashboard']['value']
)
);
$result = $this->UserSetting->setSetting($this->Auth->user(), $data);
$result = $this->User->UserSetting->setSetting($this->Auth->user(), $data);
if ($result) {
return $this->RestResponse->saveSuccessResponse('Dashboard', 'updateSettings', false, false, __('Settings updated.'));
}
return $this->RestResponse->saveFailResponse('Dashboard', 'updateSettings', false, $this->UserSetting->validationErrors, $this->response->type());
return $this->RestResponse->saveFailResponse('Dashboard', 'updateSettings', false, $this->User->UserSetting->validationErrors, $this->response->type());
}
}
@ -155,7 +155,7 @@ class DashboardsController extends AppController
}
$user = $this->Auth->user();
@session_write_close(); // allow concurrent AJAX requests (session hold lock by default)
@session_abort(); // allow concurrent AJAX requests (session hold lock by default)
if (empty($this->request->data['data'])) {
$this->request->data = array('data' => $this->request->data);
@ -237,7 +237,6 @@ class DashboardsController extends AppController
public function saveTemplate($update = false)
{
$this->loadModel('UserSetting');
if (!empty($update)) {
$conditions = array('Dashboard.id' => $update);
if (Validation::uuid($update)) {
@ -260,7 +259,7 @@ class DashboardsController extends AppController
}
$data = $this->request->data;
if (empty($update)) { // save the template stored in user setting and make it persistent
$data['value'] = $this->UserSetting->getSetting($this->Auth->user('id'), 'dashboard');
$data['value'] = $this->User->UserSetting->getSetting($this->Auth->user('id'), 'dashboard');
}
$result = $this->Dashboard->saveDashboardTemplate($this->Auth->user(), $data, $update);
if ($this->_isRest()) {
@ -279,7 +278,6 @@ class DashboardsController extends AppController
} else {
$this->layout = false;
}
$this->loadModel('User');
$permFlags = array(0 => __('Unrestricted'));
foreach ($this->User->Role->permFlags as $perm_flag => $perm_data) {
$permFlags[$perm_flag] = $perm_data['text'];

View File

@ -14,8 +14,8 @@ class EventReportsController extends AppController
public $paginate = array(
'limit' => 60,
'order' => array(
'EventReport.event_id' => 'ASC',
'EventReport.name' => 'ASC'
'EventReport.event_id' => 'ASC',
'EventReport.name' => 'ASC'
),
'recursive' => -1,
'contain' => array(
@ -78,8 +78,9 @@ class EventReportsController extends AppController
if (!$this->_isRest()) {
throw new MethodNotAllowedException(__('This function can only be reached via the API.'));
}
$report = $this->EventReport->simpleFetchById($this->Auth->user(), $reportId);
$proxyMISPElements = $this->EventReport->getProxyMISPElements($this->Auth->user(), $report['EventReport']['event_id']);
$user = $this->_closeSession();
$report = $this->EventReport->simpleFetchById($user, $reportId);
$proxyMISPElements = $this->EventReport->getProxyMISPElements($user, $report['EventReport']['event_id']);
return $this->RestResponse->viewData($proxyMISPElements, $this->response->type());
}
@ -139,7 +140,7 @@ class EventReportsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be reached via AJAX.'));
} else {
$this->layout = 'ajax';
$this->layout = false;
$this->set('report', $report);
$this->render('ajax/delete');
}
@ -163,7 +164,7 @@ class EventReportsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be reached via AJAX.'));
} else {
$this->layout = 'ajax';
$this->layout = false;
$this->set('report', $report);
}
}
@ -178,7 +179,7 @@ class EventReportsController extends AppController
$reports = $this->EventReport->find('all', [
'recursive' => -1,
'conditions' => $compiledConditions,
'contain' => $this->EventReport->defaultContain,
'contain' => EventReport::DEFAULT_CONTAIN,
]);
return $this->RestResponse->viewData($reports, $this->response->type());
} else {
@ -201,6 +202,8 @@ class EventReportsController extends AppController
$fetcherModule = $this->EventReport->isFetchURLModuleEnabled();
$this->set('importModuleEnabled', is_array($fetcherModule));
$this->render('ajax/indexForEvent');
} else {
$this->set('title_for_layout', __('Event Reports'));
}
}
}
@ -230,7 +233,7 @@ class EventReportsController extends AppController
return $this->__getFailResponseBasedOnContext($errorMessage, array(), 'applySuggestions', $reportId);
}
}
$this->layout = 'ajax';
$this->layout = false;
$this->set('reportId', $reportId);
$this->render('ajax/extractAllFromReport');
}
@ -286,7 +289,7 @@ class EventReportsController extends AppController
return $this->__getFailResponseBasedOnContext($errorMessage, array(), 'applySuggestions', $reportId);
}
}
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/replaceSuggestionInReport');
}
}
@ -325,7 +328,7 @@ class EventReportsController extends AppController
}
$this->set('importModuleEnabled', is_array($fetcherModule));
$this->set('event_id', $event_id);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/importReportFromUrl');
}
@ -367,7 +370,7 @@ class EventReportsController extends AppController
}
}
$this->set('event_id', $eventId);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/reportFromEvent');
}

View File

@ -31,7 +31,7 @@ class EventsController extends AppController
'sort', 'direction', 'focus', 'extended', 'overrideLimit', 'filterColumnsOverwrite', 'attributeFilter', 'page',
'searchFor', 'proposal', 'correlation', 'warning', 'deleted', 'includeRelatedTags', 'includeDecayScore', 'distribution',
'taggedAttributes', 'galaxyAttachedAttributes', 'objectType', 'attributeType', 'feed', 'server', 'toIDS',
'sighting', 'includeSightingdb', 'warninglistId'
'sighting', 'includeSightingdb', 'warninglistId', 'correlationId',
);
// private
@ -52,11 +52,12 @@ class EventsController extends AppController
'taggedAttributes' => '',
'galaxyAttachedAttributes' => '',
'warninglistId' => '',
'correlationId' => '',
);
// private
const DEFAULT_HIDDEN_INDEX_COLUMNS = [
'timestmap',
'timestamp',
'publish_timestamp'
];
@ -107,7 +108,7 @@ class EventsController extends AppController
$this->paginate = Set::merge($this->paginate, array('conditions' => $conditions));
}
if ($this->request->action === 'checkLocks') {
if (in_array($this->request->action, ['checkLocks', 'getDistributionGraph'], true)) {
$this->Security->doNotGenerateToken = true;
}
}
@ -618,7 +619,7 @@ class EventsController extends AppController
if (empty($usersToMatch)) {
$nothing = true;
} else {
$this->paginate['conditions']['AND'][] = ['Event.user_id' => array_unique($usersToMatch)];
$this->paginate['conditions']['AND'][] = ['Event.user_id' => array_unique($usersToMatch, SORT_REGULAR)];
}
}
break;
@ -749,7 +750,7 @@ class EventsController extends AppController
$this->set('analysisLevels', $this->Event->analysisLevels);
$this->set('distributionLevels', $this->Event->distributionLevels);
$this->set('shortDist', $this->Event->shortDist);
$this->set('distributionData', $this->genDistributionGraph(-1));
$this->set('distributionData', $this->__genDistributionGraph(-1));
$this->set('urlparams', $urlparams);
$this->set('passedArgsArray', $passedArgsArray);
$this->set('passedArgs', json_encode($passedArgs));
@ -1210,46 +1211,7 @@ class EventsController extends AppController
$this->set('tags', $tagNames);
$this->set('tagJSON', json_encode($tagJSON));
$this->set('rules', $rules);
$this->layout = 'ajax';
}
/**
* Search for a value on an attribute level for a specific field.
*
* @param array $attribute An attribute
* @param array $fields List of keys in attribute to search in
* @param array $searchParts Values to search
* @return bool Returns true on match
*/
private function __valueInFieldAttribute($attribute, $fields, $searchParts)
{
foreach ($fields as $field) {
if (strpos($field, 'Tag') === 0) {
if (empty($attribute['AttributeTag'])) {
continue;
}
$fieldValues = Hash::extract($attribute, 'AttributeTag.{n}.' . $field);
foreach ($fieldValues as $fieldValue) {
$fieldValue = mb_strtolower($fieldValue);
foreach ($searchParts as $s) {
if (strpos($fieldValue, $s) !== false) {
return true;
}
}
}
} else {
if (!isset($attribute[$field])) {
continue;
}
$fieldValue = mb_strtolower($attribute[$field]);
foreach ($searchParts as $s) {
if (strpos($fieldValue, $s) !== false) {
return true;
}
}
}
}
return false;
$this->layout = false;
}
public function viewEventAttributes($id, $all = false)
@ -1258,7 +1220,10 @@ class EventsController extends AppController
'paramArray' => self::ACCEPTED_FILTERING_NAMED_PARAMS,
'named_params' => $this->request->params['named']
);
$filters = $this->_harvestParameters($filterData);
$filters = $this->_harvestParameters($filterData, $exception);
if ($exception) {
return $exception;
}
// Remove default filters
foreach ($filters as $filterName => $filterValue) {
@ -1277,10 +1242,10 @@ class EventsController extends AppController
'fetchFullClusters' => false,
'includeAllTags' => true,
'includeGranularCorrelations' => true,
'includeEventCorrelations' => false,
'includeEventCorrelations' => true, // event correlations are need for filtering
'noEventReports' => true, // event reports for view are loaded dynamically
'noSightings' => true,
'includeServerCorrelations' => $filters['includeServerCorrelations'] ?? 1.
'includeServerCorrelations' => $filters['includeServerCorrelations'] ?? 1,
];
if (isset($filters['extended'])) {
$conditions['extended'] = 1;
@ -1294,7 +1259,7 @@ class EventsController extends AppController
if (isset($filters['deleted'])) {
if ($filters['deleted'] == 1) { // both
$conditions['deleted'] = [0, 1];
} elseif ($filters['deleted'] == 0) { // not-deleted only
} elseif ($filters['deleted'] == 0) { // not-deleted only (default)
$conditions['deleted'] = 0;
} else { // only deleted
$conditions['deleted'] = 1;
@ -1404,7 +1369,7 @@ class EventsController extends AppController
$advancedFiltering = $this->__checkIfAdvancedFiltering($filters);
$this->set('advancedFilteringActive', $advancedFiltering['active'] ? 1 : 0);
$this->set('advancedFilteringActiveRules', $advancedFiltering['activeRules']);
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('mayModify', $this->__canModifyEvent($event, $user));
$this->set('mayPublish', $this->__canPublishEvent($event));
$this->response->disableCache();
@ -1418,7 +1383,7 @@ class EventsController extends AppController
}
if (!empty($filters['includeSightingdb']) && Configure::read('Plugin.Sightings_sighting_db_enable')) {
$this->set('sightingdbs', $this->Sightingdb->getSightingdbList($this->Auth->user()));
$this->set('sightingdbs', $this->Sightingdb->getSightingdbList($user));
}
$this->set('currentUri', $this->request->here);
$this->layout = false;
@ -1658,10 +1623,10 @@ class EventsController extends AppController
$this->set('object_count', $objectCount);
$this->set('warnings', $this->Event->generateWarnings($event));
$this->set('menuData', array('menuList' => 'event', 'menuItem' => 'viewEvent'));
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('mayModify', $this->__canModifyEvent($event, $user));
$this->set('mayPublish', $this->__canPublishEvent($event));
try {
$instanceKey = $this->Event->CryptographicKey->ingestInstanceKey();
$instanceKey = $event['Event']['protected'] ? $this->Event->CryptographicKey->ingestInstanceKey() : null;
} catch (Exception $e) {
$instanceKey = null;
}
@ -1672,21 +1637,13 @@ class EventsController extends AppController
private function __eventViewCommon(array $user)
{
$this->set('defaultFilteringRules', self::DEFAULT_FILTERING_RULE);
$this->set('typeGroups', array_keys($this->Event->Attribute->typeGroupings));
$this->set('typeGroups', array_keys(Attribute::TYPE_GROUPINGS));
$orgTable = $this->Event->Orgc->find('list', array(
'fields' => array('Orgc.id', 'Orgc.name')
));
$this->set('orgTable', $orgTable);
$this->loadModel('Warninglist');
$warninglists = $this->Warninglist->find('list', [
'fields' => ['Warninglist.id', 'Warninglist.name'],
'order' => ['Warninglist.name'],
'conditions' => ['Warninglist.enabled' => true],
]);
$this->set('warninglists', $warninglists);
$dataForView = array(
'Attribute' => array('attrDescriptions' => 'fieldDescriptions', 'distributionDescriptions' => 'distributionDescriptions', 'distributionLevels' => 'distributionLevels', 'shortDist' => 'shortDist'),
'Event' => array('eventDescriptions' => 'fieldDescriptions', 'analysisDescriptions' => 'analysisDescriptions', 'analysisLevels' => 'analysisLevels')
@ -2008,7 +1965,7 @@ class EventsController extends AppController
* @param string $searchFor
* @param string|false $filterColumnsOverwrite
*/
private function __applyQueryString(&$event, $searchFor, $filterColumnsOverwrite=false)
private function __applyQueryString(&$event, $searchFor, $filterColumnsOverwrite = false)
{
// filtering on specific columns is specified
if ($filterColumnsOverwrite !== false) {
@ -2016,7 +1973,7 @@ class EventsController extends AppController
} else {
$filterColumnsOverwrite = Configure::read('MISP.event_view_filter_fields') ?: 'id,uuid,value,comment,type,category,Tag.name';
$filterValue = array_map('trim', explode(",", $filterColumnsOverwrite));
$validFilters = array('id', 'uuid', 'value', 'comment', 'type', 'category', 'Tag.name');
$validFilters = ['id', 'uuid', 'value', 'comment', 'type', 'category', 'Tag.name'];
foreach ($filterValue as $k => $v) {
if (!in_array($v, $validFilters, true)) {
unset($filterValue[$k]);
@ -2027,41 +1984,81 @@ class EventsController extends AppController
$searchParts = explode('|', mb_strtolower($searchFor));
// search in all attributes
foreach ($event['Attribute'] as $k => $attribute) {
if (!$this->__valueInFieldAttribute($attribute, $filterValue, $searchParts)) {
unset($event['Attribute'][$k]);
$foundAttributes = [];
foreach ($event['Attribute'] as $attribute) {
if ($this->__valueInFieldAttribute($attribute, $filterValue, $searchParts)) {
$foundAttributes[] = $attribute;
}
}
$event['Attribute'] = array_values($event['Attribute']);
$event['Attribute'] = $foundAttributes;
// search in all attributes
foreach ($event['ShadowAttribute'] as $k => $proposals) {
if (!$this->__valueInFieldAttribute($proposals, $filterValue, $searchParts)) {
unset($event['ShadowAttribute'][$k]);
// search in all proposals
$foundProposals = [];
foreach ($event['ShadowAttribute'] as $proposals) {
if ($this->__valueInFieldAttribute($proposals, $filterValue, $searchParts)) {
$foundProposals[] = $proposals;
}
}
$event['ShadowAttribute'] = array_values($event['ShadowAttribute']);
$event['ShadowAttribute'] = $foundProposals;
// search for all attributes in object
foreach ($event['Object'] as $k => $object) {
if ($this->__valueInFieldAttribute($object, ['id', 'uuid', 'name', 'comment'], $searchParts)) {
continue;
}
foreach ($object['Attribute'] as $k2 => $attribute) {
if (!$this->__valueInFieldAttribute($attribute, $filterValue, $searchParts)) {
unset($event['Object'][$k]['Attribute'][$k2]);
$foundAttributes = [];
foreach ($object['Attribute'] as $attribute) {
if ($this->__valueInFieldAttribute($attribute, $filterValue, $searchParts)) {
$foundAttributes[] = $attribute;
}
}
if (empty($event['Object'][$k]['Attribute'])) {
// remove object if empty
unset($event['Object'][$k]);
if (empty($foundAttributes)) {
unset($event['Object'][$k]); // remove object if contains no attributes
} else {
$event['Object'][$k]['Attribute'] = array_values($event['Object'][$k]['Attribute']);
$event['Object'][$k]['Attribute'] = $foundAttributes;
}
}
$event['Object'] = array_values($event['Object']);
}
/**
* Search for a value on an attribute level for a specific field.
*
* @param array $attribute An attribute
* @param array $fields List of keys in attribute to search in
* @param array $searchParts Values to search (OR)
* @return bool Returns true on match
*/
private function __valueInFieldAttribute($attribute, $fields, $searchParts)
{
foreach ($fields as $field) {
if ($field === 'Tag.name') {
if (empty($attribute['AttributeTag'])) {
continue;
}
foreach ($attribute['AttributeTag'] as $fieldValue) {
$fieldValue = mb_strtolower($fieldValue['Tag']['name']);
foreach ($searchParts as $s) {
if (strpos($fieldValue, $s) !== false) {
return true;
}
}
}
} else {
if (!isset($attribute[$field])) {
continue;
}
$fieldValue = mb_strtolower($attribute[$field]);
foreach ($searchParts as $s) {
if (strpos($fieldValue, $s) !== false) {
return true;
}
}
}
}
return false;
}
// look in the parameters if we are doing advanced filtering or not
private function __checkIfAdvancedFiltering($filters)
{
@ -2335,36 +2332,38 @@ class EventsController extends AppController
{
if ($this->request->is('post')) {
$results = array();
if (!empty($this->data)) {
if (!isset($this->data['Event']['submittedfile'])) {
if (!empty($this->request->data)) {
if (!empty($this->request->data['Event']['filecontent'])) {
$data = $this->request->data['Event']['filecontent'];
$isXml = $data[0] === '<';
} elseif (isset($this->request->data['Event']['submittedfile'])) {
$file = $this->request->data['Event']['submittedfile'];
if ($file['error'] === UPLOAD_ERR_NO_FILE) {
$this->Flash->error(__('No file was uploaded.'));
$this->redirect(['controller' => 'events', 'action' => 'add_misp_export']);
}
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (($ext !== 'xml' && $ext !== 'json') && $file['size'] > 0 && is_uploaded_file($file['tmp_name'])) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'file_upload', 'Event', 0, 'MISP export file upload failed', 'File details: ' . json_encode($file));
$this->Flash->error(__('You may only upload MISP XML or MISP JSON files.'));
throw new MethodNotAllowedException(__('File upload failed or file does not have the expected extension (.xml / .json).'));
}
$isXml = $ext === 'xml';
$data = FileAccessTool::readFromFile($file['tmp_name'], $file['size']);
} else {
throw new MethodNotAllowedException(__('No file uploaded.'));
}
$file = $this->data['Event']['submittedfile'];
if ($file['error'] === UPLOAD_ERR_NO_FILE) {
$this->Flash->error(__('No file was uploaded.'));
$this->redirect(['controller' => 'events', 'action' => 'add_misp_export']);
}
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (($ext !== 'xml' && $ext !== 'json') && $file['size'] > 0 && is_uploaded_file($file['tmp_name'])) {
$log = ClassRegistry::init('Log');
// #TODO Think about whether we want to Localize Log entries.
$log->createLogEntry($this->Auth->user(), 'file_upload', 'Event', 0, 'MISP export file upload failed', 'File details: ' . json_encode($file));
$this->Flash->error(__('You may only upload MISP XML or MISP JSON files.'));
throw new MethodNotAllowedException(__('File upload failed or file does not have the expected extension (.xml / .json).'));
}
$isXml = $ext === 'xml';
App::uses('FileAccessTool', 'Tools');
$data = FileAccessTool::readFromFile($file['tmp_name'], $file['size']);
$takeOwnership = Configure::read('MISP.take_ownership_xml_import')
&& (isset($this->data['Event']['takeownership']) && $this->data['Event']['takeownership'] == 1);
&& (isset($this->request->data['Event']['takeownership']) && $this->request->data['Event']['takeownership'] == 1);
try {
$results = $this->Event->addMISPExportFile($this->Auth->user(), $data, $isXml, $takeOwnership, $this->data['Event']['publish']);
$results = $this->Event->addMISPExportFile($this->Auth->user(), $data, $isXml, $takeOwnership, $this->request->data['Event']['publish']);
} catch (Exception $e) {
$this->log("Exception during processing MISP file import '{$file['name']}': {$e->getMessage()}");
$this->log("Exception during processing MISP file import: {$e->getMessage()}");
$this->Flash->error(__('Could not process MISP export file. Probably file content is invalid.'));
$this->redirect(['controller' => 'events', 'action' => 'add_misp_export']);
}
@ -2961,8 +2960,12 @@ class EventsController extends AppController
$result = $this->Event->publishRouter($event['Event']['id'], null, $this->Auth->user());
if (!Configure::read('MISP.background_jobs')) {
if (!is_array($result)) {
// redirect to the view event page
$message = __('Event published without alerts');
if ($result === true) {
$message = __('Event published without alerts');
} else {
$message = __('Event publishing failed due to a blocking module failing. The reason for the failure: %s', $result);
$errors['Module'] = 'Module failure.';
}
} else {
$lastResult = array_pop($result);
$resultString = (count($result) > 0) ? implode(', ', $result) . ' and ' . $lastResult : $lastResult;
@ -2970,11 +2973,6 @@ class EventsController extends AppController
$message = __('Event published but not pushed to %s, re-try later. If the issue persists, make sure that the correct sync user credentials are used for the server link and that the sync user on the remote server has authentication privileges.', $resultString);
}
} else {
// update the DB to set the published flag
// for background jobs, this should be done already
$event['Event']['published'] = 1;
$event['Event']['publish_timestamp'] = time();
$this->Event->save($event, true, ['id', 'published', 'publish_timestamp', 'info']); // info field is required because of SysLogLogableBehavior
$message = 'Job queued';
}
if ($this->_isRest()) {
@ -2984,7 +2982,11 @@ class EventsController extends AppController
return $this->RestResponse->saveSuccessResponse('Events', 'publish', $event['Event']['id'], false, $message);
}
} else {
$this->Flash->success($message);
if (!empty($errors)) {
$this->Flash->error($message);
} else {
$this->Flash->success($message);
}
$this->redirect(array('action' => 'view', $event['Event']['id']));
}
} else {
@ -3021,13 +3023,19 @@ class EventsController extends AppController
$errors['failed_servers'] = $result;
$message = __('Not published given no connection to %s but email sent to all participants.', $resultString);
}
} elseif (!is_bool($emailResult)) {
// Performs all the actions required to publish an event
$result = $this->Event->publishRouter($event['Event']['id'], null, $this->Auth->user());
if (!is_array($result)) {
if ($result === true) {
$message = __('Published but no email sent given GnuPG is not configured.');
$errors['GnuPG'] = 'GnuPG not set up.';
} else {
$message = $result;
$errors['Module'] = 'Module failure.';
}
// redirect to the view event page
$message = __('Published but no email sent given GnuPG is not configured.');
$errors['GnuPG'] = 'GnuPG not set up.';
} else {
$lastResult = array_pop($result);
$resultString = (count($result) > 0) ? implode(', ', $result) . ' and ' . $lastResult : $lastResult;
@ -3154,9 +3162,6 @@ class EventsController extends AppController
public function automation($legacy = false)
{
// Simply display a static view
if (!$this->userRole['perm_auth']) {
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
App::uses('BroExport', 'Export');
$export = new BroExport();
$temp = $export->mispTypes;
@ -3184,7 +3189,7 @@ class EventsController extends AppController
}
$rpzSettings = $this->Server->retrieveCurrentSettings('Plugin', 'RPZ_');
$this->set('rpzSettings', $rpzSettings);
$this->set('hashTypes', array_keys($this->Event->Attribute->hashTypes));
$this->set('hashTypes', array_keys(Attribute::FILE_HASH_TYPES));
if ($legacy) {
$this->render('legacy_automation');
}
@ -3274,7 +3279,10 @@ class EventsController extends AppController
$exportTypes[$k]['progress'] = 0;
}
}
} else {
$exportTypes = [];
}
$this->set('sigTypes', array_keys($this->Event->Attribute->typeDefinitions));
$this->set('export_types', $exportTypes);
}
@ -3314,47 +3322,65 @@ class EventsController extends AppController
return $difference . " " . $periods[$j] . " ago";
}
public function restSearchExport($id=null, $returnFormat=null)
public function restSearchExport($id = null, $returnFormat = null)
{
if (is_null($returnFormat)) {
if (is_numeric($id)) {
$idList = [$id];
} else {
$idList = json_decode($id, true);
}
if ($returnFormat === null) {
$exportFormats = [
'attack' => __('Attack matrix'),
'attack-sightings' => __('Attack matrix by sightings'),
'context' => __('Aggregated context data'),
'context-markdown' => __('Aggregated context data as Markdown'),
'csv' => __('CSV'),
'hashes' => __('Hashes'),
'hosts' => __('Hosts file'),
'json' => __('MISP JSON'),
'netfilter' => __('Netfilter'),
'opendata' => __('Open data'),
'openioc' => __('OpenIOC'),
'rpz' => __('RPZ'),
'snort' => __('Snort rules'),
'stix' => __('STIX 1 XML'),
'stix-json' => __('STIX 1 JSON'),
'stix2' => __('STIX 2'),
'suricata' => __('Suricata rules'),
'text' => __('Text file'),
'xml' => __('MISP XML'),
'yara' => __('YARA rules'),
'yara-json' => __('YARA rules (JSON)'),
];
$idList = is_numeric($id) ? [$id] : $this->_jsonDecode($id);
if (empty($idList)) {
throw new NotFoundException(__('Invalid input.'));
}
$this->set('idList', $idList);
$this->set('exportFormats', array_keys($this->Event->validFormats));
$this->set('exportFormats', $exportFormats);
$this->render('ajax/eventRestSearchExportConfirmationForm');
} else {
$returnFormat = empty($this->Event->validFormats[$returnFormat]) ? 'json' : $returnFormat;
$returnFormat = !isset($this->Event->validFormats[$returnFormat]) ? 'json' : $returnFormat;
$idList = $id;
if (!is_array($idList)) {
if (is_numeric($idList) || Validation::uuid($idList)) {
$idList = array($idList);
} else {
$idList = $this->Event->jsonDecode($idList);
$idList = $this->_jsonDecode($idList);
}
}
if (empty($idList)) {
throw new NotFoundException(__('Invalid input.'));
}
$filters = [
'eventid' => $idList
'eventid' => $idList,
'published' => [true, false], // fetch published and unpublished events
];
$elementCounter = 0;
$renderView = false;
$validFormat = $this->Event->validFormats[$returnFormat];
$responseType = $validFormat[0];
$responseType = $this->Event->validFormats[$returnFormat][0];
$final = $this->Event->restSearch($this->Auth->user(), $returnFormat, $filters, false, false, $elementCounter, $renderView);
if (!empty($renderView) && !empty($final)) {
if ($renderView) {
$final = json_decode($final->intoString(), true);
foreach ($final as $key => $data) {
$this->set($key, $data);
}
$this->set($final);
$this->set('responseType', $responseType);
$this->set('returnFormat', $returnFormat);
$this->set('renderView', $renderView);
@ -3933,7 +3959,7 @@ class EventsController extends AppController
}
$this->set('event_id', $event['Event']['id']);
if ($this->request->is('get')) {
$this->layout = 'ajax';
$this->layout = false;
$this->request->data['Attribute']['event_id'] = $event['Event']['id'];
} else if ($this->request->is('post')) {
@ -4098,29 +4124,31 @@ class EventsController extends AppController
public function filterEventIdsForPush()
{
if ($this->request->is('post')) {
$incomingIDs = array();
$incomingEvents = array();
foreach ($this->request->data as $event) {
$incomingIDs[] = $event['Event']['uuid'];
$incomingEvents[$event['Event']['uuid']] = $event['Event']['timestamp'];
}
$events = $this->Event->find('all', array(
'conditions' => array('Event.uuid' => $incomingIDs),
'recursive' => -1,
'fields' => array('Event.uuid', 'Event.timestamp', 'Event.locked'),
));
foreach ($events as $event) {
if ($event['Event']['timestamp'] >= $incomingEvents[$event['Event']['uuid']]) {
unset($incomingEvents[$event['Event']['uuid']]);
continue;
}
if ($event['Event']['locked'] == 0) {
unset($incomingEvents[$event['Event']['uuid']]);
}
}
return $this->RestResponse->viewData(array_keys($incomingEvents), $this->response->type());
if (!$this->request->is('post')) {
throw new MethodNotAllowedException(__('This endpoint requires a POST request.'));
}
$incomingUuids = [];
$incomingEvents = [];
foreach ($this->request->data as $event) {
$incomingUuids[] = $event['Event']['uuid'];
$incomingEvents[$event['Event']['uuid']] = $event['Event']['timestamp'];
}
$events = $this->Event->find('all', [
'conditions' => ['Event.uuid' => $incomingUuids],
'recursive' => -1,
'fields' => ['Event.uuid', 'Event.timestamp', 'Event.locked'],
]);
foreach ($events as $event) {
if ($event['Event']['timestamp'] >= $incomingEvents[$event['Event']['uuid']]) {
unset($incomingEvents[$event['Event']['uuid']]);
continue;
}
if ($event['Event']['locked'] == 0) {
unset($incomingEvents[$event['Event']['uuid']]);
}
}
return $this->RestResponse->viewData(array_keys($incomingEvents), $this->response->type());
}
public function checkuuid($uuid)
@ -4647,18 +4675,16 @@ class EventsController extends AppController
public function viewGraph($id)
{
// Event data are fetched by 'updateGraph', here we need just metadata.
$event = $this->Event->fetchEvent($this->Auth->user(), array(
'eventid' => $id,
'metadata' => true,
));
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
}
$this->set('event', $event[0]);
$this->set('event', $event);
$this->set('scope', 'event');
$this->set('id', $id);
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('mayPublish', $this->__canPublishEvent($event));
$this->set('id', $event['Event']['id']);
}
/*
@ -4673,8 +4699,9 @@ class EventsController extends AppController
public function updateGraph($id, $type = 'event')
{
$user = $this->_closeSession();
$validTools = array('event', 'galaxy', 'tag');
if (!in_array($type, $validTools)) {
if (!in_array($type, $validTools, true)) {
throw new MethodNotAllowedException(__('Invalid type.'));
}
$this->loadModel('Taxonomy');
@ -4682,18 +4709,17 @@ class EventsController extends AppController
App::uses('CorrelationGraphTool', 'Tools');
$grapher = new CorrelationGraphTool();
$data = $this->request->is('post') ? $this->request->data : array();
$grapher->construct($this->Event, $this->Taxonomy, $this->GalaxyCluster, $this->Auth->user(), $data);
$grapher->construct($this->Event, $this->Taxonomy, $this->GalaxyCluster, $user, $data);
$json = $grapher->buildGraphJson($id, $type);
array_walk_recursive($json, function (&$item, $key) {
if (!mb_detect_encoding($item, 'utf-8', true)) {
$item = utf8_encode($item);
}
});
$this->response->type('json');
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
return $this->RestResponse->viewData($json, 'json');
}
private function genDistributionGraph($id, $type = 'event', $extended = 0, $user = null)
private function __genDistributionGraph($id, $type = 'event', $extended = 0, $user = null)
{
$validTools = array('event');
if (!in_array($type, $validTools)) {
@ -4749,12 +4775,9 @@ class EventsController extends AppController
public function getDistributionGraph($id, $type = 'event')
{
// Close session without writing changes to them.
$user = $this->Auth->user();
session_abort();
$user = $this->_closeSession();
$extended = isset($this->params['named']['extended']) ? 1 : 0;
$json = $this->genDistributionGraph($id, $type, $extended, $user);
$json = $this->__genDistributionGraph($id, $type, $extended, $user);
return $this->RestResponse->viewData($json, 'json');
}
@ -4876,7 +4899,7 @@ class EventsController extends AppController
return $this->RestResponse->viewData($json, 'json');
}
public function viewGalaxyMatrix($scope_id, $galaxy_id, $scope='event', $disable_picking=false)
public function viewGalaxyMatrix($scope_id, $galaxy_id, $scope='event', $disable_picking=false, $extended=false)
{
$this->loadModel('Galaxy');
$mitreAttackGalaxyId = $this->Galaxy->getMitreAttackGalaxyId();
@ -4921,10 +4944,18 @@ class EventsController extends AppController
}
if ($scope !== 'tag_collection') {
$event = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $eventId, 'metadata' => true));
$event = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $eventId, 'metadata' => true, 'extended' => $extended));
if (empty($event)) {
throw new NotFoundException(__('Event not found or you are not authorised to view it.'));
}
if ($extended) {
$eventIds = array();
$eventIds[] = $eventId;
foreach ($event[0]['Event']['extensionEvents'] as $extensionEvent) {
$eventIds[] = $extensionEvent['id'];
}
$eventId = $eventIds;
}
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($this->Auth->user(), $eventId, $matrixTags);
$scoresDataEvent = $this->Event->EventTag->getTagScores($eventId, $matrixTags);
$maxScore = 0;
@ -5103,7 +5134,14 @@ class EventsController extends AppController
if (!Configure::read('Plugin.' . $type . '_services_enable')) {
throw new MethodNotAllowedException(__('%s services are not enabled.', $type));
}
$attribute = $this->Event->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $attribute_id), 'flatten' => 1));
$attribute = $this->Event->Attribute->fetchAttributes($this->Auth->user(), [
'conditions' => [
'Attribute.id' => $attribute_id
],
'flatten' => 1,
'includeEventTags' => 1,
'contain' => ['Event' => ['fields' => ['distribution', 'sharing_group_id']]],
]);
if (empty($attribute)) {
throw new MethodNotAllowedException(__('Attribute not found or you are not authorised to see it.'));
}
@ -5164,7 +5202,7 @@ class EventsController extends AppController
if (!empty($options)) {
$data['config'] = $options;
}
$result = $this->Module->queryModuleServer($data, false, $type);
$result = $this->Module->queryModuleServer($data, false, $type, false, $attribute[0]);
if (!$result) {
throw new InternalErrorException(__('%s service not reachable.', $type));
}
@ -5210,7 +5248,7 @@ class EventsController extends AppController
if (!empty($options)) {
$data['config'] = $options;
}
$result = $this->Module->queryModuleServer($data, false, $type);
$result = $this->Module->queryModuleServer($data, false, $type, false, $attribute[0]);
if (!$result) {
throw new InternalErrorException(__('%s service not reachable.', $type));
}
@ -5480,7 +5518,7 @@ class EventsController extends AppController
if ($event['Event']['disable_correlation']) {
$event['Event']['disable_correlation'] = 0;
$this->Event->save($event);
$this->Event->Attribute->generateCorrelation(false, 0, $event['Event']['id']);
$this->Event->Attribute->generateCorrelation(false, $event['Event']['id']);
} else {
$event['Event']['disable_correlation'] = 1;
$this->Event->save($event);
@ -5500,7 +5538,8 @@ class EventsController extends AppController
public function checkPublishedStatus($id)
{
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id, ['fields' => 'Event.published']);
$user = $this->_closeSession();
$event = $this->Event->fetchSimpleEvent($user, $id, ['fields' => 'Event.published']);
if (empty($event)) {
throw new NotFoundException(__('Invalid event'));
}
@ -5594,24 +5633,25 @@ class EventsController extends AppController
public function getEventInfoById($id)
{
$user = $this->_closeSession();
if (empty($id)) {
throw new MethodNotAllowedException(__('Invalid ID.'));
}
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id, [
$event = $this->Event->fetchSimpleEvent($user, $id, [
'fields' => ['Event.id', 'Event.info', 'Event.threat_level_id', 'Event.analysis'],
'contain' => ['EventTag' => ['Tag.id', 'Tag.name', 'Tag.colour'], 'ThreatLevel.name'],
]);
if ($this->_isRest()) {
return $this->RestResponse->viewData($event, $this->response->type());
} else {
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
}
$this->set('analysisLevels', $this->Event->analysisLevels);
$this->set('validUuid', Validation::uuid($id));
$this->set('id', $id);
$this->set('event', $event);
}
if ($this->request->is('ajax')) {
$this->layout = false;
}
$this->set('analysisLevels', $this->Event->analysisLevels);
$this->set('validUuid', Validation::uuid($id));
$this->set('id', $id);
$this->set('event', $event);
}
public function enrichEvent($id)
@ -5650,7 +5690,7 @@ class EventsController extends AppController
} else {
$this->loadModel('Module');
$modules = $this->Module->getEnabledModules($this->Auth->user(), 'expansion');
$this->layout = 'ajax';
$this->layout = false;
$this->set('modules', $modules);
$this->render('ajax/enrich_event');
}
@ -5693,9 +5733,7 @@ class EventsController extends AppController
public function checkLocks($id, $timestamp)
{
// Close session without writing changes to them.
$user = $this->Auth->user();
session_abort();
$user = $this->_closeSession();
$event = $this->Event->find('first', array(
'recursive' => -1,
@ -6065,6 +6103,10 @@ class EventsController extends AppController
public function runTaxonomyExclusivityCheck($id)
{
if (Configure::read('MISP.disable_taxonomy_consistency_checks')) {
return $this->RestResponse->saveFailResponse('Events', 'runTaxonomyExclusivityCheck', null, 'Taxonomy consistency checks are disabled, set `MISP.disable_taxonomy_consistency_checks` to `false` to enable them.', 'json');
}
$conditions = [];
if (is_numeric($id)) {
$conditions = array('eventid' => $id);
@ -6220,7 +6262,7 @@ class EventsController extends AppController
__('Are you sure you want to switch the event to unprotected mode? Unprotected mode is the default behaviour of MISP events, with creation and modification being purely limited by the distribution mechanism and eligible sync users.')
);
$this->set('actionName', $protect ? __('Switch to protected mode') : __('Remove protected mode'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}

View File

@ -52,7 +52,7 @@ class FavouriteTagsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException('This action is available via AJAX only.');
}
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/getToggleField');
}
}

View File

@ -1,6 +1,9 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property Galaxy $Galaxy
*/
class GalaxiesController extends AppController
{
public $components = array('Session', 'RequestHandler');
@ -316,17 +319,17 @@ class GalaxiesController extends AppController
public function selectGalaxy($target_id, $target_type='event', $namespace='misp', $noGalaxyMatrix = false)
{
$this->_closeSession();
$mitreAttackGalaxyId = $this->Galaxy->getMitreAttackGalaxyId();
$local = !empty($this->params['named']['local']) ? $this->params['named']['local'] : '0';
$eventid = !empty($this->params['named']['eventid']) ? $this->params['named']['eventid'] : '0';
$conditions = $namespace === '0' ? array() : array('namespace' => $namespace);
$conditions[] = [
'enabled' => true
];
if(!$local) {
$conditions[] = [
'local_only' => 0
];
$conditions = ['enabled' => true];
if ($namespace !== '0') {
$conditions['namespace'] = $namespace;
}
if (!$local) {
$conditions['local_only'] = false;
}
$galaxies = $this->Galaxy->find('all', array(
'recursive' => -1,
@ -380,21 +383,21 @@ class GalaxiesController extends AppController
public function selectGalaxyNamespace($target_id, $target_type='event', $noGalaxyMatrix = false)
{
$namespaces = $this->Galaxy->find('list', array(
$this->_closeSession();
$namespaces = $this->Galaxy->find('column', array(
'recursive' => -1,
'fields' => array('namespace', 'namespace'),
'fields' => array('namespace'),
'conditions' => array('enabled' => 1),
'group' => array('namespace'),
'unique' => true,
'order' => array('namespace asc')
));
$local = !empty($this->params['named']['local']) ? '1' : '0';
$eventid = !empty($this->params['named']['eventid']) ? $this->params['named']['eventid'] : '0';
$items = array();
$noGalaxyMatrix = $noGalaxyMatrix ? '1' : '0';
$items[] = array(
$items = [[
'name' => __('All namespaces'),
'value' => $this->baseurl . "/galaxies/selectGalaxy/" . $target_id . '/' . $target_type . '/0' . '/' . $noGalaxyMatrix . '/local:' . $local . '/eventid:' . $eventid
);
]];
foreach ($namespaces as $namespace) {
$items[] = array(
'name' => $namespace,
@ -411,7 +414,7 @@ class GalaxiesController extends AppController
public function selectCluster($target_id, $target_type = 'event', $selectGalaxy = false)
{
$conditions = array();
$user = $this->_closeSession();
$conditions = array(
'OR' => array(
'GalaxyCluster.published' => true,
@ -427,92 +430,79 @@ class GalaxiesController extends AppController
if ($selectGalaxy) {
$conditions['GalaxyCluster.galaxy_id'] = $selectGalaxy;
}
$local = !empty($this->params['named']['local']) ? $this->params['named']['local'] : '0';
$data = $this->Galaxy->GalaxyCluster->fetchGalaxyClusters($this->Auth->user(), array(
'conditions' => $conditions,
'fields' => array('value', 'description', 'source', 'type', 'id', 'uuid'),
'order' => array('value asc'),
), false);
$clusters = array();
$cluster_ids = array();
foreach ($data as $k => $cluster) {
$cluster_ids[] = $cluster['GalaxyCluster']['id'];
}
$data = array_column($this->Galaxy->GalaxyCluster->fetchGalaxyClusters($user, array(
'conditions' => $conditions,
'fields' => array('value', 'description', 'source', 'type', 'id', 'uuid'),
'order' => array('value asc'),
)), 'GalaxyCluster');
$synonyms = $this->Galaxy->GalaxyCluster->GalaxyElement->find('all', array(
'conditions' => array(
'GalaxyElement.galaxy_cluster_id' => $cluster_ids,
'GalaxyElement.key' => 'synonyms'
'GalaxyElement.key' => 'synonyms',
$conditions
),
'fields' => ['GalaxyElement.galaxy_cluster_id', 'GalaxyElement.value'],
'contain' => 'GalaxyCluster',
'recursive' => -1
));
$sorted_synonyms = array();
$sortedSynonyms = array();
foreach ($synonyms as $synonym) {
$sorted_synonyms[$synonym['GalaxyElement']['galaxy_cluster_id']][] = $synonym;
$sortedSynonyms[$synonym['GalaxyElement']['galaxy_cluster_id']][] = $synonym['GalaxyElement']['value'];
}
foreach ($data as $k => $cluster) {
$cluster['GalaxyCluster']['synonyms_string'] = array();
if (!empty($sorted_synonyms[$cluster['GalaxyCluster']['id']])) {
foreach ($sorted_synonyms[$cluster['GalaxyCluster']['id']] as $element) {
$cluster['GalaxyCluster']['synonyms_string'][] = $element['GalaxyElement']['value'];
$cluster['GalaxyElement'][] = $element['GalaxyElement'];
}
unset($sorted_synonyms[$cluster['GalaxyCluster']['id']]);
$clusters = [];
foreach ($data as $cluster) {
if (!empty($sortedSynonyms[$cluster['id']])) {
$cluster['synonyms_string'] = implode(', ', $sortedSynonyms[$cluster['id']]);
}
$cluster['GalaxyCluster']['synonyms_string'] = implode(', ', $cluster['GalaxyCluster']['synonyms_string']);
unset($cluster['GalaxyElement']);
$clusters[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['uuid']] = $cluster['GalaxyCluster'];
$clusters[$cluster['type']][$cluster['uuid']] = $cluster;
}
ksort($clusters);
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$items = array();
foreach ($clusters as $namespace => $cluster_data) {
foreach ($cluster_data as $k => $cluster) {
$name = $cluster['value'];
foreach ($clusters as $cluster_data) {
foreach ($cluster_data as $cluster) {
$optionName = $cluster['value'];
if ($cluster['synonyms_string'] !== '') {
$synom = __('Synonyms: ') . $cluster['synonyms_string'];
$optionName .= $cluster['synonyms_string'] !== '' ? ' (' . $cluster['synonyms_string'] . ')' : '';
} else {
$synom = '';
if (isset($cluster['synonyms_string'])) {
$optionName .= ' (' . $cluster['synonyms_string'] . ')';
}
$itemParam = array(
'name' => $optionName,
'value' => $cluster['id'],
'template' => array(
'name' => $name,
'name' => $cluster['value'],
'infoExtra' => $cluster['description'],
),
'additionalData' => array(
'uuid' => $cluster['uuid']
)
);
if ($cluster['synonyms_string'] !== '') {
$itemParam['template']['infoContextual'] = $synom;
if (isset($cluster['synonyms_string'])) {
$itemParam['template']['infoContextual'] = __('Synonyms: ') . $cluster['synonyms_string'];
}
$items[] = $itemParam;
unset($cluster_data[$k]);
}
}
$onClickForm = 'quickSubmitGalaxyForm';
if ($this->_isRest()) {
return $this->RestResponse->viewData($items, $this->response->type());
} else {
$this->set('items', $items);
$this->set('options', array( // set chosen (select picker) options
'functionName' => $onClickForm,
'multiple' => $target_type == 'galaxyClusterRelation' ? 0 : '-1',
'select_options' => array(
'additionalData' => array(
'target_id' => $target_id,
'target_type' => $target_type,
'local' => $local
)
),
));
$this->render('ajax/cluster_choice');
}
$mirrorOnEventEnabled = Configure::read("MISP.enable_clusters_mirroring_from_attributes_to_event");
$mirrorOnEvent = $mirrorOnEventEnabled && $target_type == 'attribute';
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$this->set('mirrorOnEvent', $mirrorOnEvent);
$this->set('items', $items);
$local = !empty($this->params['named']['local']) ? $this->params['named']['local'] : '0';
$this->set('options', array( // set chosen (select picker) options
'functionName' => 'quickSubmitGalaxyForm',
'multiple' => $target_type == 'galaxyClusterRelation' ? 0 : '-1',
'select_options' => array(
'additionalData' => array(
'target_id' => $target_id,
'target_type' => $target_type,
'local' => $local
)
),
));
$this->render('ajax/cluster_choice');
}
public function attachCluster($target_id, $target_type = 'event')
@ -526,7 +516,10 @@ class GalaxiesController extends AppController
public function attachMultipleClusters($target_id, $target_type = 'event')
{
$local = !empty($this->params['named']['local']);
$mirrorOnEventEnabled = Configure::read("MISP.enable_clusters_mirroring_from_attributes_to_event");
$mirrorOnEvent = $mirrorOnEventEnabled && $target_type == 'attribute';
$this->set('local', $local);
$this->set('mirrorOnEvent', $mirrorOnEvent);
if ($this->request->is('post')) {
if ($target_id === 'selected') {
$target_id_list = json_decode($this->request->data['Galaxy']['attribute_ids']);
@ -534,14 +527,25 @@ class GalaxiesController extends AppController
$target_id_list = array($target_id);
}
$cluster_ids = $this->request->data['Galaxy']['target_ids'];
$mirrorOnEventRequested = $mirrorOnEvent && !empty($this->request->data['Galaxy']['mirror_on_event']);
if (strlen($cluster_ids) > 0) {
$cluster_ids = json_decode($cluster_ids, true);
if ($cluster_ids === null || empty($cluster_ids)) {
$cluster_ids = $this->_jsonDecode($cluster_ids);
if (empty($cluster_ids)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Failed to parse request or no clusters picked.'))), 'status'=>200, 'type' => 'json'));
}
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Failed to parse request.'))), 'status'=>200, 'type' => 'json'));
}
if ($mirrorOnEventRequested && !empty($target_id_list)) {
$first_attribute_id = $target_id_list[0]; // We consider that all attributes to be tagged are contained in the same event.
$this->loadModel('Attribute');
$attribute = $this->Attribute->fetchAttributeSimple($this->Auth->user(), array('conditions' => array('Attribute.id' => $first_attribute_id), 'flatten' => 1));
if (!empty($attribute['Attribute']['event_id'])) {
$event_id = $attribute['Attribute']['event_id'];
} else {
return new CakeResponse(array('body' => json_encode(array('saved' => false, 'errors' => __('Failed to parse request. Could not fetch attribute'))), 'status' => 200, 'type' => 'json'));
}
}
$result = "";
if (!is_array($cluster_ids)) { // in case we only want to attach 1
$cluster_ids = array($cluster_ids);
@ -549,6 +553,9 @@ class GalaxiesController extends AppController
foreach ($cluster_ids as $cluster_id) {
foreach ($target_id_list as $target_id) {
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id, $local);
if ($mirrorOnEventRequested) {
$result = $result && $this->Galaxy->attachCluster($this->Auth->user(), 'event', $event_id, $cluster_id, $local);
}
}
}
if ($this->request->is('ajax')) {
@ -558,6 +565,7 @@ class GalaxiesController extends AppController
$this->redirect($this->referer());
}
} else {
$this->set('local', $local);
$this->set('target_id', $target_id);
$this->set('target_type', $target_type);
$this->layout = false;
@ -586,29 +594,32 @@ class GalaxiesController extends AppController
public function showGalaxies($id, $scope = 'event')
{
$this->layout = 'ajax';
$this->set('scope', $scope);
if ($scope == 'event') {
if ($scope === 'event') {
$this->loadModel('Event');
$object = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id, 'metadata' => 1));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid event.');
throw new NotFoundException('Invalid event.');
}
$this->set('object', $object[0]);
} elseif ($scope == 'attribute') {
} elseif ($scope === 'attribute') {
$this->loadModel('Attribute');
$object = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id), 'flatten' => 1));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid attribute.');
throw new NotFoundException('Invalid attribute.');
}
$object[0] = $this->Attribute->Event->massageTags($this->Auth->user(), $object[0], 'Attribute');
} elseif ($scope == 'tag_collection') {
} elseif ($scope === 'tag_collection') {
$this->loadModel('TagCollection');
$object = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $id)));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid Tag Collection.');
throw new NotFoundException('Invalid Tag Collection.');
}
} else {
throw new NotFoundException("Invalid scope.");
}
$this->layout = false;
$this->set('scope', $scope);
$this->set('object', $object[0]);
$this->render('/Events/ajax/ajaxGalaxies');
}

View File

@ -72,8 +72,6 @@ class GalaxyClusterRelationsController extends AppController
$this->paginate['contain'] = array('SharingGroup', 'SourceCluster' => ['Org', 'Orgc'], 'TargetCluster', 'GalaxyClusterRelationTag' => array('Tag'));
$relations = $this->paginate();
$relations = $this->GalaxyClusterRelation->removeNonAccessibleTargetCluster($this->Auth->user(), $relations);
$this->loadModel('SharingGroup');
$sgs = $this->SharingGroup->fetchAllAuthorised($this->Auth->user());
$this->loadModel('Attribute');
$distributionLevels = $this->Attribute->distributionLevels;
unset($distributionLevels[5]);

View File

@ -155,7 +155,7 @@ class GalaxyClustersController extends AppController
$this->set('custom_cluster_count', $customClusterCount);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/index');
}
}
@ -545,162 +545,32 @@ class GalaxyClustersController extends AppController
}
}
public function attachToEvent($event_id, $tag_name)
{
$this->loadModel('Event');
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
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'])) {
throw new MethodNotAllowedException('Invalid Event.');
}
}
$tag = $this->Event->EventTag->Tag->find('first', array('conditions' => array('Tag.name' => $tag_name), 'recursive' => -1));
if (empty($tag)) {
$this->Event->EventTag->Tag->create();
$this->Event->EventTag->Tag->save(array('name' => $tag_name, 'colour' => '#0088cc', 'exportable' => 1));
$tag_id = $this->Event->EventTag->Tag->id;
} else {
$tag_id = $tag['Tag']['id'];
}
$existingEventTag = $this->Event->EventTag->find('first', array('conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id), 'recursive' => -1));
if (empty($existingEventTag)) {
$cluster = $this->GalaxyCluster->find('first', array(
'recursive' => -1,
'conditions' => array('GalaxyCluster.tag_name' => $existingEventTag['Tag']['name'])
));
$this->Event->EventTag->create();
$this->Event->EventTag->save(array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $event_id));
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $this->Auth->user('Organisation')['name'],
'model' => 'Event',
'model_id' => $event_id,
'email' => $this->Auth->user('email'),
'action' => 'galaxy',
'title' => 'Attached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') to event (' . $event_id . ')',
'change' => ''
));
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$this->Flash->success('Galaxy attached.');
} else {
$this->Flash->error('Galaxy already attached.');
}
$this->redirect($this->referer());
}
public function detach($target_id, $target_type, $tag_id)
{
$this->loadModel('Event');
if ($target_type == 'attribute') {
$attribute = $this->Event->Attribute->find('first', array(
'recursive' => -1,
'fields' => array('id', 'event_id'),
'conditions' => array('Attribute.id' => $target_id)
));
if (empty($attribute)) {
throw new MethodNotAllowedException('Invalid Attribute.');
}
$event_id = $attribute['Attribute']['event_id'];
} elseif ($target_type == 'event') {
$event_id = $target_id;
} elseif ($target_type === 'tag_collection') {
// pass
} else {
throw new MethodNotAllowedException('Invalid options');
if ($this->request->is('ajax') && $this->request->is('get')) {
$this->set('url', Router::url());
return $this->render('/Elements/emptyForm', false);
}
if ($target_type === 'tag_collection') {
$tag_collection = $this->GalaxyCluster->Tag->TagCollectionTag->TagCollection->fetchTagCollection($this->Auth->user(), array(
'conditions' => array('TagCollection.id' => $target_id),
'contain' => array('Organisation', 'TagCollectionTag' => array('Tag'))
));
if (empty($tag_collection)) {
throw new MethodNotAllowedException('Invalid Tag Collection');
}
$tag_collection = $tag_collection[0];
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_tag_editor'] || $this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id']) {
throw new MethodNotAllowedException('Invalid Tag Collection');
}
}
} else {
$this->Event->id = $event_id;
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $event_id);
if (empty($event)) {
throw new MethodNotAllowedException('Invalid Event.');
}
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'])) {
throw new MethodNotAllowedException('Invalid Event.');
}
}
}
$this->request->allowMethod(['post']);
if ($target_type == 'attribute') {
$existingTargetTag = $this->Event->Attribute->AttributeTag->find('first', array(
'conditions' => array('AttributeTag.tag_id' => $tag_id, 'AttributeTag.attribute_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
} elseif ($target_type == 'event') {
$existingTargetTag = $this->Event->EventTag->find('first', array(
'conditions' => array('EventTag.tag_id' => $tag_id, 'EventTag.event_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
} elseif ($target_type == 'tag_collection') {
$existingTargetTag = $this->GalaxyCluster->Tag->TagCollectionTag->find('first', array(
'conditions' => array('TagCollectionTag.tag_id' => $tag_id, 'TagCollectionTag.tag_collection_id' => $target_id),
'recursive' => -1,
'contain' => array('Tag')
));
}
if (empty($existingTargetTag)) {
$this->Flash->error('Galaxy not attached.');
} else {
$cluster = $this->GalaxyCluster->find('first', array(
'recursive' => -1,
'conditions' => array('GalaxyCluster.tag_name' => $existingTargetTag['Tag']['name'])
));
if ($target_type == 'event') {
$result = $this->Event->EventTag->delete($existingTargetTag['EventTag']['id']);
} elseif ($target_type == 'attribute') {
$result = $this->Event->Attribute->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
} elseif ($target_type == 'tag_collection') {
$result = $this->GalaxyCluster->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
}
if ($result) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$this->Flash->success('Galaxy successfully detached.');
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $this->Auth->user('Organisation')['name'],
'model' => ucfirst($target_type),
'model_id' => $target_id,
'email' => $this->Auth->user('email'),
'action' => 'galaxy',
'title' => 'Detached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') from ' . $target_type . ' (' . $target_id . ')',
'change' => ''
));
try {
$this->GalaxyCluster->Galaxy->detachClusterByTagId($this->Auth->user(), $target_id, $target_type, $tag_id);
} catch (NotFoundException $e) {
if (!$this->request->is('ajax')) {
$this->Flash->error($e->getMessage());
} else {
$this->Flash->error('Could not detach galaxy from event.');
throw $e;
}
}
$message = __('Galaxy successfully detached.');
if ($this->request->is('ajax')) {
return $this->RestResponse->viewData(['saved' => true, 'check_publish' => true, 'success' => $message], 'json');
}
$this->Flash->success($message);
$this->redirect($this->referer());
}

View File

@ -53,7 +53,7 @@ class GalaxyElementsController extends AppController
$this->set('JSONElements', $expanded);
}
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/index');
}
}
@ -82,7 +82,7 @@ class GalaxyElementsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be reached via AJAX.'));
} else {
$this->layout = 'ajax';
$this->layout = false;
$this->set('elementId', $elementId);
$this->render('ajax/delete');
}
@ -110,7 +110,7 @@ class GalaxyElementsController extends AppController
}
$this->set('clusterId', $clusterId);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/flattenJson');
}
}

View File

@ -16,6 +16,15 @@ class JobsController extends AppController
),
);
public function beforeFilter()
{
parent::beforeFilter();
if ($this->request->action === 'getGenerateCorrelationProgress') {
$this->Security->doNotGenerateToken = true;
}
}
public function index($queue = false)
{
if (!Configure::read('MISP.background_jobs')) {
@ -24,9 +33,9 @@ class JobsController extends AppController
$this->loadModel('Server');
$issueCount = 0;
$workers = $this->Server->workerDiagnostics($issueCount);
$queues = array('email', 'default', 'cache', 'prio', 'update');
$queues = ['email', 'default', 'cache', 'prio', 'update'];
if ($queue && in_array($queue, $queues, true)) {
$this->paginate['conditions'] = array('Job.worker' => $queue);
$this->paginate['conditions'] = ['Job.worker' => $queue];
}
$jobs = $this->paginate();
foreach ($jobs as &$job) {
@ -37,9 +46,9 @@ class JobsController extends AppController
$job['Job']['job_status'] = 'Unknown';
$job['Job']['failed'] = null;
}
if(Configure::read('SimpleBackgroundJobs.enabled')){
if (Configure::read('SimpleBackgroundJobs.enabled')) {
$job['Job']['worker_status'] = true;
}else{
} else {
$job['Job']['worker_status'] = isset($workers[$job['Job']['worker']]) && $workers[$job['Job']['worker']]['ok'];
}
}
@ -78,20 +87,27 @@ class JobsController extends AppController
}
}
public function getGenerateCorrelationProgress($id)
public function getGenerateCorrelationProgress($ids)
{
$job = $this->Job->find('first', [
'fields' => ['progress', 'process_id'],
'conditions' => ['id' => $id],
$this->_closeSession();
$ids = explode(",", $ids);
$jobs = $this->Job->find('all', [
'fields' => ['id', 'progress', 'process_id'],
'conditions' => ['id' => $ids],
'recursive' => -1,
]);
if (!$job) {
throw new NotFoundException("Job with ID `$id` not found");
if (empty($jobs)) {
throw new NotFoundException('No jobs found');
}
$output = [];
foreach ($jobs as $job) {
$output[$job['Job']['id']] = [
'job_status' => $this->__getJobStatus($job['Job']['process_id']),
'progress' => (int)$job['Job']['progress'],
];
}
$output = [
'job_status' => $this->__getJobStatus($job['Job']['process_id']),
'progress' => (int)$job['Job']['progress'],
];
return $this->RestResponse->viewData($output, 'json');
}

View File

@ -30,17 +30,17 @@ class LogsController extends AppController
public function admin_index()
{
$paramArray = array('id', 'title', 'created', 'model', 'model_id', 'action', 'user_id', 'change', 'email', 'org', 'description', 'ip');
$filterData = array(
'request' => $this->request,
'named_params' => $this->params['named'],
'paramArray' => $paramArray,
'ordered_url_params' => func_get_args()
);
$exception = false;
$filters = $this->_harvestParameters($filterData, $exception);
unset($filterData);
if ($this->_isRest()) {
$paramArray = array('id', 'title', 'created', 'model', 'model_id', 'action', 'user_id', 'change', 'email', 'org', 'description', 'ip');
$filterData = array(
'request' => $this->request,
'named_params' => $this->params['named'],
'paramArray' => $paramArray,
'ordered_url_params' => func_get_args()
);
$exception = false;
$filters = $this->_harvestParameters($filterData, $exception);
unset($filterData);
if ($filters === false) {
return $exception;
}
@ -100,6 +100,9 @@ class LogsController extends AppController
if (isset($this->params['named']['filter']) && in_array($this->params['named']['filter'], array_keys($validFilters))) {
$this->paginate['conditions']['Log.action'] = $validFilters[$this->params['named']['filter']]['values'];
}
foreach ($filters as $key => $value) {
$this->paginate['conditions']["Log.$key"] = $value;
}
$this->set('validFilters', $validFilters);
$this->set('filter', isset($this->params['named']['filter']) ? $this->params['named']['filter'] : false);
$this->set('list', $this->paginate());
@ -389,6 +392,7 @@ class LogsController extends AppController
'Galaxy',
'GalaxyCluster',
'GalaxyClusterRelation',
'Workflow',
];
sort($models);
$models = array('' => 'ALL') + $this->_arrayToValuesIndexArray($models);

View File

@ -168,7 +168,7 @@ class NoticelistsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException('This action is available via AJAX only.');
}
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/getToggleField');
}

View File

@ -147,7 +147,7 @@ class ObjectReferencesController extends AppController
$this->set('relationships', $relationships);
$this->set('event', $event);
$this->set('objectId', $object['Object']['id']);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/add');
}
}

View File

@ -19,7 +19,7 @@ class ObjectTemplateElementsController extends AppController
$this->paginate['conditions'] = array('ObjectTemplateElement.object_template_id' => $id);
$elements = $this->paginate();
$this->set('list', $elements);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/view_elements');
}
}

View File

@ -9,18 +9,28 @@ class ObjectTemplatesController extends AppController
public $components = array('RequestHandler', 'Session');
public $paginate = array(
'limit' => 60,
'order' => array(
'Object.id' => 'desc'
),
'contain' => array(
'Organisation' => array('fields' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid'))
),
'recursive' => -1
'limit' => 60,
'order' => array(
'Object.id' => 'desc'
),
'contain' => array(
'Organisation' => array('fields' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid'))
),
'recursive' => -1
);
public function objectMetaChoice($event_id)
public function beforeFilter()
{
parent::beforeFilter();
if (in_array($this->request->action, ['objectMetaChoice', 'objectChoice'], true)) {
$this->Security->doNotGenerateToken = true;
}
}
public function objectMetaChoice($eventId)
{
session_abort();
$metas = $this->ObjectTemplate->find('column', array(
'conditions' => array('ObjectTemplate.active' => 1),
'fields' => array('ObjectTemplate.meta-category'),
@ -28,7 +38,6 @@ class ObjectTemplatesController extends AppController
'unique' => true,
));
$eventId = h($event_id);
$items = [[
'name' => __('All Objects'),
'value' => $this->baseurl . "/ObjectTemplates/objectChoice/$eventId/0"
@ -36,7 +45,7 @@ class ObjectTemplatesController extends AppController
foreach ($metas as $meta) {
$items[] = array(
'name' => $meta,
'value' => $this->baseurl . "/ObjectTemplates/objectChoice/$eventId/" . h($meta)
'value' => $this->baseurl . "/ObjectTemplates/objectChoice/$eventId/$meta",
);
}
@ -49,7 +58,8 @@ class ObjectTemplatesController extends AppController
public function objectChoice($event_id, $category=false)
{
$this->ObjectTemplate->populateIfEmpty($this->Auth->user());
$user = $this->_closeSession();
$this->ObjectTemplate->populateIfEmpty($user);
$conditions = array('ObjectTemplate.active' => 1);
if ($category !== false && $category !== "0") {
$conditions['meta-category'] = $category;
@ -158,7 +168,7 @@ class ObjectTemplatesController extends AppController
'conditions' => array('ObjectTemplateElement.object_template_id' => $id)
));
$this->set('list', $elements);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/view_elements');
}
@ -293,7 +303,7 @@ class ObjectTemplatesController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException('This action is available via AJAX only.');
}
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/getToggleField');
}

View File

@ -600,7 +600,7 @@ class ObjectsController extends AppController
}
$this->set('value', $result);
$this->set('field', $field);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/objectViewFieldForm');
}
@ -632,7 +632,7 @@ class ObjectsController extends AppController
if (!$this->__canModifyEvent($object)) {
throw new NotFoundException(__('Invalid object'));
}
$this->layout = 'ajax';
$this->layout = false;
if ($field == 'distribution') {
$distributionLevels = $this->MispObject->shortDist;
unset($distributionLevels[4]);
@ -728,10 +728,9 @@ class ObjectsController extends AppController
if (!isset($fieldName)) {
throw new MethodNotAllowedException('No field requested.');
}
$fields = array('template_uuid', 'template_version', 'id', 'event_id');
$params = array(
'conditions' => array('Object.id' => $id),
'fields' => $fields,
'fields' => array('template_uuid', 'template_version', 'id', 'event_id'),
'flatten' => 1,
'contain' => array(
'Event'
@ -741,9 +740,8 @@ class ObjectsController extends AppController
$object = $this->MispObject->fetchObjects($this->Auth->user(), $params);
if (empty($object)) {
throw new NotFoundException(__('Invalid object'));
} else {
$object = $object[0];
}
$object = $object[0];
if (!$this->__canModifyEvent($object)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
@ -768,25 +766,30 @@ class ObjectsController extends AppController
}
// check if fields can be added
foreach($object['Attribute'] as $i => $objAttr) {
foreach($object['Attribute'] as $objAttr) {
$objectAttrFromTemplate = $template['ObjectTemplateElement'][0];
if ($objAttr['object_relation'] == $fieldName && !$objectAttrFromTemplate['multiple']) {
throw new NotFoundException(__('Invalid field'));
}
}
$template = $this->MispObject->prepareTemplate($template, $object);
$this->layout = 'ajax';
$this->layout = false;
$this->set('object', $object['Object']);
$template_element = $template['ObjectTemplateElement'][0];
unset($template_element['value']); // avoid filling if multiple
$this->set('template_element', $template_element);
$distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user());
$distributionData = $this->MispObject->Attribute->fetchDistributionData($this->Auth->user());
$this->set('distributionData', $distributionData);
$info = array();
foreach ($distributionData['levels'] as $key => $value) {
$info['distribution'][$key] = array('key' => $value, 'desc' => $this->MispObject->Event->Attribute->distributionDescriptions[$key]['formdesc']);
$info = ['category' => [], 'distribution' => []];
foreach ($this->MispObject->Attribute->categoryDefinitions as $key => $value) {
$info['category'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
$this->set('info', $info);
foreach ($this->MispObject->Attribute->distributionLevels as $key => $value) {
$info['distribution'][$key] = $this->MispObject->Attribute->distributionDescriptions[$key]['formdesc'];
}
$this->set('fieldDesc', $info);
$this->render('ajax/quickAddAttributeForm');
} else if ($this->request->is('post') || $this->request->is('put')) {
return $this->edit($this->request->data['Object']['id'], false, true);

View File

@ -39,7 +39,7 @@ class PostsController extends AppController
$event_id = 0;
$post_id = 0;
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->layout = false;
}
// we have a target type and a target id. The target id defines what type of object we want to attach this event to (is it a reply to another post,
// did someone add a post to a thread, does a thread for the event exist already, etc.

View File

@ -949,7 +949,14 @@ class ServersController extends AppController
public function serverSettingsReloadSetting($setting, $id)
{
$pathToSetting = explode('.', $setting);
if (strpos($setting, 'Plugin.Enrichment') !== false || strpos($setting, 'Plugin.Import') !== false || strpos($setting, 'Plugin.Export') !== false || strpos($setting, 'Plugin.Cortex') !== false) {
if (
strpos($setting, 'Plugin.Enrichment') !== false ||
strpos($setting, 'Plugin.Import') !== false ||
strpos($setting, 'Plugin.Export') !== false ||
strpos($setting, 'Plugin.Cortex') !== false ||
strpos($setting, 'Plugin.Action') !== false ||
strpos($setting, 'Plugin.Workflow') !== false
) {
$settingObject = $this->Server->getCurrentServerSettings();
} else {
$settingObject = $this->Server->serverSettings;
@ -997,7 +1004,13 @@ class ServersController extends AppController
$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.'));
$sessionErrors = array(0 => __('OK'), 1 => __('High'), 2 => __('Alternative setting used'), 3 => __('Test failed'));
$sessionErrors = array(
0 => __('OK'),
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'),
8 => __('Alternative setting used'),
9 => __('Test failed')
);
$moduleErrors = array(0 => __('OK'), 1 => __('System not enabled'), 2 => __('No modules found'));
$backgroundJobsErrors = array(
0 => __('OK'),
@ -1060,6 +1073,11 @@ class ServersController extends AppController
$diagnostic_errors = 0;
App::uses('File', 'Utility');
App::uses('Folder', 'Utility');
if ($tab === 'correlations') {
$this->loadModel('Correlation');
$correlation_metrics = $this->Correlation->collectMetrics();
$this->set('correlation_metrics', $correlation_metrics);
}
if ($tab === 'files') {
$files = $this->Server->grabFiles();
$this->set('files', $files);
@ -1141,6 +1159,7 @@ class ServersController extends AppController
// get the DB diagnostics
$dbDiagnostics = $this->Server->dbSpaceUsage();
$dbSchemaDiagnostics = $this->Server->dbSchemaDiagnostic();
$dbConfiguration = $this->Server->dbConfiguration();
$redisInfo = $this->Server->redisInfo();
@ -1149,10 +1168,8 @@ class ServersController extends AppController
$moduleStatus[$type] = $this->Server->moduleDiagnostics($diagnostic_errors, $type);
}
// check the size of the session table
$sessionCount = 0;
$sessionStatus = $this->Server->sessionDiagnostics($diagnostic_errors, $sessionCount);
$this->set('sessionCount', $sessionCount);
// get php session diagnostics
$sessionStatus = $this->Server->sessionDiagnostics($diagnostic_errors);
$this->loadModel('AttachmentScan');
try {
@ -1163,7 +1180,7 @@ class ServersController extends AppController
$securityAudit = (new SecurityAudit())->run($this->Server);
$view = compact('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'moduleStatus', 'yaraStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stix', 'moduleErrors', 'moduleTypes', 'dbDiagnostics', 'dbSchemaDiagnostics', 'redisInfo', 'attachmentScan', 'securityAudit');
$view = compact('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'moduleStatus', 'yaraStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stix', 'moduleErrors', 'moduleTypes', 'dbDiagnostics', 'dbSchemaDiagnostics', 'dbConfiguration', 'redisInfo', 'attachmentScan', 'securityAudit');
} else {
$view = [];
}
@ -1204,6 +1221,7 @@ class ServersController extends AppController
'readableFiles' => $readableFiles,
'dbDiagnostics' => $dbDiagnostics,
'dbSchemaDiagnostics' => $dbSchemaDiagnostics,
'dbConfiguration' => $dbConfiguration,
'redisInfo' => $redisInfo,
'finalSettings' => $dumpResults,
'extensions' => $extensions,
@ -1441,7 +1459,6 @@ class ServersController extends AppController
}
$this->set('id', $id);
}
$setting = $this->Server->getSettingData($settingName);
if ($setting === false) {
throw new NotFoundException(__('Setting %s is invalid.', $settingName));
@ -1913,7 +1930,7 @@ class ServersController extends AppController
$dbVersion = $this->AdminSetting->getSetting('db_version');
$updateProgress = $this->Server->getUpdateProgress();
$updateProgress['db_version'] = $dbVersion;
$maxUpdateNumber = max(array_keys($this->Server->db_changes));
$maxUpdateNumber = max(array_keys(Server::DB_CHANGES));
$updateProgress['complete_update_remaining'] = max($maxUpdateNumber - $dbVersion, 0);
$updateProgress['update_locked'] = $this->Server->isUpdateLocked();
$updateProgress['lock_remaining_time'] = $this->Server->getLockRemainingTime();
@ -2202,6 +2219,17 @@ class ServersController extends AppController
}
}
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');
}
}
public function cspReport()
{
if (!$this->request->is('post')) {

View File

@ -254,7 +254,7 @@ class ShadowAttributesController extends AppController
{
if ($this->request->is('ajax')) {
$this->set('ajax', true);
$this->layout = 'ajax';
$this->layout = false;
} else {
$this->set('ajax', false);
}
@ -406,27 +406,14 @@ class ShadowAttributesController extends AppController
}
$this->set('event_id', $event['Event']['id']);
// combobox for types
$types = array_keys($this->ShadowAttribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->ShadowAttribute->Attribute->getNonAttachmentTypes();
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
$categories = array_keys($this->ShadowAttribute->Event->Attribute->categoryDefinitions);
$categories = array_keys($this->ShadowAttribute->Attribute->categoryDefinitions);
$categories = $this->_arrayToValuesIndexArray($categories);
$this->set('categories', $categories);
$fieldDesc = ['category' => [], 'type' => []];
foreach ($this->ShadowAttribute->categoryDefinitions as $key => $value) {
$fieldDesc['category'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
foreach ($this->ShadowAttribute->typeDefinitions as $key => $value) {
$fieldDesc['type'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
$this->set('fieldDesc', $fieldDesc);
$this->__common();
$this->set('categoryDefinitions', $this->ShadowAttribute->categoryDefinitions);
}
@ -531,19 +518,19 @@ class ShadowAttributesController extends AppController
}
} else {
$shadowAttribute = array(
'ShadowAttribute' => array(
'value' => $filename,
'category' => $this->request->data['ShadowAttribute']['category'],
'type' => 'attachment',
'event_id' => $this->request->data['ShadowAttribute']['event_id'],
'comment' => $this->request->data['ShadowAttribute']['comment'],
'data' => base64_encode($tmpfile->read()),
'to_ids' => 0,
'email' => $this->Auth->user('email'),
'org_id' => $this->Auth->user('org_id'),
'event_uuid' => $event['Event']['uuid'],
'event_org_id' => $event['Event']['orgc_id'],
)
'ShadowAttribute' => array(
'value' => $filename,
'category' => $this->request->data['ShadowAttribute']['category'],
'type' => 'attachment',
'event_id' => $this->request->data['ShadowAttribute']['event_id'],
'comment' => $this->request->data['ShadowAttribute']['comment'],
'data' => base64_encode($tmpfile->read()),
'to_ids' => 0,
'email' => $this->Auth->user('email'),
'org_id' => $this->Auth->user('org_id'),
'event_uuid' => $event['Event']['uuid'],
'event_org_id' => $event['Event']['orgc_id'],
)
);
$this->ShadowAttribute->create();
$r = $this->ShadowAttribute->save($shadowAttribute);
@ -593,17 +580,14 @@ class ShadowAttributesController extends AppController
$categories = $this->_arrayToValuesIndexArray($selectedCategories);
$this->set('categories', $categories);
foreach ($this->ShadowAttribute->categoryDefinitions as $key => $value) {
$info['category'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
}
foreach ($this->ShadowAttribute->typeDefinitions as $key => $value) {
$info['type'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
}
$this->set('info', $info);
$this->__common();
$this->set('attrDescriptions', $this->ShadowAttribute->fieldDescriptions);
$this->set('typeDefinitions', $this->ShadowAttribute->typeDefinitions);
$this->set('categoryDefinitions', $this->ShadowAttribute->categoryDefinitions);
$this->set('isMalwareSampleCategory', $isMalwareSampleCategory);
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('event', $event);
$this->set('title_for_layout', __('Propose attachment'));
}
// Propose an edit to an attribute
@ -623,7 +607,7 @@ class ShadowAttributesController extends AppController
$existingAttribute = $existingAttribute[0];
// Check if the attribute is an attachment, if yes, block the type and the value fields from being edited.
if ('attachment' == $existingAttribute['Attribute']['type'] || 'malware-sample' == $existingAttribute['Attribute']['type']) {
if ($this->ShadowAttribute->Attribute->typeIsAttachment($existingAttribute['Attribute']['type'])) {
$this->set('attachment', true);
$attachment = true;
} else {
@ -718,12 +702,7 @@ class ShadowAttributesController extends AppController
}
// combobox for types
$types = array_keys($this->ShadowAttribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->ShadowAttribute->Attribute->getNonAttachmentTypes();
if ($existingAttribute['Attribute']['object_id']) {
$this->set('objectAttribute', true);
} else {
@ -732,15 +711,10 @@ class ShadowAttributesController extends AppController
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
$categories = $this->_arrayToValuesIndexArray(array_keys($this->ShadowAttribute->Event->Attribute->categoryDefinitions));
$categories = $this->_arrayToValuesIndexArray(array_keys($this->ShadowAttribute->Attribute->categoryDefinitions));
$categories = $this->_arrayToValuesIndexArray($categories);
foreach ($this->ShadowAttribute->Event->Attribute->categoryDefinitions as $key => $value) {
$info['category'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
}
foreach ($this->ShadowAttribute->Event->Attribute->typeDefinitions as $key => $value) {
$info['type'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
}
$categoryDefinitions = $this->ShadowAttribute->Event->Attribute->categoryDefinitions;
$categoryDefinitions = $this->ShadowAttribute->Attribute->categoryDefinitions;
if ($existingAttribute['Attribute']['object_id']) {
foreach ($categoryDefinitions as $k => $v) {
if (!in_array($existingAttribute['Attribute']['type'], $v['types'])) {
@ -754,10 +728,22 @@ class ShadowAttributesController extends AppController
}
}
$this->set('categories', $categories);
$this->set('info', $info);
$this->__common();
$this->set('attrDescriptions', $this->ShadowAttribute->fieldDescriptions);
$this->set('typeDefinitions', $this->ShadowAttribute->typeDefinitions);
$this->set('categoryDefinitions', $this->ShadowAttribute->Event->Attribute->categoryDefinitions);
$this->set('categoryDefinitions', $this->ShadowAttribute->Attribute->categoryDefinitions);
}
private function __common()
{
$fieldDesc = ['category' => [], 'type' => []];
foreach ($this->ShadowAttribute->categoryDefinitions as $key => $value) {
$fieldDesc['category'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
foreach ($this->ShadowAttribute->typeDefinitions as $key => $value) {
$fieldDesc['type'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
$this->set('fieldDesc', $fieldDesc);
}
public function delete($id)

View File

@ -151,7 +151,7 @@ class SharingGroupBlueprintsController extends AppController
$this->set('title', __('Execute Sharing Group Blueprint'));
$this->set('question', __('Are you sure you want to (re)create a sharing group based on the Sharing Group Blueprint?'));
$this->set('actionName', __('Execute'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}
@ -189,7 +189,7 @@ class SharingGroupBlueprintsController extends AppController
$this->set('title', __('Detach Sharing Group Blueprint'));
$this->set('question', __('Are you sure you want to detach the associated sharing group from this Sharing Group Blueprint? This action is irreversible.'));
$this->set('actionName', __('Detach'));
$this->layout = 'ajax';
$this->layout = false;
$this->render('/genericTemplates/confirm');
}
}

View File

@ -260,7 +260,7 @@ class SharingGroupsController extends AppController
public function index($passive = false)
{
$passive = $passive === 'true';
$authorizedSgIds = $this->SharingGroup->fetchAllAuthorised($this->Auth->user());
$authorizedSgIds = $this->SharingGroup->authorizedIds($this->Auth->user());
$this->paginate['conditions'][] = array('SharingGroup.id' => $authorizedSgIds);
$this->paginate['conditions'][] = array('SharingGroup.active' => $passive === true ? 0 : 1);

View File

@ -315,7 +315,7 @@ class SightingsController extends AppController
}
$this->set('csv', $statistics['csv']['all']);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/view_sightings');
}

View File

@ -13,29 +13,29 @@ class TagCollectionsController extends AppController
);
public $paginate = array(
'limit' => 60,
'order' => array(
'TagCollection.name' => 'ASC'
'limit' => 60,
'order' => array(
'TagCollection.name' => 'ASC'
),
'recursive' => -1,
'contain' => array(
'TagCollectionTag' => array(
'Tag'
),
'recursive' => -1,
'contain' => array(
'TagCollectionTag' => array(
'Tag'
),
'Organisation' => array(
'fields' => array(
'Organisation.id',
'Organisation.name',
'Organisation.uuid'
)
),
'User' => array(
'fields' => array(
'User.email',
'User.id'
)
'Organisation' => array(
'fields' => array(
'Organisation.id',
'Organisation.name',
'Organisation.uuid'
)
),
'User' => array(
'fields' => array(
'User.email',
'User.id'
)
)
)
);
public function add()
@ -387,7 +387,7 @@ class TagCollectionsController extends AppController
$this->set('tag_id', $tag_id);
$this->set('model', 'tag_collection');
$this->set('model_name', $tagCollection['TagCollection']['name']);
$this->layout = 'ajax';
$this->layout = false;
$this->render('/Attributes/ajax/tagRemoveConfirmation');
} else {
$rearrangeRules = array(
@ -446,7 +446,6 @@ class TagCollectionsController extends AppController
public function index()
{
//$this->Auth->user('Role')['perm_site_admin']);
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions = array(
@ -512,9 +511,9 @@ class TagCollectionsController extends AppController
}
if ($this->_isRest()) {
return $this->RestResponse->viewData($list, $this->response->type());
} else {
$this->set('list', $list);
}
$this->set('list', $list);
$this->set('title_for_layout', __('Tag Collections'));
}
public function getRow($id)

View File

@ -349,9 +349,10 @@ class TagsController extends AppController
public function showEventTag($id)
{
$user = $this->_closeSession();
$this->loadModel('Taxonomy');
$event = $this->Tag->EventTag->Event->fetchSimpleEvent($this->Auth->user(), $id, [
$event = $this->Tag->EventTag->Event->fetchSimpleEvent($user, $id, [
'fields' => ['Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'],
'contain' => [
'EventTag' => array(
@ -364,24 +365,26 @@ class TagsController extends AppController
throw new NotFoundException(__('Invalid event.'));
}
// Remove galaxy tags
$event = $this->Tag->EventTag->Event->massageTags($this->Auth->user(), $event, 'Event', false, true);
$event = $this->Tag->removeGalaxyClusterTags($user, $event);
$this->set('tags', $event['EventTag']);
$this->set('missingTaxonomies', $this->Tag->EventTag->Event->missingTaxonomies($event));
$tagConflicts = $this->Taxonomy->checkIfTagInconsistencies($event['EventTag']);
$this->set('tagConflicts', $tagConflicts);
$this->set('event', $event);
$this->layout = 'ajax';
$this->set('mayModify', $this->__canModifyEvent($event, $user));
$this->layout = false;
$this->render('/Events/ajax/ajaxTags');
}
public function showAttributeTag($id)
{
$user = $this->_closeSession();
$this->helpers[] = 'TextColour';
$this->loadModel('Attribute');
$this->loadModel('Taxonomy');
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), [
$attributes = $this->Attribute->fetchAttributes($user, [
'conditions' => ['Attribute.id' => $id],
'includeAllTags' => true,
'flatten' => true,
@ -394,7 +397,7 @@ class TagsController extends AppController
}
$attribute = $attributes[0];
// Remove galaxy tags
$attribute = $this->Tag->EventTag->Event->massageTags($this->Auth->user(), $attribute, 'Attribute', false, true);
$attribute = $this->Tag->removeGalaxyClusterTags($user, $attribute, 'Attribute');
$attributeTags = $attribute['AttributeTag'];
$this->set('event', ['Event' => $attribute['Event']]);
@ -402,7 +405,8 @@ class TagsController extends AppController
$this->set('attributeId', $id);
$tagConflicts = $this->Taxonomy->checkIfTagInconsistencies($attributeTags);
$this->set('tagConflicts', $tagConflicts);
$this->layout = 'ajax';
$this->set('mayModify', $this->__canModifyEvent($attribute, $user));
$this->layout = false;
$this->render('/Attributes/ajax/ajaxAttributeTags');
}
@ -435,7 +439,7 @@ class TagsController extends AppController
'conditions' => array('Event.id' => $id)
));
$this->set('event', $event);
$this->layout = 'ajax';
$this->layout = false;
$this->render('/Events/ajax/ajaxTags');
}
@ -456,13 +460,11 @@ class TagsController extends AppController
public function selectTaxonomy($id, $scope = 'event')
{
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
throw new NotFoundException('You don\'t have permission to do that.');
}
$user = $this->_closeSession();
$localFlag = !empty($this->params['named']['local']) ? '/local:1' : '';
$items = array();
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
if ($favourites) {
$hasFavourites = $this->Tag->FavouriteTag->hasAny(array('FavouriteTag.user_id' => $user['id']));
if ($hasFavourites) {
$items[] = array(
'name' => __('Favourite Tags'),
'value' => $this->baseurl . "/tags/selectTag/" . h($id) . "/favourites/" . h($scope) . $localFlag
@ -484,11 +486,11 @@ class TagsController extends AppController
);
$this->loadModel('Taxonomy');
$options = $this->Taxonomy->find('list', array('conditions' => array('enabled' => true), 'fields' => array('namespace'), 'order' => array('Taxonomy.namespace ASC')));
foreach ($options as $k => $option) {
$taxonomies = $this->Taxonomy->find('list', array('conditions' => array('enabled' => true), 'fields' => array('namespace'), 'order' => array('Taxonomy.namespace ASC')));
foreach ($taxonomies as $taxonomyId => $name) {
$items[] = array(
'name' => __('Taxonomy Library') . ":" . h($option),
'value' => $this->baseurl . "/tags/selectTag/" . h($id) . "/" . h($k) . "/" . h($scope . $localFlag)
'name' => __('Taxonomy Library') . ":" . h($name),
'value' => $this->baseurl . "/tags/selectTag/" . h($id) . "/" . h($taxonomyId) . "/" . h($scope) . $localFlag
);
}
$this->set('items', $items);
@ -502,6 +504,7 @@ class TagsController extends AppController
public function selectTag($id, $taxonomy_id, $scope = 'event', $filterData = '')
{
$user = $this->_closeSession();
$this->loadModel('Taxonomy');
$expanded = array();
$this->set('taxonomy_id', $taxonomy_id);
@ -527,87 +530,81 @@ class TagsController extends AppController
$expanded[$tagCollection['TagCollection']['id']] .= sprintf(' (%s)', $tagList);
}
}
} elseif ($taxonomy_id === '0') { // custom tags
$temp = $this->Taxonomy->getAllTaxonomyTags(true, $user, true, true, $local_tag);
$tags = array();
foreach ($temp as $tag) {
$tags[$tag['Tag']['id']] = $tag['Tag'];
}
unset($temp);
$expanded = $tags;
} elseif ($taxonomy_id === 'favourites') {
$tags = array();
$conditions = array(
'FavouriteTag.user_id' => $user['id'],
'Tag.org_id' => array(0, $user['org_id']),
'Tag.user_id' => array(0, $user['id']),
'Tag.hide_tag' => 0,
);
if (!$local_tag) {
$conditions['Tag.local_only'] = 0;
}
$favTags = $this->Tag->FavouriteTag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Tag'),
'order' => array('Tag.name asc')
));
foreach ($favTags as $favTag) {
$tags[$favTag['FavouriteTag']['tag_id']] = $favTag['Tag'];
$expanded = $tags;
}
} elseif ($taxonomy_id === 'all') { // all tags
$conditions = [
'Tag.is_galaxy' => 0,
'Tag.hide_tag' => 0,
];
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array(0, $user['org_id']);
$conditions['Tag.user_id'] = array(0, $user['id']);
}
if (!$local_tag) {
$conditions['Tag.local_only'] = 0;
}
$tags = $this->Tag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'order' => array('name asc'),
'fields' => array('Tag.id', 'Tag.name', 'Tag.colour')
));
$tags = array_column(array_column($tags, 'Tag'), null, "id");
$expanded = $tags;
} else {
if ($taxonomy_id === '0') {
$temp = $this->Taxonomy->getAllTaxonomyTags(true, $this->Auth->user(), true, true, $local_tag);
$tags = array();
foreach ($temp as $tag) {
$tags[$tag['Tag']['id']] = $tag['Tag'];
}
unset($temp);
$expanded = $tags;
} elseif ($taxonomy_id === 'favourites') {
$tags = array();
$conditions = array(
'FavouriteTag.user_id' => $this->Auth->user('id'),
'Tag.org_id' => array(0, $this->Auth->user('org_id')),
'Tag.user_id' => array(0, $this->Auth->user('id')),
'Tag.hide_tag' => 0,
);
if (!$local_tag) {
$conditions['Tag.local_only'] = 0;
}
$favTags = $this->Tag->FavouriteTag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Tag'),
'order' => array('Tag.name asc')
));
foreach ($favTags as $favTag) {
$tags[$favTag['FavouriteTag']['tag_id']] = $favTag['Tag'];
$expanded = $tags;
}
} elseif ($taxonomy_id === 'all') {
$conditions = [
'Tag.name NOT LIKE' => 'misp-galaxy:%',
'Tag.hide_tag' => 0,
];
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array(0, $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array(0, $this->Auth->user('id'));
}
if (!$local_tag) {
$conditions['Tag.local_only'] = 0;
}
$allTags = $this->Tag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'order' => array('name asc'),
'fields' => array('Tag.id', 'Tag.name', 'Tag.colour')
));
$tags = array();
foreach ($allTags as $tag) {
$tags[$tag['Tag']['id']] = $tag['Tag'];
}
unset($allTags);
$expanded = $tags;
} else {
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
$tags = array();
if (!empty($taxonomies['entries'])) {
$isSiteAdmin = $this->_isSiteAdmin();
foreach ($taxonomies['entries'] as $entry) {
if (!empty($entry['existing_tag']['Tag'])) {
$tag = $entry['existing_tag']['Tag'];
if ($tag['hide_tag']) {
continue; // do not include hidden tags
}
if ($tag['local_only'] && !$local_tag) {
continue; // we skip the local tags for global entries
}
if (!$isSiteAdmin) {
// Skip all tags that this user cannot use for tagging, determined by the org restriction on tags
if ($tag['org_id'] != '0' && $tag['org_id'] != $this->Auth->user('org_id')) {
continue;
}
if ($tag['user_id'] != '0' && $tag['user_id'] != $this->Auth->user('id')) {
continue;
}
}
$tags[$tag['id']] = $tag;
$expanded[$tag['id']] = $entry['expanded'];
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
$tags = array();
if (!empty($taxonomies['entries'])) {
$isSiteAdmin = $this->_isSiteAdmin();
foreach ($taxonomies['entries'] as $entry) {
if (!empty($entry['existing_tag']['Tag'])) {
$tag = $entry['existing_tag']['Tag'];
if ($tag['hide_tag']) {
continue; // do not include hidden tags
}
if ($tag['local_only'] && !$local_tag) {
continue; // we skip the local tags for global entries
}
if (!$isSiteAdmin) {
// Skip all tags that this user cannot use for tagging, determined by the org restriction on tags
if ($tag['org_id'] != '0' && $tag['org_id'] != $user['org_id']) {
continue;
}
if ($tag['user_id'] != '0' && $tag['user_id'] != $user['id']) {
continue;
}
}
$tags[$tag['id']] = $tag;
$expanded[$tag['id']] = $entry['expanded'];
}
}
}
@ -626,7 +623,7 @@ class TagsController extends AppController
$items = array();
foreach ($tags as $k => $tag) {
$tagName = $tag['name'];
$choice_id = $k;
$choice_id = (int)$k;
if ($taxonomy_id === 'collections') {
$choice_id = 'collection_' . $choice_id;
}
@ -664,7 +661,7 @@ class TagsController extends AppController
),
));
$this->set('local', !empty($this->params['named']['local']));
$this->render('ajax/select_tag');
$this->render('/Elements/generic_picker');
}
public function tagStatistics($percentage = false, $keysort = false)
@ -1003,6 +1000,7 @@ class TagsController extends AppController
public function search($tag = false, $strictTagNameOnly = false, $searchIfTagExists = true)
{
$user = $this->_closeSession();
if (isset($this->request->data['Tag'])) {
$this->request->data = $this->request->data['Tag'];
}
@ -1022,7 +1020,7 @@ class TagsController extends AppController
$tag[$k] = strtolower($t);
$conditionsCluster['OR'][] = array('LOWER(GalaxyCluster.value)' => $tag[$k]);
}
foreach ($tag as $k => $t) {
foreach ($tag as $t) {
$conditionsCluster['OR'][] = array('AND' => array('GalaxyElement.key' => 'synonyms', 'LOWER(GalaxyElement.value) LIKE' => $t));
}
$elements = $this->GalaxyCluster->GalaxyElement->find('all', array(
@ -1033,7 +1031,7 @@ class TagsController extends AppController
foreach ($elements as $element) {
$tag[] = strtolower($element['GalaxyCluster']['tag_name']);
}
foreach ($tag as $k => $t) {
foreach ($tag as $t) {
$conditions['OR'][] = array('LOWER(Tag.name) LIKE' => $t);
}
} else {
@ -1067,7 +1065,7 @@ class TagsController extends AppController
$tags[$k]['Taxonomy'] = $taxonomy['Taxonomy'];
$tags[$k]['TaxonomyPredicate'] = $taxonomy['TaxonomyPredicate'][0];
}
$cluster = $this->GalaxyCluster->getCluster($t['Tag']['name'], $this->Auth->user());
$cluster = $this->GalaxyCluster->getCluster($t['Tag']['name'], $user);
if (!empty($cluster)) {
$dataFound = true;
$tags[$k]['GalaxyCluster'] = $cluster['GalaxyCluster'];

View File

@ -270,9 +270,9 @@ class TaxonomiesController extends AppController
$message = __('Could not update any of the taxonomy libraries');
} else {
$flashType = 'success';
$message = __('Successfully updated ') . $successes . __(' taxonomy libraries.');
$message = __('Successfully updated %s taxonomy libraries.', $successes);
if ($fails != 0) {
$message .= __(' However, could not update ') . $fails . __(' taxonomy libraries.');
$message .= __(' However, could not update %s taxonomy libraries.', $fails);
}
}
if ($this->_isRest()) {
@ -494,7 +494,7 @@ class TaxonomiesController extends AppController
$this->set('required', !$taxonomy['Taxonomy']['required']);
$this->set('id', $id);
$this->autoRender = false;
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/toggle_required');
}
@ -594,4 +594,14 @@ class TaxonomiesController extends AppController
return $taxonomyIds;
}
public function normalizeCustomTagsToTaxonomyFormat()
{
$this->request->allowMethod(['post', 'put']);
$conversionResult = $this->Taxonomy->normalizeCustomTagsToTaxonomyFormat();
$this->Flash->success(__('%s tags successfully converted. %s row updated.', $conversionResult['tag_converted'], $conversionResult['row_updated']));
$this->redirect(array('controller' => 'taxonomies', 'action' => 'index'));
}
}

View File

@ -38,7 +38,7 @@ class TemplateElementsController extends AppController
$this->loadModel('Attribute');
$this->set('validTypeGroups', $this->Attribute->validTypeGroups);
$this->set('id', $id);
$this->layout = 'ajaxTemplate';
$this->layout = false;
$this->set('elements', $templateElements);
$mayModify = false;
if ($this->_isSiteAdmin() || $template['Template']['org'] == $this->Auth->user('Organisation')['name']) {
@ -57,7 +57,7 @@ class TemplateElementsController extends AppController
throw new MethodNotAllowedException('This action is for ajax requests only.');
}
$this->set('id', $id);
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/template_element_add_choices');
}
@ -116,7 +116,7 @@ class TemplateElementsController extends AppController
$this->set('categoryArray', $categoryArray);
$this->set('categories', $categories);
}
$this->layout = 'ajaxTemplate';
$this->layout = false;
$this->render('ajax/template_element_add_' . $type);
} elseif ($this->request->is('post')) {
$pos = $this->TemplateElement->lastPosition($id);
@ -210,7 +210,7 @@ class TemplateElementsController extends AppController
$this->set('categoryArray', $categoryArray);
$this->set('categories', $categories);
}
$this->layout = 'ajaxTemplate';
$this->layout = false;
$this->render('ajax/template_element_edit_' . $type);
} elseif ($this->request->is('post') || $this->request->is('put')) {
$this->request->data[$ModelType]['id'] = $templateElement[$ModelType][0]['id'];

View File

@ -139,7 +139,7 @@ class ThreadsController extends AppController
}
}
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->layout = false;
$this->render('/Elements/eventdiscussion');
}
}
@ -148,7 +148,7 @@ class ThreadsController extends AppController
{
$this->loadModel('Posts');
$this->loadModel('SharingGroup');
$sgids = $this->SharingGroup->fetchAllAuthorised($this->Auth->user());
$sgids = $this->SharingGroup->authorizedIds($this->Auth->user());
$conditions = null;
if (!$this->_isSiteAdmin()) {
$conditions['AND']['OR'] = array(

View File

@ -118,6 +118,24 @@ class UsersController extends AppController
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Something went wrong, please try again later.')), 'status'=>200, 'type' => 'json'));
}
public function unsubscribe($code)
{
$user = $this->Auth->user();
if (!hash_equals($this->User->unsubscribeCode($user), rtrim($code, '.'))) {
$this->Flash->error(__('Invalid unsubscribe code.'));
$this->redirect(['action' => 'view', 'me']);
}
if ($user['autoalert']) {
$this->User->updateField($this->Auth->user(), 'autoalert', false);
$this->Flash->success(__('Successfully unsubscribed from event alert.'));
} else {
$this->Flash->info(__('Already unsubscribed from event alert.'));
}
$this->redirect(['action' => 'view', 'me']);
}
public function edit()
{
$currentUser = $this->User->find('first', array(
@ -427,6 +445,7 @@ class UsersController extends AppController
'expiration',
'current_login',
'last_login',
'last_api_access',
'force_logout',
'date_created',
'date_modified'
@ -541,7 +560,7 @@ class UsersController extends AppController
$rules = $this->_arrayToValuesIndexArray($rules);
$this->set('rules', $rules);
$this->set('baseurl', Configure::read('MISP.baseurl'));
$this->layout = 'ajax';
$this->layout = false;
}
public function admin_view($id = null)
@ -631,21 +650,19 @@ class UsersController extends AppController
if (isset($this->request->data['User']['password'])) {
$this->request->data['User']['confirm_password'] = $this->request->data['User']['password'];
}
$default_publish_alert = Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : 0;
$defaults = array(
'external_auth_required' => 0,
'external_auth_key' => '',
'server_id' => 0,
'gpgkey' => '',
'certif_public' => '',
'autoalert' => $default_publish_alert,
'contactalert' => 0,
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'authkey' => (new RandomTool())->random_str(true, 40),
'termsaccepted' => 0,
'org_id' => $this->Auth->user('org_id')
'external_auth_required' => 0,
'external_auth_key' => '',
'server_id' => 0,
'gpgkey' => '',
'certif_public' => '',
'autoalert' => $this->User->defaultPublishAlert(),
'contactalert' => 0,
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'termsaccepted' => 0,
'org_id' => $this->Auth->user('org_id'),
);
foreach ($defaults as $key => $value) {
if (!isset($this->request->data['User'][$key])) {
@ -654,15 +671,14 @@ class UsersController extends AppController
}
}
$this->request->data['User']['date_created'] = time();
$this->request->data['User']['date_modified'] = time();
if (!array_key_exists($this->request->data['User']['role_id'], $syncRoles)) {
$this->request->data['User']['server_id'] = 0;
}
$this->User->create();
// set invited by
$this->loadModel('Role');
$this->Role->recursive = -1;
$chosenRole = $this->Role->findById($this->request->data['User']['role_id']);
$chosenRole = $this->User->Role->find('first', [
'conditions' => ['id' => $this->request->data['User']['role_id']],
]);
if (empty($chosenRole)) {
throw new MethodNotAllowedException('Invalid role');
}
@ -682,9 +698,6 @@ class UsersController extends AppController
$this->request->data['User']['newsread'] = 0;
if (!$this->_isSiteAdmin()) {
$this->request->data['User']['org_id'] = $this->Auth->user('org_id');
$this->loadModel('Role');
$this->Role->recursive = -1;
$chosenRole = $this->Role->findById($this->request->data['User']['role_id']);
if (
$chosenRole['Role']['perm_site_admin'] == 1 ||
$chosenRole['Role']['perm_regexp_access'] == 1 ||
@ -804,8 +817,7 @@ class UsersController extends AppController
$this->set('isSiteAdmin', $this->_isSiteAdmin());
$this->set('default_role_id', $default_role_id);
$this->set('servers', $servers);
$this->set(compact('roles'));
$this->set(compact('syncRoles'));
$this->set(compact('roles', 'syncRoles'));
}
}
@ -932,9 +944,9 @@ class UsersController extends AppController
$fields[] = 'role_id';
}
if (!$this->_isSiteAdmin() && isset($this->request->data['User']['role_id'])) {
$this->loadModel('Role');
$this->Role->recursive = -1;
$chosenRole = $this->Role->findById($this->request->data['User']['role_id']);
$chosenRole = $this->User->Role->find('first', [
'conditions' => ['id' => $this->request->data['User']['role_id']],
]);
if (empty($chosenRole) || (($chosenRole['Role']['id'] != $allowedRole) && ($chosenRole['Role']['perm_site_admin'] == 1 || $chosenRole['Role']['perm_regexp_access'] == 1 || $chosenRole['Role']['perm_sync'] == 1))) {
throw new Exception('You are not authorised to assign that role to a user.');
}
@ -1047,8 +1059,7 @@ class UsersController extends AppController
$this->set('servers', $servers);
$this->set('orgs', $orgs);
$this->set('id', $id);
$this->set(compact('roles'));
$this->set(compact('syncRoles'));
$this->set(compact('roles', 'syncRoles'));
$this->set('canChangeLogin', $this->__canChangeLogin());
$this->set('canChangePassword', $this->__canChangePassword());
}
@ -1058,9 +1069,6 @@ class UsersController extends AppController
if (!$this->request->is('post') && !$this->request->is('delete')) {
throw new MethodNotAllowedException(__('Action not allowed, post or delete request expected.'));
}
if (!$this->_isAdmin()) {
throw new Exception('Administrators only.');
}
$this->User->id = $id;
$conditions = array('User.id' => $id);
if (!$this->_isSiteAdmin()) {
@ -1383,16 +1391,16 @@ class UsersController extends AppController
public function histogram($selected = null)
{
//if (!$this->request->is('ajax') && !$this->_isRest()) throw new MethodNotAllowedException('This function can only be accessed via AJAX or the API.');
$user = $this->_closeSession();
if ($selected == '[]') {
$selected = null;
}
$selectedTypes = array();
if ($selected) {
$selectedTypes = json_decode($selected);
$selectedTypes = $this->_jsonDecode($selected);
}
if (!$this->_isSiteAdmin() && !empty(Configure::read('Security.hide_organisation_index_from_users'))) {
$org_ids = array($this->Auth->user('org_id'));
$org_ids = array($user['org_id']);
} else {
$org_ids = $this->User->Event->find('column', array(
'fields' => array('Event.orgc_id'),
@ -1403,12 +1411,7 @@ class UsersController extends AppController
'fields' => array('Organisation.id', 'Organisation.name'),
'conditions' => array('Organisation.id' => $org_ids)
));
$orgs = array(0 => 'All organisations');
foreach ($org_ids as $v) {
if (!empty($orgs_temp[$v])) {
$orgs[$v] = $orgs_temp[$v];
}
}
$orgs = array(0 => 'All organisations') + $orgs_temp;
$data = array();
$max = 1;
foreach ($orgs as $org_id => $org_name) {
@ -1481,7 +1484,7 @@ class UsersController extends AppController
$this->set('typeDb', $typeDb);
$this->set('sigTypes', $sigTypes);
$this->layout = 'ajax';
$this->layout = false;
}
public function terms()
@ -1491,17 +1494,36 @@ class UsersController extends AppController
$this->Flash->success(__('You accepted the Terms and Conditions.'));
$this->redirect(array('action' => 'routeafterlogin'));
}
$termsFile = Configure::read('MISP.terms_file');
if (empty($termsFile)) {
throw new NotFoundException(__("MISP Terms and Conditions are not defined"));
}
$termsDownload = (bool)Configure::read('MISP.terms_download');
if (!$termsDownload) {
$termsFilePath = APP . 'files' . DS . 'terms' . DS . basename($termsFile);
try {
$termsContent = FileAccessTool::readFromFile($termsFilePath);
} catch (Exception $e) {
$termsContent = false;
}
$this->set("termsContent", $termsContent);
}
$this->set("termsDownload", $termsDownload);
$this->set('termsaccepted', $this->Auth->user('termsaccepted'));
}
public function downloadTerms()
{
if (!Configure::read('MISP.terms_file')) {
$termsFile = APP ."View/Users/terms";
} else {
$termsFile = APP . 'files' . DS . 'terms' . DS . Configure::read('MISP.terms_file');
$termsFile = Configure::read('MISP.terms_file');
if (empty($termsFile)) {
throw new NotFoundException(__("MISP Terms and Conditions are not defined"));
}
$this->response->file($termsFile, array('download' => true, 'name' => Configure::read('MISP.terms_file')));
$termsFilePath = APP . 'files' . DS . 'terms' . DS . basename($termsFile);
$this->response->file($termsFilePath, ['download' => true, 'name' => $termsFile]);
return $this->response;
}
@ -1588,9 +1610,6 @@ class UsersController extends AppController
public function admin_email($isPreview=false)
{
if (!$this->_isAdmin()) {
throw new MethodNotAllowedException();
}
$isPostOrPut = $this->request->is('post') || $this->request->is('put');
$conditions = array();
if (!$this->_isSiteAdmin()) {
@ -1600,17 +1619,11 @@ class UsersController extends AppController
// harvest parameters
if ($isPostOrPut) {
$recipient = $this->request->data['User']['recipient'];
} else {
$recipient = isset($this->params['named']['recipient']) ? $this->params['named']['recipient'] : null;
}
if ($isPostOrPut) {
$recipientEmailList = $this->request->data['User']['recipientEmailList'];
} else {
$recipientEmailList = isset($this->params['named']['recipientEmailList']) ? $this->params['named']['recipientEmailList'] : null;
}
if ($isPostOrPut) {
$orgNameList = $this->request->data['User']['orgNameList'];
} else {
$recipient = isset($this->params['named']['recipient']) ? $this->params['named']['recipient'] : null;
$recipientEmailList = isset($this->params['named']['recipientEmailList']) ? $this->params['named']['recipientEmailList'] : null;
$orgNameList = isset($this->params['named']['orgNameList']) ? $this->params['named']['orgNameList'] : null;
}
@ -1637,7 +1650,7 @@ class UsersController extends AppController
$users = $this->User->find('all', array('recursive' => -1, 'order' => array('email ASC'), 'conditions' => $conditions));
// User has filled in his contact form, send out the email.
if ($isPostOrPut) {
$this->request->data['User']['message'] = $this->User->adminMessageResolve($this->request->data['User']['message']);
$this->request->data['User']['message'] = $this->__replaceEmailVariables($this->request->data['User']['message']);
$failures = '';
foreach ($users as $user) {
$password = $this->User->generateRandomPassword();
@ -1684,11 +1697,11 @@ class UsersController extends AppController
$textsToFetch = array('newUserText', 'passwordResetText');
$this->loadModel('Server');
foreach ($textsToFetch as $text) {
${$text} = Configure::read('MISP.' . $text);
if (!${$text}) {
${$text} = $this->Server->serverSettings['MISP'][$text]['value'];
$value = Configure::read('MISP.' . $text);
if (!$value) {
$value = $this->Server->serverSettings['MISP'][$text]['value'];
}
$this->set($text, ${$text});
$this->set($text, $value);
}
}
}
@ -1723,7 +1736,7 @@ class UsersController extends AppController
$error = 'No encryption key found for the user and the instance posture blocks non encrypted e-mails from being sent.';
}
$this->set('error', $error);
$this->layout = 'ajax';
$this->layout = false;
$this->set('user', $user);
$this->set('firstTime', $firstTime);
$this->render('ajax/passwordResetConfirmationForm');
@ -1780,9 +1793,7 @@ class UsersController extends AppController
// Email construction
$body = Configure::read('Security.email_otp_text') ?: $this->Server->serverSettings['Security']['email_otp_text']['value'];
$body = str_replace('$misp', Configure::read('MISP.baseurl'), $body);
$body = str_replace('$org', Configure::read('MISP.org'), $body);
$body = str_replace('$contact', Configure::read('MISP.contact'), $body);
$body = $this->__replaceEmailVariables($body);
$body = str_replace('$validity', $validity, $body);
$body = str_replace('$otp', $otp, $body);
$body = str_replace('$ip', $this->__getClientIP(), $body);
@ -2051,7 +2062,6 @@ class UsersController extends AppController
private function __statisticsUsers($params = array())
{
$this->loadModel('Organisation');
$this->loadModel('User');
$this_month = strtotime(date('Y/m') . '/01');
$this_year = strtotime(date('Y') . '/01/01');
$ranges = array(
@ -2103,12 +2113,13 @@ class UsersController extends AppController
public function tagStatisticsGraph()
{
$this->_closeSession();
$this->loadModel('EventTag');
$tags = $this->EventTag->getSortedTagList();
$this->loadModel('Taxonomy');
$taxonomies = $this->Taxonomy->find('list', array(
'conditions' => array('enabled' => true),
'fields' => array('Taxonomy.namespace')
'conditions' => array('enabled' => true),
'fields' => array('Taxonomy.namespace')
));
$flatData = array();
$tagIds = $this->EventTag->Tag->find('list', array('fields' => array('Tag.name', 'Tag.id')));
@ -2138,7 +2149,6 @@ class UsersController extends AppController
}
$treemap['children'][] = $newElement;
}
$taxonomyColourCodes = array();
$taxonomies = array_merge(array('custom'), $taxonomies);
if ($this->_isRest()) {
$data = array(
@ -2147,12 +2157,11 @@ class UsersController extends AppController
);
return $this->RestResponse->viewData($data, $this->response->type());
} else {
$this->set('taxonomyColourCodes', $taxonomyColourCodes);
$this->set('taxonomies', $taxonomies);
$this->set('flatData', $flatData);
$this->set('treemap', $treemap);
$this->set('tags', $tags);
$this->layout = 'treemap';
$this->layout = false;
$this->render('ajax/tag_statistics_graph');
}
}
@ -2337,6 +2346,7 @@ class UsersController extends AppController
public function searchGpgKey($email = false)
{
session_abort();
if (!$email) {
throw new NotFoundException('No email provided.');
}
@ -2345,7 +2355,6 @@ class UsersController extends AppController
throw new NotFoundException('No keys found for given email at keyserver.');
}
$this->set('keys', $keys);
$this->autorender = false;
$this->layout = false;
$this->render('ajax/fetchpgpkey');
}
@ -2764,4 +2773,17 @@ class UsersController extends AppController
}
return !Configure::read('MISP.disable_user_login_change');
}
/**
* Replaces $misp, $org and $contact variables in emails
* @param string $body
* @return string
*/
private function __replaceEmailVariables($body)
{
$body = str_replace('$misp', Configure::read('MISP.baseurl'), $body);
$body = str_replace('$org', Configure::read('MISP.org'), $body);
$body = str_replace('$contact', Configure::read('MISP.contact'), $body);
return $body;
}
}

View File

@ -321,7 +321,7 @@ class WarninglistsController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This action is available via AJAX only.'));
}
$this->layout = 'ajax';
$this->layout = false;
$this->render('ajax/getToggleField');
}
@ -360,9 +360,7 @@ class WarninglistsController extends AppController
public function import()
{
if (!$this->request->is('post')) {
throw new MethodNotAllowedException(__('This function only accepts POST requests.'));
}
$this->request->allowMethod(['post']);
if (empty($this->request->data)) {
throw new BadRequestException(__('No valid data received.'));
@ -378,11 +376,11 @@ class WarninglistsController extends AppController
throw new BadRequestException(__('No valid data received: `list` field is not array'));
}
$id = $this->Warninglist->import($this->request->data);
if (is_int($id)) {
try {
$id = $this->Warninglist->import($this->request->data);
return $this->RestResponse->saveSuccessResponse('Warninglist', 'import', $id, false, __('Warninglist imported'));
} else {
return $this->RestResponse->saveFailResponse('Warninglist', 'import', false, $id);
} catch (Exception $e) {
return $this->RestResponse->saveFailResponse('Warninglist', 'import', false, $e->getMessage());
}
}

View File

@ -0,0 +1,127 @@
<?php
App::uses('AppController', 'Controller');
class WorkflowBlueprintsController extends AppController
{
public $components = array(
'RequestHandler'
);
public function update($force = false)
{
$this->request->allowMethod(['post', 'put']);
$this->WorkflowBlueprint->update($force);
$message = __('Default workflow blueprints updated');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('WorkflowBlueprint', 'update', false, $this->response->type(), $message);
} else {
$this->Flash->success($message);
$this->redirect(array('controller' => 'workflowBlueprints', 'action' => 'index'));
}
}
public function index()
{
$params = [
'filters' => ['name', 'uuid', 'timestamp'],
'quickFilters' => ['name', 'uuid'],
];
$this->CRUD->index($params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('menuData', ['menuList' => 'workflowBlueprints', 'menuItem' => 'index']);
}
public function add($fromEditor = false)
{
$params = [
'beforeSave' => function(array $blueprint) {
$blueprint['WorkflowBlueprint']['default'] = false;
return $blueprint;
},
];
$this->CRUD->add($params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('fromEditor', !empty($fromEditor));
$this->set('menuData', ['menuList' => 'workflowBlueprints', 'menuItem' => 'add']);
}
public function edit($id)
{
$params = [
'beforeSave' => function (array $blueprint) {
$blueprint['WorkflowBlueprint']['default'] = false;
return $blueprint;
},
];
$this->CRUD->edit($id, $params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->request->data['WorkflowBlueprint']['data'] = JsonTool::encode($this->data['WorkflowBlueprint']['data']);
$this->set('menuData', ['menuList' => 'workflowBlueprints', 'menuItem' => 'edit']);
$this->set('id', $id);
$this->render('add');
}
public function delete($id)
{
$params = [
];
$this->CRUD->delete($id, $params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('menuData', ['menuList' => 'workflowBlueprints', 'menuItem' => 'delete']);
}
public function view($id)
{
$filters = $this->IndexFilter->harvestParameters(['format']);
if (!empty($filters['format'])) {
if ($filters['format'] == 'dot') {
$dot = $this->WorkflowBlueprint->getDotNotation($id);
return $this->RestResponse->viewData($dot, $this->response->type());
} else if ($filters['format'] == 'mermaid') {
$mermaid = $this->WorkflowBlueprint->getMermaid($id);
return $this->RestResponse->viewData($mermaid, $this->response->type());
}
}
$this->CRUD->view($id, [
]);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('id', $id);
$this->set('menuData', ['menuList' => 'workflowBlueprints', 'menuItem' => 'view']);
}
public function import()
{
if ($this->request->is('post') || $this->request->is('put')) {
$workflowBlueprintData = JsonTool::decode($this->request->data['WorkflowBlueprint']['data']);
if ($workflowBlueprintData === null) {
throw new MethodNotAllowedException(__('Error while decoding JSON'));
}
$this->request->data['WorkflowBlueprint']['data'] = JsonTool::encode($workflowBlueprintData);
$this->add();
}
}
public function export($id)
{
$workflowBlueprint = $this->WorkflowBlueprint->find('first', [
'conditions' => [
'id' => $id,
]
]);
$content = JsonTool::encode($workflowBlueprint, JSON_PRETTY_PRINT);
$this->response->body($content);
$this->response->type('json');
$this->response->download(sprintf('blueprint_%s_%s.json', str_replace(' ', '-', strtolower($workflowBlueprint['WorkflowBlueprint']['name'])), time()));
return $this->response;
}
}

View File

@ -0,0 +1,428 @@
<?php
App::uses('AppController', 'Controller');
class WorkflowsController extends AppController
{
public $components = array(
'RequestHandler'
);
private $toggleableFields = ['enabled'];
public function beforeFilter()
{
parent::beforeFilter();
$this->Security->unlockedActions[] = 'checkGraph';
$requirementErrors = [];
if (empty(Configure::read('MISP.background_jobs'))) {
$requirementErrors[] = __('Background workers must be enabled to use workflows');
$this->render('error');
}
if (empty(Configure::read('Plugin.Workflow_enable'))) {
$requirementErrors[] = __('The workflow plugin must be enabled to use workflows. Go to `/servers/serverSettings/Plugin` the enable the `Plugin.Workflow` setting');
$this->render('error');
}
try {
$this->Workflow->setupRedisWithException();
} catch (Exception $e) {
$requirementErrors[] = $e->getMessage();
}
if (!empty($requirementErrors)) {
$this->set('requirementErrors', $requirementErrors);
$this->render('error');
}
}
public function index()
{
$params = [
'filters' => ['name', 'uuid'],
'quickFilters' => ['name', 'uuid'],
];
$this->CRUD->index($params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('menuData', array('menuList' => 'workflows', 'menuItem' => 'index'));
}
public function rebuildRedis()
{
$this->Workflow->rebuildRedis();
}
public function edit($id)
{
$this->set('id', $id);
$savedWorkflow = $this->Workflow->fetchWorkflow($id);
if ($this->request->is('post') || $this->request->is('put')) {
$newWorkflow = $this->request->data;
$newWorkflow['Workflow']['data'] = JsonTool::decode($newWorkflow['Workflow']['data']);
$newWorkflow = $this->__applyDataFromSavedWorkflow($newWorkflow, $savedWorkflow);
$result = $this->Workflow->editWorkflow($newWorkflow);
$redirectTarget = ['action' => 'view', $id];
if (!empty($result['errors'])) {
return $this->__getFailResponseBasedOnContext($result['errors'], null, 'edit', $this->Workflow->id, $redirectTarget);
} else {
$successMessage = __('Workflow saved.');
$savedWorkflow = $result['saved'];
return $this->__getSuccessResponseBasedOnContext($successMessage, $savedWorkflow, 'edit', false, $redirectTarget);
}
} else {
$savedWorkflow['Workflow']['data'] = JsonTool::encode($savedWorkflow['Workflow']['data']);
$this->request->data = $savedWorkflow;
}
$this->set('menuData', array('menuList' => 'workflows', 'menuItem' => 'edit'));
$this->render('add');
}
public function delete($id)
{
$params = [
];
$this->CRUD->delete($id, $params);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
}
public function view($id)
{
$filters = $this->IndexFilter->harvestParameters(['format']);
if (!empty($filters['format'])) {
if ($filters['format'] == 'dot') {
$dot = $this->Workflow->getDotNotation($id);
return $this->RestResponse->viewData($dot, $this->response->type());
} else if ($filters['format'] == 'mermaid') {
$mermaid = $this->Workflow->getMermaid($id);
return $this->RestResponse->viewData($mermaid, $this->response->type());
}
}
$this->CRUD->view($id, [
]);
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('id', $id);
$this->set('menuData', array('menuList' => 'workflows', 'menuItem' => 'view'));
}
public function editor($id)
{
$trigger_id = false;
$workflow = false;
if (is_numeric($id)) {
$workflow_id = $id;
} else {
$trigger_id = $id;
}
$modules = $this->Workflow->getModulesByType();
if (!empty($trigger_id)) {
$trigger_ids = Hash::extract($modules['modules_trigger'], '{n}.id');
if (!in_array($trigger_id, $trigger_ids)) {
return $this->__getFailResponseBasedOnContext(
[__('Unkown trigger %s', $trigger_id)],
null,
'add',
$trigger_id,
['controller' => 'workflows', 'action' => 'triggers']
);
}
$workflow = $this->Workflow->fetchWorkflowByTrigger($trigger_id, false);
if (empty($workflow)) { // Workflow do not exists yet. Create it.
$result = $this->Workflow->addWorkflow([
'name' => sprintf('Workflow for trigger %s', $trigger_id),
'data' => $this->Workflow->genGraphDataForTrigger($trigger_id),
'trigger_id' => $trigger_id,
]);
if (!empty($result['errors'])) {
return $this->__getFailResponseBasedOnContext(
[__('Could not create workflow for trigger %s', $trigger_id), $result['errors']],
null,
'add',
$trigger_id,
['controller' => 'workflows', 'action' => 'editor']
);
}
$workflow = $this->Workflow->fetchWorkflowByTrigger($trigger_id, false);
}
} else {
$workflow = $this->Workflow->fetchWorkflow($workflow_id);
}
$modules = $this->Workflow->attachNotificationToModules($modules, $workflow);
$this->loadModel('WorkflowBlueprint');
$workflowBlueprints = $this->WorkflowBlueprint->find('all');
$workflowBlueprints = array_map(function($blueprint) {
return $this->WorkflowBlueprint->attachModuleDataToBlueprint($blueprint);
}, $workflowBlueprints);
$this->set('selectedWorkflow', $workflow);
$this->set('workflowTriggerId', $trigger_id);
$this->set('modules', $modules);
$this->set('workflowBlueprints', $workflowBlueprints);
}
public function executeWorkflow($workflow_id)
{
if ($this->request->is('post') || $this->request->is('put')) {
$blockingErrors = [];
$data = JsonTool::decode($this->request->data['Workflow']['data']);
$result = $this->Workflow->executeWorkflow($workflow_id, $data, $blockingErrors);
if (!empty($logging) && empty($result['success'])) {
$logging['message'] = !empty($logging['message']) ? $logging['message'] : __('Error while executing workflow.');
$errorMessage = implode(', ', $blockingErrors);
$this->Workflow->loadLog()->createLogEntry('SYSTEM', $logging['action'], $logging['model'], $logging['id'], $logging['message'], __('Returned message: %s', $errorMessage));
}
return $this->RestResponse->viewData([
'success' => $result['success'],
'outcome' => $result['outcomeText'],
], $this->response->type());
}
$this->render('ajax/executeWorkflow');
}
public function triggers()
{
$triggers = $this->Workflow->getModulesByType('trigger');
$triggers = $this->Workflow->attachWorkflowToTriggers($triggers);
$data = $triggers;
App::uses('CustomPaginationTool', 'Tools');
$customPagination = new CustomPaginationTool();
$customPagination->truncateAndPaginate($data, $this->params, 'Workflow', true);
if ($this->_isRest()) {
return $this->RestResponse->viewData($data, $this->response->type());
}
$this->set('data', $data);
$this->set('menuData', ['menuList' => 'workflows', 'menuItem' => 'index_trigger']);
}
public function moduleIndex()
{
$modules = $this->Workflow->getModulesByType();
$errorWhileLoading = $this->Workflow->getModuleLoadingError();
$this->Module = ClassRegistry::init('Module');
$mispModules = $this->Module->getModules('Action');
$this->set('module_service_error', !is_array($mispModules));
$filters = $this->IndexFilter->harvestParameters(['type', 'actiontype', 'enabled']);
$moduleType = $filters['type'] ?? 'action';
$actionType = $filters['actiontype'] ?? 'all';
$enabledState = $filters['enabled'] ?? false;
if ($moduleType == 'all' || $moduleType == 'custom') {
$data = array_merge(
$modules["modules_action"],
$modules["modules_logic"]
);
} else {
$data = $modules["modules_{$moduleType}"];
}
if ($actionType == 'mispmodule') {
$data = array_filter($data, function($module) {
return !empty($module['is_misp_module']);
});
} else if ($actionType == 'blocking') {
$data = array_filter($data, function ($module) {
return !empty($module['blocking']);
});
} else if ($moduleType == 'custom') {
$data = array_filter($data, function ($module) {
return !empty($module['is_custom']);
});
}
if ($enabledState !== false) {
$moduleType = !empty($enabledState) ? 'enabled' : 'disabled';
$data = array_filter($data, function ($module) use ($enabledState) {
return !empty($enabledState) ? empty($module['disabled']) : !empty($module['disabled']);
});
}
if ($this->_isRest()) {
return $this->RestResponse->viewData($data, $this->response->type());
}
App::uses('CustomPaginationTool', 'Tools');
$customPagination = new CustomPaginationTool();
$params = $customPagination->createPaginationRules($data, $this->passedArgs, 'Workflow');
$params = $customPagination->applyRulesOnArray($data, $params, 'Workflow');
$params['options'] = array_merge($params['options'], $filters);
$this->params['paging'] = [$this->modelClass => $params];
$this->set('data', $data);
$this->set('indexType', $moduleType);
$this->set('actionType', $actionType);
$this->set('errorWhileLoading', $errorWhileLoading);
$this->set('menuData', ['menuList' => 'workflows', 'menuItem' => 'index_module']);
}
public function moduleView($module_id)
{
$module = $this->Workflow->getModuleByID($module_id);
if (empty($module)) {
throw new NotFoundException(__('Invalid trigger ID'));
}
$is_trigger = $module['module_type'] == 'trigger';
if ($is_trigger) {
$module = $this->Workflow->attachWorkflowToTriggers([$module])[0];
$module['listening_workflows'] = $this->Workflow->getListeningWorkflowForTrigger($module);
}
if ($this->_isRest()) {
return $this->RestResponse->viewData($module, $this->response->type());
}
$this->set('data', $module);
$this->set('menuData', ['menuList' => 'workflows', 'menuItem' => 'view_module']);
}
public function toggleModule($module_id, $enabled, $is_trigger=false)
{
$this->request->allowMethod(['post', 'put']);
$saved = $this->Workflow->toggleModule($module_id, $enabled, $is_trigger);
if ($saved) {
return $this->__getSuccessResponseBasedOnContext(
__('%s module %s', ($enabled ? 'Enabled' : 'Disabled'), $module_id),
null,
'toggle_module',
$module_id,
['action' => (!empty($is_trigger) ? 'triggers' : 'moduleIndex')]
);
} else {
return $this->__getFailResponseBasedOnContext(
__('Could not %s module %s', ($enabled ? 'Enabled' : 'Disabled'), $module_id),
null,
'toggle_module',
$module_id,
['action' => (!empty($is_trigger) ? 'triggers' : 'moduleIndex')]
);
}
}
public function debugToggleField($workflow_id, $enabled)
{
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This action is available via AJAX only.'));
}
$this->layout = false;
$this->render('ajax/getDebugToggleField');
if ($this->request->is('post') || $this->request->is('put')) {
$success = $this->Workflow->toggleDebug($workflow_id, $enabled);
if (!empty($success)) {
return $this->__getSuccessResponseBasedOnContext(
__('%s debug mode', ($enabled ? __('Enabled') : __('Disabled'))),
null,
'toggle_debug',
$workflow_id,
['action' => 'triggers']
);
} else {
return $this->__getFailResponseBasedOnContext(
__('Could not %s debug mode', ($enabled ? __('enable') : __('disable'))),
null,
'toggle_debug',
$workflow_id,
['action' => 'triggers']
);
}
}
}
public function massToggleField($fieldName, $enabled, $is_trigger=false)
{
if (!in_array($fieldName, $this->toggleableFields)) {
throw new MethodNotAllowedException(__('The field `%s` cannot be toggled', $fieldName));
}
if ($this->request->is('post') || $this->request->is('put')) {
$module_ids = JsonTool::decode($this->request->data['Workflow']['module_ids']);
$enabled_count = $this->Workflow->toggleModules($module_ids, $enabled, $is_trigger);
if (!empty($enabled_count)) {
return $this->__getSuccessResponseBasedOnContext(
__('%s %s modules', ($enabled ? 'Enabled' : 'Disabled'), $enabled_count),
null,
'toggle_module',
$module_ids,
['action' => (!empty($is_trigger) ? 'triggers' : 'moduleIndex')]
);
} else {
return $this->__getFailResponseBasedOnContext(
__('Could not %s modules', ($enabled ? 'enable' : 'disable')),
null,
'toggle_module',
$module_ids,
['action' => (!empty($is_trigger) ? 'triggers' : 'moduleIndex')]
);
}
}
}
private function __getSuccessResponseBasedOnContext($message, $data = null, $action = '', $id = false, $redirect = array())
{
if ($this->_isRest()) {
if (!is_null($data)) {
return $this->RestResponse->viewData($data, $this->response->type());
} else {
return $this->RestResponse->saveSuccessResponse('Workflow', $action, $id, false, $message);
}
} elseif ($this->request->is('ajax')) {
return $this->RestResponse->saveSuccessResponse('Workflow', $action, $id, false, $message, $data);
} else {
$this->Flash->success($message);
$this->redirect($redirect);
}
return;
}
private function __getFailResponseBasedOnContext($message, $data = null, $action = '', $id = false, $redirect = array())
{
if (is_array($message)) {
$message = implode(', ', $message);
}
if ($this->_isRest()) {
if ($data !== null) {
return $this->RestResponse->viewData($data, $this->response->type());
} else {
return $this->RestResponse->saveFailResponse('Workflow', $action, $id, $message);
}
} elseif ($this->request->is('ajax')) {
return $this->RestResponse->saveFailResponse('Workflow', $action, $id, $message, false, $data);
} else {
$this->Flash->error($message);
$this->redirect($redirect);
}
}
private function __applyDataFromSavedWorkflow($newWorkflow, $savedWorkflow)
{
if (!isset($newWorkflow['Workflow'])) {
$newWorkflow = ['Workflow' => $newWorkflow];
}
$ignoreFieldList = ['id', 'uuid'];
foreach (Workflow::CAPTURE_FIELDS_EDIT as $field) {
if (!in_array($field, $ignoreFieldList) && isset($newWorkflow['Workflow'][$field])) {
$savedWorkflow['Workflow'][$field] = $newWorkflow['Workflow'][$field];
}
}
return $savedWorkflow;
}
public function checkGraph()
{
$this->request->allowMethod(['post']);
$graphData = JsonTool::decode($this->request->data['graph']);
$cycles = [];
$isAcyclic = $this->Workflow->workflowGraphTool->isAcyclic($graphData, $cycles);
$edgesMultipleOutput = [];
$hasMultipleOutputConnection = $this->Workflow->workflowGraphTool->hasMultipleOutputConnection($graphData, $edgesMultipleOutput);
$edgesWarnings = [];
$hasPathWarnings = $this->Workflow->hasPathWarnings($graphData, $edgesWarnings);
$data = [
'is_acyclic' => [
'is_acyclic' => $isAcyclic,
'cycles' => $cycles,
],
'multiple_output_connection' => [
'has_multiple_output_connection' => $hasMultipleOutputConnection,
'edges' => $edgesMultipleOutput,
],
'path_warnings' => [
'has_path_warnings' => $hasPathWarnings,
'edges' => $edgesWarnings,
],
];
return $this->RestResponse->viewData($data, 'json');
}
}

View File

@ -43,7 +43,7 @@ class RecentSightingsWidget
else $type = "Expiration";
$output = $attribute->{'value'} . " (id: " . $attribute->{'id'} . ") in " . $event->{'info'} . " (id: " . $event->{'id'} . ")";
$data[] = array( 'title' => __($type), 'value' => $output,
$data[] = array( 'title' => $type, 'value' => $output,
'html' => sprintf(
' (Event <a href="%s%s">%s</a>)',
Configure::read('MISP.baseurl') . '/events/view/', $event->{'id'},

View File

@ -7,7 +7,8 @@ class DefaultWarning
public $functions = [
'emptyEventCheck',
'contextCheck',
'tlpDistributionCheck'
'tlpDistributionCheck',
'taxonomyInconsistenciesCheck'
];
function __construct()
@ -47,6 +48,13 @@ class DefaultWarning
}
}
public function taxonomyInconsistenciesCheck(array $event, array &$warnings)
{
if (Configure::read('MISP.disable_taxonomy_consistency_checks')) {
$warnings[__('Tags')][] = __('Taxonomy consistency checks are disabled in the configuration, set `MISP.disable_taxonomy_consistency_checks` to `false` to enable them.');
}
}
/**
* @param string $tagName
* @return void
@ -55,7 +63,7 @@ class DefaultWarning
{
$lowerTagName = trim(strtolower($tagName));
if (substr($lowerTagName, 0, 4) === 'tlp:') {
if (!in_array($lowerTagName, ['tlp:white', 'tlp:green', 'tlp:amber', 'tlp:red', 'tlp:ex:chr'], true)) {
if (!in_array($lowerTagName, ['tlp:white', 'tlp:green', 'tlp:amber', 'tlp:red', 'tlp:ex:chr', 'tlp:clear', 'tlp:amber+strict'], true)) {
$warnings['TLP'][] = __('Unknown TLP tag, please refer to the TLP taxonomy as to what is valid, otherwise filtering rules created by your partners may miss your intent.');
} else if ($lowerTagName !== $tagName) {
$warnings['TLP'][] = __('TLP tag with invalid formatting: Make sure that you only use TLP tags from the taxonomy. Custom tags with invalid capitalisation, white spaces or other artifacts will break synchronisation and filtering rules intended for the correct taxonomy derived tags.');

View File

@ -6,16 +6,16 @@ class HashesExport
'flatten' => 1
);
public $validTypes = array(
const VALID_TYPES = array(
'simple' => array(
'md5', 'sha1', 'sha256', 'sha224', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'tlsh',
'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'pehash', 'authentihash',
'impfuzzy'
'md5', 'sha1', 'sha256', 'sha224', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'sha3-224', 'sha3-256',
'sha3-384', 'sha3-512', 'ssdeep', 'imphash', 'tlsh', 'x509-fingerprint-sha1', 'x509-fingerprint-md5',
'x509-fingerprint-sha256', 'pehash', 'authentihash', 'impfuzzy'
),
'composite' => array(
'malware-sample', 'filename|md5', 'filename|sha1', 'filename|sha256', 'filename|sha224', 'filename|sha512',
'filename|sha512/224', 'filename|sha512/256', 'filename|ssdeep', 'filename|imphash', 'filename|tlsh',
'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'filename|pehash',
'filename|sha512/224', 'filename|sha512/256', 'filename|sha3-224', 'filename|sha3-256', 'filename|sha3-384',
'filename|sha3-512', 'filename|ssdeep', 'filename|imphash', 'filename|tlsh', 'filename|pehash',
'filename|authentihash', 'filename|impfuzzy'
)
);
@ -23,18 +23,17 @@ class HashesExport
public function handler($data, $options = array())
{
if ($options['scope'] === 'Attribute') {
if (in_array($data['Attribute']['type'], $this->validTypes['composite'])) {
if (in_array($data['Attribute']['type'], self::VALID_TYPES['composite'], true)) {
return explode('|', $data['Attribute']['value'])[1];
} else if (in_array($data['Attribute']['type'], $this->validTypes['simple'])) {
} else if (in_array($data['Attribute']['type'], self::VALID_TYPES['simple'], true)) {
return $data['Attribute']['value'];
}
}
if ($options['scope'] === 'Event') {
} else if ($options['scope'] === 'Event') {
$result = array();
foreach ($data['Attribute'] as $attribute) {
if (in_array($attribute['type'], $this->validTypes['composite'])) {
if (in_array($attribute['type'], self::VALID_TYPES['composite'], true)) {
$result[] = explode('|', $attribute['value'])[1];
} else if (in_array($attribute['type'], $this->validTypes['simple'])) {
} else if (in_array($attribute['type'], self::VALID_TYPES['simple'], true)) {
$result[] = $attribute['value'];
}
}

View File

@ -2,7 +2,7 @@
class JsonExport
{
public $non_restrictive_export = true;
public $non_restrictive_export = true;
/**
* @param $data
@ -11,17 +11,17 @@ class JsonExport
*/
public function handler($data, $options = array())
{
if ($options['scope'] === 'Attribute') {
return $this->__attributeHandler($data, $options);
} else if($options['scope'] === 'Event') {
return $this->__eventHandler($data, $options);
} else if($options['scope'] === 'Object') {
if ($options['scope'] === 'Attribute') {
return $this->__attributeHandler($data, $options);
} else if ($options['scope'] === 'Event') {
return $this->__eventHandler($data, $options);
} else if ($options['scope'] === 'Object') {
return $this->__objectHandler($data, $options);
} else if($options['scope'] === 'Sighting') {
return $this->__sightingsHandler($data, $options);
} else if($options['scope'] === 'GalaxyCluster') {
return $this->__galaxyClusterHandler($data, $options);
}
} else if ($options['scope'] === 'Sighting') {
return $this->__sightingsHandler($data, $options);
} else if ($options['scope'] === 'GalaxyCluster') {
return $this->__galaxyClusterHandler($data, $options);
}
}
/**
@ -29,66 +29,68 @@ class JsonExport
* @param array $options
* @return Generator
*/
private function __eventHandler($event, $options = array())
private function __eventHandler($event, $options = array())
{
App::uses('JSONConverterTool', 'Tools');
return JSONConverterTool::streamConvert($event);
}
private function __objectHandler($object, $options = array()) {
App::uses('JSONConverterTool', 'Tools');
return json_encode(JSONConverterTool::convertObject($object, false, true));
return JSONConverterTool::streamConvert($event);
}
private function __attributeHandler($attribute, $options = array())
{
$attribute = array_merge($attribute['Attribute'], $attribute);
unset($attribute['Attribute']);
if (isset($attribute['Object']) && empty($attribute['Object']['id'])) {
unset($attribute['Object']);
}
$tagTypes = array('AttributeTag', 'EventTag');
foreach($tagTypes as $tagType) {
if (isset($attribute[$tagType])) {
foreach ($attribute[$tagType] as $tk => $tag) {
if ($tagType === 'EventTag') {
$attribute[$tagType][$tk]['Tag']['inherited'] = 1;
}
$attribute['Tag'][] = $attribute[$tagType][$tk]['Tag'];
}
unset($attribute[$tagType]);
}
}
unset($attribute['value1']);
unset($attribute['value2']);
return json_encode($attribute);
}
private function __objectHandler($object, $options = array())
{
App::uses('JSONConverterTool', 'Tools');
return JsonTool::encode(JSONConverterTool::convertObject($object, false, true));
}
private function __attributeHandler($attribute, $options = array())
{
$attribute = array_merge($attribute['Attribute'], $attribute);
unset($attribute['Attribute']);
if (isset($attribute['Object']) && empty($attribute['Object']['id'])) {
unset($attribute['Object']);
}
$tagTypes = array('AttributeTag', 'EventTag');
foreach ($tagTypes as $tagType) {
if (isset($attribute[$tagType])) {
foreach ($attribute[$tagType] as $tag) {
if ($tagType === 'EventTag') {
$tag['Tag']['inherited'] = 1;
}
$attribute['Tag'][] = $tag['Tag'];
}
unset($attribute[$tagType]);
}
}
unset($attribute['value1']);
unset($attribute['value2']);
return JsonTool::encode($attribute);
}
private function __sightingsHandler($sighting, $options = array())
{
return json_encode($sighting);
return JsonTool::encode($sighting);
}
private function __galaxyClusterHandler($cluster, $options = array())
{
return json_encode($cluster);
return JsonTool::encode($cluster);
}
public function header($options = array())
{
if ($options['scope'] === 'Attribute') {
return '{"response": {"Attribute": [';
} else {
return '{"response": [';
}
if ($options['scope'] === 'Attribute') {
return '{"response": {"Attribute": [';
} else {
return '{"response": [';
}
}
public function footer($options = array())
{
if ($options['scope'] === 'Attribute') {
return ']}}' . PHP_EOL;
} else {
return ']}' . PHP_EOL;
}
if ($options['scope'] === 'Attribute') {
return ']}}' . PHP_EOL;
} else {
return ']}' . PHP_EOL;
}
}
public function separator()

View File

@ -7,84 +7,125 @@ class NidsExport
public $classtype = 'trojan-activity';
public $format = ""; // suricata (default), snort
public $supportedObjects = array('network-connection', 'ddos');
public $checkWhitelist = true;
public $checkWhitelist = true;
public $additional_params = array(
'contain' => array(
'Event' => array(
'fields' => array('threat_level_id')
)
),
'flatten' => 1
);
public $additional_params = array(
'contain' => array(
'Event' => array(
'fields' => array('threat_level_id')
)
),
public function handler($data, $options = array())
{
$continue = empty($format);
$this->checkWhitelist = false;
if ($options['scope'] === 'Attribute') {
$this->export(
array($data),
$options['user']['nids_sid'],
$options['returnFormat'],
$continue
);
} else if ($options['scope'] === 'Event') {
if (!empty($data['EventTag'])) {
$data['Event']['EventTag'] = $data['EventTag'];
}
if (!empty($data['Attribute'])) {
$this->__convertFromEventFormat($data['Attribute'], $data, $options, $continue);
}
if (!empty($data['Object'])) {
foreach ($data['Object'] as $object) {
$this->__convertFromEventFormat($object['Attribute'], $data, $options, $continue);
}
}
}
return '';
}
);
private function __convertFromEventFormat($attributes, $event, $options = array(), $continue = false) {
$rearranged = array();
foreach ($attributes as $attribute) {
$attributeTag = array();
if (!empty($attribute['AttributeTag'])) {
$attributeTag = $attribute['AttributeTag'];
unset($attribute['AttributeTag']);
}
$rearranged[] = array(
'Attribute' => $attribute,
'AttributeTag' => $attributeTag,
'Event' => $event['Event']
);
}
$this->export(
$rearranged,
$options['user']['nids_sid'],
$options['returnFormat'],
$continue
);
return true;
public function handler($data, $options = array())
{
$continue = empty($format);
$this->checkWhitelist = false;
if ($options['scope'] === 'Attribute') {
$this->export(
array($data),
$options['user']['nids_sid'],
$options['returnFormat'],
$continue
);
} else if ($options['scope'] === 'Event') {
if (!empty($data['EventTag'])) {
$data['Event']['EventTag'] = $data['EventTag'];
}
if (!empty($data['Attribute'])) {
$this->__convertFromEventFormat($data['Attribute'], $data, $options, $continue);
}
if (!empty($data['Object'])) {
$this->__convertFromEventFormatObject($data['Object'], $data, $options, $continue);
}
}
return '';
}
}
private function __convertFromEventFormat($attributes, $event, $options = array(), $continue = false) {
public function header($options = array())
{
$this->explain();
return '';
}
$rearranged = array();
foreach ($attributes as $attribute) {
$attributeTag = array();
if (!empty($attribute['AttributeTag'])) {
$attributeTag = $attribute['AttributeTag'];
unset($attribute['AttributeTag']);
}
$rearranged[] = array(
'Attribute' => $attribute,
'AttributeTag' => $attributeTag,
'Event' => $event['Event']
);
}
$this->export(
$rearranged,
$options['user']['nids_sid'],
$options['returnFormat'],
$continue
);
return true;
public function footer()
{
return implode ("\n", $this->rules);
}
}
public function separator()
{
return '';
}
private function __convertFromEventFormatObject($objects, $event, $options = array(), $continue = false) {
$rearranged = array();
foreach ($objects as $object) {
if(in_array($object['name'], $this->supportedObjects)){
$objectTag = array();
foreach($object['Attribute'] as $attribute) {
if (!empty($attribute['AttributeTag'])) {
$objectTag = array_merge($objectTag, $attribute['AttributeTag']);
unset($attribute['AttributeTag']);
}
}
$rearranged[] = array(
'Attribute' => $object, // Using 'Attribute' instead of 'Object' to comply with function export
'AttributeTag' => $objectTag, // Using 'AttributeTag' instead of 'ObjectTag' to comply with function export
'Event' => $event['Event']
);
} else { // In case no custom export exists for the object, the approach falls back to the attribute case
$this->__convertFromEventFormat($object['Attribute'], $event, $options, $continue);
}
}
$this->export(
$rearranged,
$options['user']['nids_sid'],
$options['returnFormat'],
$continue
);
return true;
}
public function header($options = array())
{
$this->explain();
return '';
}
public function footer()
{
return implode ("\n", $this->rules);
}
public function separator()
{
return '';
}
public function explain()
{
@ -93,7 +134,7 @@ class NidsExport
$this->rules[] = '# These NIDS rules contain some variables that need to exist in your configuration.';
$this->rules[] = '# Make sure you have set:';
$this->rules[] = '#';
$this->rules[] = '# $HOME_NET - Your internal network range';
$this->rules[] = '# $HOME_NET - Your internal network range';
$this->rules[] = '# $EXTERNAL_NET - The network considered as outside';
$this->rules[] = '# $SMTP_SERVERS - All your internal SMTP servers';
$this->rules[] = '# $HTTP_PORTS - The ports used to contain HTTP traffic (not required with suricata export)';
@ -106,10 +147,10 @@ class NidsExport
public function export($items, $startSid, $format="suricata", $continue = false)
{
$this->format = $format;
if ($this->checkWhitelist && !isset($this->Whitelist)) {
$this->Whitelist = ClassRegistry::init('Whitelist');
$this->whitelist = $this->Whitelist->getBlockedValues();
}
if ($this->checkWhitelist && !isset($this->Whitelist)) {
$this->Whitelist = ClassRegistry::init('Whitelist');
$this->whitelist = $this->Whitelist->getBlockedValues();
}
// output a short explanation
if (!$continue) {
@ -119,20 +160,20 @@ class NidsExport
foreach ($items as $item) {
// retrieve all tags for this item to add them to the msg
$tagsArray = [];
if (!empty($item['AttributeTag'])) {
foreach ($item['AttributeTag'] as $tag_attr) {
if (array_key_exists('name', $tag_attr['Tag'])) {
array_push($tagsArray, $tag_attr['Tag']['name']);
}
}
}
if (!empty($item['Event']['EventTag'])) {
foreach ($item['Event']['EventTag'] as $tag_event) {
if (array_key_exists('name', $tag_event['Tag'])) {
array_push($tagsArray, $tag_event['Tag']['name']);
}
}
}
if (!empty($item['AttributeTag'])) {
foreach ($item['AttributeTag'] as $tag_attr) {
if (array_key_exists('name', $tag_attr['Tag'])) {
array_push($tagsArray, $tag_attr['Tag']['name']);
}
}
}
if (!empty($item['Event']['EventTag'])) {
foreach ($item['Event']['EventTag'] as $tag_event) {
if (array_key_exists('name', $tag_event['Tag'])) {
array_push($tagsArray, $tag_event['Tag']['name']);
}
}
}
$ruleFormatMsgTags = implode(",", $tagsArray);
# proto src_ip src_port direction dst_ip dst_port msg rule_content tag sid rev
@ -142,69 +183,180 @@ class NidsExport
$sid = $startSid + ($item['Attribute']['id'] * 10); // leave 9 possible rules per attribute type
$sid++;
switch ($item['Attribute']['type']) {
// LATER nids - test all the snort attributes
// LATER nids - add the tag keyword in the rules to capture network traffic
// LATER nids - sanitize every $attribute['value'] to not conflict with snort
case 'ip-dst':
$this->ipDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-src':
$this->ipSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-dst|port':
$this->ipDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-src|port':
$this->ipSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email':
$this->emailSrcRule($ruleFormat, $item['Attribute'], $sid);
$this->emailDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-src':
$this->emailSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-dst':
$this->emailDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-subject':
$this->emailSubjectRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-attachment':
$this->emailAttachmentRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'domain':
$this->domainRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'domain|ip':
$this->domainIpRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'hostname':
$this->hostnameRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'url':
$this->urlRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'user-agent':
$this->userAgentRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ja3-fingerprint-md5':
$this->ja3Rule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ja3s-fingerprint-md5': // Atribute type doesn't exists yet (2020-12-10) but ready when created.
$this->ja3sRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'snort':
$this->snortRule($ruleFormat, $item['Attribute'], $sid, $ruleFormatMsg, $ruleFormatReference);
// no break
default:
break;
if(!empty($item['Attribute']['type'])) { // item is an 'Attribute'
switch ($item['Attribute']['type']) {
// LATER nids - test all the snort attributes
// LATER nids - add the tag keyword in the rules to capture network traffic
// LATER nids - sanitize every $attribute['value'] to not conflict with snort
case 'ip-dst':
$this->ipDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-src':
$this->ipSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-dst|port':
$this->ipDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ip-src|port':
$this->ipSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email':
$this->emailSrcRule($ruleFormat, $item['Attribute'], $sid);
$sid++;
$this->emailDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-src':
$this->emailSrcRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-dst':
$this->emailDstRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-subject':
$this->emailSubjectRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'email-attachment':
$this->emailAttachmentRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'domain':
$this->domainRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'domain|ip':
$this->domainIpRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'hostname':
$this->hostnameRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'url':
$this->urlRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'user-agent':
$this->userAgentRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ja3-fingerprint-md5':
$this->ja3Rule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ja3s-fingerprint-md5': // Atribute type doesn't exists yet (2020-12-10) but ready when created.
$this->ja3sRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'snort':
$this->snortRule($ruleFormat, $item['Attribute'], $sid, $ruleFormatMsg, $ruleFormatReference);
// no break
default:
break;
}
} else if(!empty($item['Attribute']['name'])) { // Item is an 'Object'
switch ($item['Attribute']['name']) {
case 'network-connection':
$this->networkConnectionRule($ruleFormat, $item['Attribute'], $sid);
break;
case 'ddos':
$this->ddosRule($ruleFormat, $item['Attribute'], $sid);
break;
default:
break;
}
}
}
return $this->rules;
}
public function networkConnectionRule($ruleFormat, $object, &$sid)
{
$attributes = NidsExport::getObjectAttributes($object);
if(!array_key_exists('layer4-protocol', $attributes)){
$attributes['layer4-protocol'] = 'ip'; // If layer-4 protocol is unknown, we roll-back to layer-3 ('ip')
}
if(!array_key_exists('ip-src', $attributes)){
$attributes['ip-src'] = '$HOME_NET'; // If ip-src is unknown, we roll-back to $HOME_NET
}
if(!array_key_exists('ip-dst', $attributes)){
$attributes['ip-dst'] = '$HOME_NET'; // If ip-dst is unknown, we roll-back to $HOME_NET
}
if(!array_key_exists('src-port', $attributes)){
$attributes['src-port'] = 'any'; // If src-port is unknown, we roll-back to 'any'
}
if(!array_key_exists('dst-port', $attributes)){
$attributes['dst-port'] = 'any'; // If dst-port is unknown, we roll-back to 'any'
}
$this->rules[] = sprintf(
$ruleFormat,
false,
$attributes['layer4-protocol'], // proto
$attributes['ip-src'], // src_ip
$attributes['src-port'], // src_port
'->', // direction
$attributes['ip-dst'], // dst_ip
$attributes['dst-port'], // dst_port
'Network connection between ' . $attributes['ip-src'] . ' and ' . $attributes['ip-dst'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
}
public function ddosRule($ruleFormat, $object, &$sid)
{
$attributes = NidsExport::getObjectAttributes($object);
if(!array_key_exists('protocol', $attributes)){
$attributes['protocol'] = 'ip'; // If protocol is unknown, we roll-back to 'ip'
}
if(!array_key_exists('ip-src', $attributes)){
$attributes['ip-src'] = '$HOME_NET'; // If ip-src is unknown, we roll-back to $HOME_NET
}
if(!array_key_exists('ip-dst', $attributes)){
$attributes['ip-dst'] = '$HOME_NET'; // If ip-dst is unknown, we roll-back to $HOME_NET
}
if(!array_key_exists('src-port', $attributes)){
$attributes['src-port'] = 'any'; // If src-port is unknown, we roll-back to 'any'
}
if(!array_key_exists('dst-port', $attributes)){
$attributes['dst-port'] = 'any'; // If dst-port is unknown, we roll-back to 'any'
}
$this->rules[] = sprintf(
$ruleFormat,
false,
$attributes['protocol'], // proto
$attributes['ip-src'], // src_ip
$attributes['src-port'], // src_port
'->', // direction
$attributes['ip-dst'], // dst_ip
$attributes['dst-port'], // dst_port
'DDOS attack detected between ' . $attributes['ip-src'] . ' and ' . $attributes['ip-dst'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
}
public static function getObjectAttributes($object)
{
$attributes = array();
foreach ($object['Attribute'] as $attribute) {
$attributes[$attribute['object_relation']] = $attribute['value'];
}
return $attributes;
}
public function domainIpRule($ruleFormat, $attribute, &$sid)
{
$values = explode('|', $attribute['value']);
@ -225,17 +377,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'ip', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
$ipport[0], // dst_ip
$ipport[1], // dst_port
'Outgoing To IP: ' . $attribute['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
'ip', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
$ipport[0], // dst_ip
$ipport[1], // dst_port
'Outgoing To IP: ' . $attribute['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
}
@ -246,17 +398,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'ip', // proto
$ipport[0], // src_ip
$ipport[1], // src_port
'->', // direction
'$HOME_NET', // dst_ip
'any', // dst_port
'Incoming From IP: ' . $attribute['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
'ip', // proto
$ipport[0], // src_ip
$ipport[1], // src_port
'->', // direction
'$HOME_NET', // dst_ip
'any', // dst_port
'Incoming From IP: ' . $attribute['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
}
@ -268,17 +420,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Source Email Address: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Source Email Address: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -290,17 +442,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Destination Email Address: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Destination Email Address: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -313,17 +465,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Subject', // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Subject', // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -336,17 +488,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Attachment', // msg
$content, // rule_content // LATER nids - test and finetune this snort rule https://secure.wikimedia.org/wikipedia/en/wiki/MIME#Content-Disposition
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'->', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Attachment', // msg
$content, // rule_content // LATER nids - test and finetune this snort rule https://secure.wikimedia.org/wikipedia/en/wiki/MIME#Content-Disposition
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -358,33 +510,33 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'udp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
'udp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content. ' flow:established;', // rule_content
'', // tag
$sid, // sid
1 // rev
'tcp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content. ' flow:established;', // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests
@ -392,17 +544,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -414,33 +566,33 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'udp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
'udp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content. ' flow:established;', // rule_content
'', // tag
$sid, // sid
1 // rev
'tcp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content. ' flow:established;', // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests,
@ -448,17 +600,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP Domain: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP Domain: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -473,17 +625,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP URL: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing HTTP URL: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -495,17 +647,17 @@ class NidsExport
$this->rules[] = sprintf(
$ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing User-Agent: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing User-Agent: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
@ -527,37 +679,37 @@ class NidsExport
$tmpRule = str_replace(array("\r","\n"), " ", $attribute['value']);
// rebuild the rule by overwriting the different keywords using preg_replace()
// sid - '/sid\s*:\s*[0-9]+\s*;/'
// rev - '/rev\s*:\s*[0-9]+\s*;/'
// sid - '/sid\s*:\s*[0-9]+\s*;/'
// rev - '/rev\s*:\s*[0-9]+\s*;/'
// classtype - '/classtype:[a-zA-Z_-]+;/'
// msg - '/msg\s*:\s*".*?"\s*;/'
// msg - '/msg\s*:\s*".*?"\s*;/'
// reference - '/reference\s*:\s*.+?;/'
// tag - '/tag\s*:\s*.+?;/'
// tag - '/tag\s*:\s*.+?;/'
$replaceCount = array();
$tmpRule = preg_replace('/sid\s*:\s*[0-9]+\s*;/', 'sid:' . $sid . ';', $tmpRule, -1, $replaceCount['sid']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
$tmpRule = preg_replace('/rev\s*:\s*[0-9]+\s*;/', 'rev:1;', $tmpRule, -1, $replaceCount['rev']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
$tmpRule = preg_replace('/classtype:[a-zA-Z_-]+;/', 'classtype:' . $this->classtype . ';', $tmpRule, -1, $replaceCount['classtype']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
$tmpRule = preg_replace('/msg\s*:\s*"(.*?)"\s*;/', sprintf($ruleFormatMsg, 'snort-rule | $1') . ';', $tmpRule, -1, $replaceCount['msg']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
$tmpRule = preg_replace('/reference\s*:\s*.+?;/', $ruleFormatReference . ';', $tmpRule, -1, $replaceCount['reference']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
$tmpRule = preg_replace('/reference\s*:\s*.+?;/', $ruleFormatReference . ';', $tmpRule, -1, $replaceCount['reference']);
if (null == $tmpRule) {
return false;
} // don't output the rule on error with the regex
} // don't output the rule on error with the regex
// FIXME nids - implement priority overwriting
// some values were not replaced, so we need to add them ourselves, and insert them in the rule
@ -667,13 +819,13 @@ class NidsExport
public function checkWhitelist($value)
{
if ($this->checkWhitelist && is_array($this->whitelist)) {
foreach ($this->whitelist as $wlitem) {
if (preg_match($wlitem, $value)) {
return true;
}
}
}
if ($this->checkWhitelist && is_array($this->whitelist)) {
foreach ($this->whitelist as $wlitem) {
if (preg_match($wlitem, $value)) {
return true;
}
}
}
return false;
}

View File

@ -387,10 +387,11 @@ class AttachmentTool
* @param string $data
* @param int $maxWidth
* @param int $maxHeight
* @param string $outputFormat Can be 'png' or 'webp'
* @return string
* @throws Exception
*/
public function resizeImage($data, $maxWidth, $maxHeight)
public function resizeImage($data, $maxWidth, $maxHeight, $outputFormat = 'png')
{
$image = imagecreatefromstring($data);
if ($image === false) {
@ -425,7 +426,16 @@ class AttachmentTool
// Output image to string
ob_start();
imagepng($imageThumbnail, null, 9);
if ($outputFormat === 'webp') {
if (!function_exists('imagewebp')) {
throw new InvalidArgumentException("Webp image format is not supported.");
}
imagewebp($imageThumbnail);
} elseif ($outputFormat === 'png') {
imagepng($imageThumbnail, null, 9);
} else {
throw new InvalidArgumentException("Unsupported image format $outputFormat.");
}
$imageData = ob_get_clean();
imagedestroy($imageThumbnail);
@ -460,7 +470,8 @@ class AttachmentTool
*/
public function attachmentDirIsS3()
{
return substr(Configure::read('MISP.attachments_dir'), 0, 2) === "s3";
$attachmentsDir = Configure::read('MISP.attachments_dir');
return $attachmentsDir && substr($attachmentsDir, 0, 2) === "s3";
}
/**

View File

@ -407,7 +407,7 @@ class AttributeValidationTool
case 'dns-soa-email':
case 'jabber-id':
// we don't use the native function to prevent issues with partial email addresses
if (preg_match("#^.*\@.*\..*$#i", $value)) {
if (preg_match("#^.[^\s]*\@.*\..*$#i", $value)) {
return true;
}
return __('Email address has an invalid format. Please double check the value or select type "other".');

View File

@ -7,17 +7,17 @@ App::uses('BackgroundJob', 'Tools/BackgroundJobs');
/**
* BackgroundJobs Tool
*
*
* Utility class to queue jobs, run them and monitor workers.
*
*
* To run a worker manually (debug only):
* $ ./Console/cake start_worker [queue]
*
*
* It is recommended to run these commands with [Supervisor](http://supervisord.org).
* `Supervisor` has an extensive feature set to manage scripts as services,
* such as autorestart, parallel execution, logging, monitoring and much more.
* `Supervisor` has an extensive feature set to manage scripts as services,
* such as autorestart, parallel execution, logging, monitoring and much more.
* All can be managed via the terminal or a XML-RPC API.
*
*
* Use the following configuration as a template for the services:
* /etc/supervisor/conf.d/misp-workers.conf:
* [group:misp-workers]
@ -27,14 +27,14 @@ App::uses('BackgroundJob', 'Tools/BackgroundJobs');
* [program:default]
* command=/var/www/MISP/app/Console/cake start_worker default
* process_name=%(program_name)s_%(process_num)02d
* numprocs=5 ; adjust the amount of parallel workers to your MISP usage
* numprocs=5 ; adjust the amount of parallel workers to your MISP usage
* autostart=true
* autorestart=true
* redirect_stderr=false
* stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log
* stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log
* user=www-data
*
*
*/
class BackgroundJobsTool
{
@ -73,18 +73,21 @@ class BackgroundJobsTool
const
CMD_EVENT = 'event',
CMD_SERVER = 'server',
CMD_ADMIN = 'admin';
CMD_ADMIN = 'admin',
CMD_WORKFLOW = 'workflow';
const ALLOWED_COMMANDS = [
self::CMD_EVENT,
self::CMD_SERVER,
self::CMD_ADMIN
self::CMD_ADMIN,
self::CMD_WORKFLOW,
];
const CMD_TO_SHELL_DICT = [
self::CMD_EVENT => 'EventShell',
self::CMD_SERVER => 'ServerShell',
self::CMD_ADMIN => 'AdminShell'
self::CMD_ADMIN => 'AdminShell',
self::CMD_WORKFLOW => 'WorkflowShell',
];
const JOB_STATUS_PREFIX = 'job_status';
@ -176,7 +179,7 @@ class BackgroundJobsTool
/**
* Enqueue a Job using the CakeResque.
* @deprecated
*
*
* @param string $queue Name of the queue to enqueue the job to.
* @param string $class Class of the job.
* @param array $args Arguments passed to the job.
@ -212,9 +215,9 @@ class BackgroundJobsTool
*
* @param string $queue Queue name, e.g. 'default'.
* @param int $timeout Time to block the read if the queue is empty.
* Must be less than your configured `read_write_timeout`
* Must be less than your configured `read_write_timeout`
* for the redis connection.
*
*
* @throws Exception
*/
public function dequeue($queue, int $timeout = 30)
@ -262,7 +265,7 @@ class BackgroundJobsTool
* Clear all the queue's jobs.
*
* @param string $queue Queue name, e.g. 'default'.
*
*
* @return boolean True on success, false on failure.
*/
public function clearQueue($queue): bool
@ -309,7 +312,7 @@ class BackgroundJobsTool
* Get the number of jobs inside a queue.
*
* @param string $queue Queue name, e.g. 'default'.
*
*
* @return integer Number of jobs.
*/
public function getQueueSize(string $queue): int
@ -327,7 +330,7 @@ class BackgroundJobsTool
* Update job
*
* @param BackgroundJob $job
*
*
* @return void
*/
public function update(BackgroundJob $job)

View File

@ -0,0 +1,63 @@
<?php
class BetterCakeEventManager extends CakeEventManager
{
/**
* This method is similar as original dispatch, but do not return newly created event. With returning event, there is
* big memory leak in PHP at least for PHP version 7.4.19.
* @param CakeEvent $event
*/
public function dispatch($event)
{
$listeners = $this->listeners($event->name());
if (empty($listeners)) {
return null;
}
foreach ($listeners as $listener) {
if ($event->isStopped()) {
break;
}
if ($listener['passParams'] === true) {
$result = call_user_func_array($listener['callable'], $event->data);
} else {
$result = $listener['callable']($event);
}
if ($result === false) {
$event->stopPropagation();
}
if ($result !== null) {
$event->result = $result;
}
}
}
/**
* @param $eventKey
* @return array
*/
public function listeners($eventKey)
{
if ($this->_isGlobal) {
$localListeners = [];
} else {
$localListeners = $this->_listeners[$eventKey] ?? [];
}
$globalListeners = static::instance()->prioritisedListeners($eventKey);
$priorities = array_merge(array_keys($globalListeners), array_keys($localListeners));
$priorities = array_unique($priorities, SORT_REGULAR);
asort($priorities);
$result = [];
foreach ($priorities as $priority) {
if (isset($globalListeners[$priority])) {
$result = array_merge($result, $globalListeners[$priority]);
}
if (isset($localListeners[$priority])) {
$result = array_merge($result, $localListeners[$priority]);
}
}
return $result;
}
}

View File

@ -31,14 +31,14 @@ class ComplexTypeTool
)
);
const HEX_HASH_TYPES = array(
32 => array('single' => array('md5', 'imphash', 'x509-fingerprint-md5'), 'composite' => array('filename|md5', 'filename|imphash')),
40 => array('single' => array('sha1', 'pehash', 'x509-fingerprint-sha1', 'cdhash'), 'composite' => array('filename|sha1', 'filename|pehash')),
56 => array('single' => array('sha224', 'sha512/224'), 'composite' => array('filename|sha224', 'filename|sha512/224')),
64 => array('single' => array('sha256', 'authentihash', 'sha512/256', 'x509-fingerprint-sha256'), 'composite' => array('filename|sha256', 'filename|authentihash', 'filename|sha512/256')),
96 => array('single' => array('sha384'), 'composite' => array('filename|sha384')),
128 => array('single' => array('sha512'), 'composite' => array('filename|sha512'))
);
const HEX_HASH_TYPES = [
32 => ['single' => ['md5', 'imphash', 'x509-fingerprint-md5', 'ja3-fingerprint-md5'], 'composite' => ['filename|md5', 'filename|imphash']],
40 => ['single' => ['sha1', 'pehash', 'x509-fingerprint-sha1', 'cdhash'], 'composite' => ['filename|sha1', 'filename|pehash']],
56 => ['single' => ['sha224', 'sha512/224'], 'composite' => ['filename|sha224', 'filename|sha512/224']],
64 => ['single' => ['sha256', 'authentihash', 'sha512/256', 'x509-fingerprint-sha256'], 'composite' => ['filename|sha256', 'filename|authentihash', 'filename|sha512/256']],
96 => ['single' => ['sha384'], 'composite' => ['filename|sha384']],
128 => ['single' => ['sha512'], 'composite' => ['filename|sha512']],
];
private $__tlds = null;

View File

@ -83,14 +83,14 @@ class CustomPaginationTool
$items = array_values($items);
}
public function sortArray($items, $params, $escapeReindex = false)
public function sortArray(array $items, $params, $escapeReindex = false)
{
if (isset($params['sort'])) {
$sortArray = array();
foreach ($items as $k => $item) {
$sortArray[$k] = !empty(Hash::get($item, $params['sort'])) ? $item[$params['sort']] : '';
$sortArray[$k] = !empty($item[$params['sort']]) ? $item[$params['sort']] : '';
}
if (empty($params['options']['direction']) || $params['options']['direction'] == 'asc') {
if (empty($params['options']['direction']) || $params['options']['direction'] === 'asc') {
asort($sortArray);
} else {
arsort($sortArray);
@ -107,12 +107,13 @@ class CustomPaginationTool
return $items;
}
public function applyRulesOnArray(&$items, $options, $model, $sort = 'id', $focusKey = 'uuid', $escapeReindex = false)
public function applyRulesOnArray(array &$items, $options, $model, $sort = 'id', $focusKey = 'uuid', $escapeReindex = false)
{
$params = $this->createPaginationRules($items, $options, $model, $sort, $focusKey);
$items = $this->sortArray($items, $params, $escapeReindex);
if (!empty($params['options']['focus'])) {
$focus = $params['options']['focus'];
$focus = $params['options']['focus'];
foreach ($items as $k => $item) {
if ($item[$focusKey] === $focus) {
$params['page'] = 1 + intval(floor($k / $params['limit']));
@ -122,6 +123,7 @@ class CustomPaginationTool
}
unset($params['options']['focus']);
}
// Start array from one
array_unshift($items, 'dummy');
unset($items[0]);
$this->truncateByPagination($items, $params);

View File

@ -96,7 +96,7 @@ class FileAccessTool
* @param bool $createFolder
* @throws Exception
*/
public static function writeToFile($file, $content, $createFolder = false)
public static function writeToFile($file, $content, $createFolder = false, $append = false)
{
$dir = dirname($file);
if ($createFolder && !is_dir($dir)) {
@ -105,7 +105,7 @@ class FileAccessTool
}
}
if (file_put_contents($file, $content, LOCK_EX) === false) {
if (file_put_contents($file, $content, LOCK_EX | (!empty($append) ? FILE_APPEND : 0)) === false) {
$freeSpace = disk_free_space($dir);
throw new Exception("An error has occurred while attempt to write to file `$file`. Maybe not enough space? ($freeSpace bytes left)");
}

View File

@ -0,0 +1,97 @@
<?php
class GraphvizDOTTool
{
const NODE_STYLE = [
'trigger' => [
'margin' => 0,
'shape' => 'diamond',
],
'logic' => [
'margin' => 0,
'shape' => 'parallelogram',
],
'action' => [
'margin' => 0,
'shape' => 'box',
],
];
const EDGE_STYLE = [
];
/**
* dot Get DOT language format of the provided graph
*
* @return string
*/
public static function dot(array $graph_data)
{
$parsedGraph = self::__parseGraph($graph_data);
$str = self::__header();
$str .= self::__nodes($parsedGraph['nodes']);
$str .= self::__edges($parsedGraph['edges']);
$str .= self::__footer();
return $str;
}
private static function __parseGraph($graph_data)
{
$graphUtil = new GraphUtil($graph_data);
$nodes = $graphUtil->graph;
$edges = $graphUtil->edgeList;
return [
'nodes' => $nodes,
'edges' => $edges,
];
}
private static function __header()
{
return 'digraph G {' . PHP_EOL;
}
private static function __footer()
{
return '}';
}
private static function __nodes($nodes)
{
$str = ' {' . PHP_EOL;
foreach ($nodes as $node) {
$str .= ' ' . self::__node($node);
}
$str .= ' }' . PHP_EOL;
return $str;
}
private static function __node(array $node)
{
$node_attributes = self::NODE_STYLE[$node['data']['module_type']];
$node_attributes['label'] = $node['data']['name'];
$node_attributes_text = self::__arrayToAttributes($node_attributes);
return sprintf('%s [%s]' . PHP_EOL, $node['id'], $node_attributes_text);
}
private static function __edges($edges)
{
$str = '';
foreach ($edges as $source_id => $target_ids) {
foreach ($target_ids as $target_id) {
$str .= ' ' . self::__edge($source_id, $target_id);
}
}
return $str;
}
private static function __edge($source_id, $target_id)
{
return sprintf('%s -> %s [%s]' . PHP_EOL, $source_id, $target_id, self::__arrayToAttributes(self::EDGE_STYLE));
}
private static function __arrayToAttributes(array $list)
{
return implode(', ', array_map(function ($key, $value) {
return sprintf('%s="%s"', $key, $value);
}, array_keys($list), $list));
}
}

View File

@ -187,11 +187,7 @@ class JSONConverterTool
$resultArray = ': ' . $array . PHP_EOL;
}
if ($root) {
$text = '';
foreach ($resultArray as $r) {
$text .= $r;
}
return $text;
return implode('', $resultArray);
} else {
return $resultArray;
}

View File

@ -0,0 +1,83 @@
<?php
App::uses('FontAwesomeHelper', 'View/Helper');
require_once APP . 'Lib/Tools/WorkflowGraphTool.php';
class MermaidFlowchartTool
{
const NODE_STYLE = [
'trigger' => '{{%s}}',
'logic' => '[/%s/]',
'action' => '[%s]',
];
/**
* dot Get DOT language format of the provided graph
*
* @return string
*/
public static function mermaid(array $graph_data)
{
$parsedGraph = self::__parseGraph($graph_data);
$str = self::__header();
$str .= self::__nodes($parsedGraph['nodes'], $parsedGraph['edges']);
$str .= self::__footer();
return $str;
}
private static function __parseGraph($graph_data)
{
$graphUtil = new GraphUtil($graph_data);
$nodes = Hash::combine($graphUtil->graph, '{n}.id', '{n}');
$edges = $graphUtil->edgeList;
return [
'nodes' => $nodes,
'edges' => $edges,
];
}
private static function __header()
{
return 'flowchart LR' . PHP_EOL;
}
private static function __footer()
{
return '';
}
private static function __nodes($nodes, $edges)
{
$str = '';
foreach ($nodes as $node) {
$str .= self::__node($nodes, $node, $edges[$node['id']]);
}
return $str;
}
private static function __node(array $all_nodes, array $node, array $edges)
{
$str = '';
foreach ($edges as $target_id) {
if (empty($all_nodes[$target_id])) {
continue;
}
$target_node = $all_nodes[$target_id];
$sourceNode = self::__singleNode($node);
$targetNode = self::__singleNode($target_node);
$str .= ' ' . sprintf('%s --> %s', $sourceNode, $targetNode) . PHP_EOL;
}
return $str;
}
private static function __singleNode(array $node)
{
$str = $node['id'];
$icon = sprintf("%s:fa-%s ", FontAwesomeHelper::findNamespace($node['data']['module_data']['icon']), $node['data']['module_data']['icon']);
$node_content = sprintf('"%s%s"',(!empty($node['data']['module_data']['icon']) ? "$icon " : ''), $node['name']);
$str .= sprintf(
self::NODE_STYLE[$node['data']['module_type']],
$node_content
);
return $str;
}
}

View File

@ -1,7 +1,7 @@
<?php
class ProcessException extends Exception
{
/** @var string */
/** @var string|null */
private $stderr;
/** @var string */
@ -10,13 +10,14 @@ class ProcessException extends Exception
/**
* @param string|array $command
* @param int $returnCode
* @param string $stderr
* @param string|null $stderr
* @param string $stdout
*/
public function __construct($command, $returnCode, $stderr, $stdout)
{
$commandForException = is_array($command) ? implode(' ', $command) : $command;
$message = "Command '$commandForException' return error code $returnCode.\nSTDERR: '$stderr'\nSTDOUT: '$stdout'";
$stderrToMessage = $stderr === null ? 'Logged to tmp/logs/exec-errors.log' : "'$stderr'";
$message = "Command '$commandForException' finished with error code $returnCode.\nSTDERR: $stderrToMessage\nSTDOUT: '$stdout'";
$this->stderr = $stderr;
$this->stdout = $stdout;
parent::__construct($message, $returnCode);
@ -48,13 +49,13 @@ class ProcessTool
public static function execute(array $command, $cwd = null, $stderrToFile = false)
{
$descriptorSpec = [
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"], // stderr
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'], // stderr
];
if ($stderrToFile) {
self::logMessage('Running command ' . implode(' ', $command));
$descriptorSpec[2] = ["file", self::LOG_FILE, 'a'];
$descriptorSpec[2] = ['file', self::LOG_FILE, 'a'];
}
// PHP older than 7.4 do not support proc_open with array, so we need to convert values to string manually

View File

@ -62,9 +62,13 @@ class PubSubTool
if ($response === null) {
throw new Exception("No response from status command returned after 5 seconds.");
}
return json_decode(trim($response[1]), true);
return JsonTool::decode(trim($response[1]));
}
/**
* @return bool
* @throws ProcessException
*/
public function checkIfPythonLibInstalled()
{
$script = APP . 'files' . DS . 'scripts' . DS . 'mispzmq' . DS . 'mispzmqtest.py';
@ -143,6 +147,12 @@ class PubSubTool
return $this->pushToRedis('data:misp_json_warninglist', $warninglist);
}
public function workflow_push(array $data)
{
$topic = 'data:misp_json_workflow';
return $this->pushToRedis($topic, $data);
}
/**
* @param array $data
* @param string $type
@ -301,7 +311,7 @@ class PubSubTool
$pluginConfig = Configure::read('Plugin');
foreach ($settings as $key => $setting) {
$temp = isset($pluginConfig['ZeroMQ_' . $key]) ? $pluginConfig['ZeroMQ_' . $key] : null;
$temp = $pluginConfig['ZeroMQ_' . $key] ?? null;
if ($temp) {
$settings[$key] = $temp;
}

View File

@ -14,7 +14,7 @@ class QueryTool
{
$db = $model->getDataSource();
$connection = $db->getConnection();
if ($db->config['datasource'] === 'Database/Mysql' || $db->config['datasource'] === 'Database/MysqlObserver') {
if (in_array($db->config['datasource'], ['Database/Mysql', 'Database/MysqlObserver', 'Database/MysqlExtended'])) {
$query = $connection->prepare('DELETE FROM ' . $table . ' WHERE ' . $field . ' = :value');
} elseif ($db->config['datasource'] == 'Database/Postgres' ) {
$query = $connection->prepare('DELETE FROM "' . $table . '" WHERE "' . $field . '" = :value');

View File

@ -431,7 +431,7 @@ class SecurityAudit
App::uses('CakeEmail', 'Network/Email');
$email = new CakeEmail();
$emailConfig = $email->config();
if ($emailConfig['transport'] === 'Smtp' && $emailConfig['port'] == 25 && !$emailConfig['tls']) {
if ($emailConfig['transport'] === 'Smtp' && $emailConfig['port'] == 25 && empty($emailConfig['tls'])) {
$output['Email'][] = [
'warning',
__('STARTTLS is not enabled.'),

View File

@ -114,7 +114,7 @@ class CakeEmailExtended extends CakeEmail
throw new InvalidArgumentException("Expected instance of CakeEmailBody, " . gettype($this->body) . " given.");
}
$this->_boundary = md5(uniqid());
$this->_boundary = md5(mt_rand());
$rendered = [];
if (!empty($this->body->text)) {
@ -191,7 +191,7 @@ class MimeMultipart
public function __construct($subtype = 'mixed', $additionalTypes = array())
{
$this->subtype = $subtype;
$this->boundary = md5(uniqid());
$this->boundary = md5(mt_rand());
$this->additionalTypes = $additionalTypes;
}
@ -484,6 +484,10 @@ class SendEmail
]);
}
if ($body instanceof SendEmailTemplate && $body->listUnsubscribe()) {
$email->addHeaders(['List-Unsubscribe' => "<{$body->listUnsubscribe()}>"]);
}
$signed = false;
if (Configure::read('GnuPG.sign')) {
if (!$this->gpg) {

View File

@ -10,6 +10,9 @@ class SendEmailTemplate
/** @var string|null */
private $referenceId;
/** @var string */
private $listUnsubscribe;
/** @var string|null */
private $subject;
@ -31,6 +34,18 @@ class SendEmailTemplate
$this->referenceId = $referenceId;
}
/**
* @param string|null $listUnsubscribe
* @return string|void
*/
public function listUnsubscribe($listUnsubscribe = null)
{
if ($listUnsubscribe === null) {
return $this->listUnsubscribe;
}
$this->listUnsubscribe = $listUnsubscribe;
}
/**
* Get subject from template. Must be called after render method.
* @param string|null $subject

View File

@ -1,5 +1,6 @@
<?php
App::uses('SyncTool', 'Tools');
App::uses('JsonTool', 'Tools');
class ServerSyncTool
{
@ -8,8 +9,11 @@ class ServerSyncTool
FEATURE_ORG_RULE = 'org_rule',
FEATURE_FILTER_SIGHTINGS = 'filter_sightings',
FEATURE_PROPOSALS = 'proposals',
FEATURE_PROTECTED_EVENT = 'protected_event',
FEATURE_POST_TEST = 'post_test',
FEATURE_PROTECTED_EVENT = 'protected_event';
FEATURE_EDIT_OF_GALAXY_CLUSTER = 'edit_of_galaxy_cluster',
PERM_SYNC = 'perm_sync',
PERM_GALAXY_EDITOR = 'perm_galaxy_editor';
/** @var array */
private $server;
@ -89,6 +93,17 @@ class ServerSyncTool
return $this->get($url);
}
/**
* @param array $events
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException
* @throws HttpSocketJsonException
*/
public function filterEventIdsForPush(array $events)
{
return $this->post('/events/filterEventIdsForPush', $events);
}
/**
* @param array $event
* @return HttpSocketResponseExtended
@ -164,6 +179,39 @@ class ServerSyncTool
return $this->post('/attributes/restSearch.json', $rules);
}
/**
* @param array $rules
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException
* @throws HttpSocketJsonException
*/
public function galaxyClusterSearch(array $rules)
{
return $this->post('/galaxy_clusters/restSearch', $rules);
}
/**
* @param int|string $galaxyClusterId Galaxy Cluster ID or UUID
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException
*/
public function fetchGalaxyCluster($galaxyClusterId)
{
return $this->get('/galaxy_clusters/view/' . $galaxyClusterId);
}
/**
* @param array $cluster
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException
* @throws HttpSocketJsonException
*/
public function pushGalaxyCluster(array $cluster)
{
$logMessage = "Pushing Galaxy Cluster #{$cluster['GalaxyCluster']['id']} to Server #{$this->serverId()}";
return $this->post('/galaxies/pushCluster', [$cluster], $logMessage);
}
/**
* @param array $params
* @return HttpSocketResponseExtended
@ -332,6 +380,12 @@ class ServerSyncTool
case self::FEATURE_PROTECTED_EVENT:
$version = explode('.', $info['version']);
return $version[0] == 2 && $version[1] == 4 && $version[2] > 155;
case self::FEATURE_EDIT_OF_GALAXY_CLUSTER:
return isset($info['perm_galaxy_editor']);
case self::PERM_SYNC:
return isset($info['perm_sync']) && $info['perm_sync'];
case self::PERM_GALAXY_EDITOR:
return isset($info['perm_galaxy_editor']) && $info['perm_galaxy_editor'];
default:
throw new InvalidArgumentException("Invalid flag `$flag` provided");
}
@ -373,7 +427,7 @@ class ServerSyncTool
private function post($url, $data, $logMessage = null)
{
$protectedMode = !empty($data['Event']['protected']);
$data = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$data = JsonTool::encode($data);
if ($logMessage && !empty(Configure::read('Security.sync_audit'))) {
$pushLogEntry = sprintf(

View File

@ -192,6 +192,19 @@ class TmpFileTool
return fstat($this->tmpfile)['size'];
}
/**
* @param string $algo
* @return string
* @throws Exception
*/
public function hash($algo)
{
$this->rewind();
$hash = hash_init($algo);
hash_update_stream($hash, $this->tmpfile);
return hash_final($hash);
}
/**
* @return string
* @throws Exception

View File

@ -0,0 +1,142 @@
<?php
App::uses('JSONConverterTool', 'Tools');
/**
* WorkflowFormatConverterTool convert passed data into the MISP core format with these additional properties:
* - Attributes are encapsulated in the Event they belong to as well as their object (if applicable)
* - Events have an additional key `_AttributeFlattened` which combines both Attribute and ObjectAttribute in the same array
* - Attributes have an additional key `_allTags` which group both AttributeTag and EventTag.
* - Tags in this `_allTags` key have an additional flag `inherited` indicating if the tag has been propagated from the Event to the Attribute
*/
class WorkflowFormatConverterTool
{
private static $fakeSiteAdminUser = ['Role' => ['perm_site_admin' => true]];
public static function convert(array $data, $scope=''): array
{
if (empty($scope)) {
$scope = self::__guessScopeFromData($data);
}
$converted = [];
switch ($scope) {
case 'event':
$converted = self::__convertEvent($data);
break;
case 'attribute':
$converted = self::__convertAttribute($data);
break;
case 'object':
$converted = self::__convertObject($data);
break;
default:
break;
}
$converted = self::__includeFlattenedAttributes($converted);
return $converted;
}
private static function __convertEvent(array $event): array
{
$converted = [];
$converted = JSONConverterTool::convert($event, false, true);
return $converted;
}
private static function __convertObject(array $object): array
{
$converted = [];
$convertedObject = JSONConverterTool::convertObject($object, false, true);
$convertedObject = ['Object' => $convertedObject['Object']];
$converted = self::__encapsulateEntityWithEvent($convertedObject);
return $converted;
}
/**
* __convertAttribute Convert and clean an attribute. May also transform the attribute into an Object if applicable.
* However, the object will not be full and will only contain the attribute
*
* @param array $attribute
* @return array
*/
private static function __convertAttribute(array $attribute): array
{
$allTags = [];
if (!empty($attribute['EventTag'])) {
foreach ($attribute['AttributeTag'] as $attributeTag) {
$attributeTag['Tag']['inherited'] = false;
$allTags[] = $attributeTag['Tag'];
}
foreach ($attribute['EventTag'] as $eventTag) {
$eventTag['Tag']['inherited'] = true;
$allTags[] = $eventTag['Tag'];
}
}
$convertedAttribute = JSONConverterTool::convertAttribute($attribute, true);
$convertedAttribute['Attribute']['_allTags'] = $allTags;
if ($convertedAttribute['Attribute']['object_id'] != 0) {
$objectModel = ClassRegistry::init('MispObject');
$object = $objectModel->fetchObjectSimple(self::$fakeSiteAdminUser, [
'conditions' => [
'Object.id' => $convertedAttribute['Attribute']['object_id'],
],
]);
if (!empty($object)) {
$object = $object[0]['Object'];
$object['Attribute'][] = $convertedAttribute['Attribute'];
$convertedAttribute = ['Object' => $object];
} else {
$convertedAttribute = ['Attribute' => $convertedAttribute['Attribute']];
}
} else {
$convertedAttribute = ['Attribute' => $convertedAttribute['Attribute']];
}
$converted = self::__encapsulateEntityWithEvent($convertedAttribute);
return $converted;
}
private static function __encapsulateEntityWithEvent(array $data): array
{
$eventModel = ClassRegistry::init('Event');
$event = $eventModel->fetchSimpleEvent(self::$fakeSiteAdminUser, $data['Attribute']['event_id'] ?? $data['Object']['event_id'], [
'contain' => [
'EventTag' => ['Tag']
]
]);
if (empty($event)) {
return [];
}
$event = self::__convertEvent($event);
$event = $event['Event'];
reset($data);
$entityType = key($data);
$event[$entityType][] = $data[$entityType];
return ['Event' => $event];
}
private static function __includeFlattenedAttributes(array $event): array
{
$attributes = $event['Event']['Attribute'] ?? [];
$objectAttributes = Hash::extract($event['Event']['Object'] ?? [], '{n}.Attribute.{n}');
$event['Event']['_AttributeFlattened'] = array_merge($attributes, $objectAttributes);
return $event;
}
private static function __guessScopeFromData(array $data)
{
if (isset($data['Object']) && !isset($data['Attribute'])) {
return 'object';
}
if (!isset($data['Attribute'])) {
return 'event';
}
if (!isset($data['Event'])) {
return 'attribute';
}
if (isset($data['RelatedEvent']) || isset($data['Orgc']) || isset($data['Org'])) {
return 'event';
}
if (!empty($data['Attribute'])) {
return 'attribute';
}
}
}

View File

@ -0,0 +1,421 @@
<?php
class CyclicGraphException extends Exception {}
class GraphUtil
{
public function __construct($graphData)
{
$this->graph = $graphData;
$this->numberNodes = count($this->graph);
$this->edgeList = $this->_buildEdgeList($graphData);
$this->properties = [];
}
private function _buildEdgeList($graphData): array
{
$list = [];
foreach ($graphData as $node) {
$list[(int)$node['id']] = [];
foreach (($node['outputs'] ?? []) as $output_id => $outputs) {
foreach ($outputs as $connections) {
foreach ($connections as $connection) {
$list[$node['id']][] = (int)$connection['node'];
}
}
}
}
return $list;
}
private function _DFSUtil($node_id, &$color): bool
{
$color[$node_id] = 'GRAY';
foreach ($this->edgeList[$node_id] as $i) {
if ($color[$i] == 'GRAY') {
$this->loopNode = $i;
$this->properties[] = [$node_id, $i, __('Cycle')];
return true;
}
if ($color[$i] == 'WHITE' && $this->_DFSUtil($i, $color)) {
if (!is_null($this->loopNode)) {
$this->properties[] = [$node_id, $i, __('Cycle')];
if ($this->loopNode == $node_id) {
$this->loopNode = null;
}
}
return true;
}
}
$color[$node_id] = 'BLACK';
return false;
}
/**
* isCyclic Return is the graph is cyclic, so if it contains a cycle.
*
* A directed graph G is acyclic if and only if a depth-first search of G yields no back edges.
* Introduction to Algorithms, third edition By Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein
*
* @return array
*/
public function isCyclic(): array
{
$this->properties = [];
$color = [];
foreach (array_keys($this->edgeList) as $node_id) {
$color[$node_id] = 'WHITE';
}
$this->loopNode = null;
foreach (array_keys($this->edgeList) as $node_id) {
if ($color[$node_id] == 'WHITE') {
if ($this->_DFSUtil($node_id, $color)) {
return [true, $this->properties];
}
}
}
return [false, []];
}
public function hasMultipleOutputConnection(): array
{
$edges = [];
foreach ($this->graph as $node) {
foreach (($node['outputs'] ?? []) as $output_id => $outputs) {
foreach ($outputs as $connections) {
if (count($connections) > 1 && empty($node['data']['multiple_output_connection'])) {
$edges[$node['id']] = array_map(function ($connection) {
return intval($connection['node']);
}, $connections);
}
}
}
}
return [!empty($edges), $edges];
}
}
class GraphWalker
{
private $graph;
private $WorkflowModel;
private $startNodeID;
private $for_path;
private $cursor;
const PATH_TYPE_BLOCKING = 'blocking';
const PATH_TYPE_NON_BLOCKING = 'non-blocking';
const PATH_TYPE_INCLUDE_LOGIC = 'include-logic';
const ALLOWED_PATH_TYPES = [GraphWalker::PATH_TYPE_BLOCKING, GraphWalker::PATH_TYPE_NON_BLOCKING, GraphWalker::PATH_TYPE_INCLUDE_LOGIC];
public function __construct(array $graphData, $WorkflowModel, $startNodeID, $for_path=null)
{
$this->graph = $graphData;
$this->WorkflowModel = $WorkflowModel;
$this->startNodeID = $startNodeID;
$this->for_path = $for_path;
$this->triggersByNodeID = [];
if (empty($this->graph[$startNodeID])) {
throw new Exception(__('Could not find start node %s', $startNodeID));
}
$this->cursor = $startNodeID;
}
private function getModuleClass($node)
{
$moduleClass = $this->loaded_classes[$node['data']['module_type']][$node['data']['id']] ?? null;
return $moduleClass;
}
private function _getPathType($node_id, $path_type)
{
$node = $this->graph[$node_id];
if ($node['data']['module_type'] == 'logic' && $node['data']['id'] == 'concurrent-task') {
return self::PATH_TYPE_NON_BLOCKING;
}
return $path_type;
}
private function _evaluateOutputs($node, WorkflowRoamingData $roamingData, $shouldExecuteLogicNode=true)
{
$allowed_outputs = ($node['outputs'] ?? []);
if ($shouldExecuteLogicNode && $node['data']['module_type'] == 'logic') {
$allowed_outputs = $this->_executeModuleLogic($node, $roamingData);
}
return $allowed_outputs;
}
/**
* _executeModuleLogic function
*
* @param array $node
* @return array
*/
private function _executeModuleLogic(array $node, WorkflowRoamingData $roamingData): array
{
$outputs = ($node['outputs'] ?? []);
if ($node['data']['id'] == 'if') {
$useFirstOutput = $this->_evaluateIFCondition($node, $roamingData);
return $useFirstOutput ? ['output_1' => $outputs['output_1']] : ['output_2' => $outputs['output_2']];
} else if ($node['data']['id'] == 'concurrent-task') {
$this->_evaluateConcurrentTask($node, $roamingData, $outputs['output_1']);
return ['output_1' => []];
} else {
$useFirstOutput = $this->_evaluateCustomLogicCondition($node, $roamingData);
return $useFirstOutput ? ['output_1' => $outputs['output_1']] : ['output_2' => $outputs['output_2']];
}
return $outputs;
}
private function _evaluateIFCondition($node, WorkflowRoamingData $roamingData): bool
{
$result = $this->WorkflowModel->executeNode($node, $roamingData);
return $result;
}
private function _evaluateCustomLogicCondition($node, WorkflowRoamingData $roamingData): bool
{
$result = $this->WorkflowModel->executeNode($node, $roamingData);
return $result;
}
private function _evaluateConcurrentTask($concurrent_node, WorkflowRoamingData $roamingData, array $connections)
{
foreach ($connections['connections'] as $connection) {
$node_id_to_exec = (int)$connection['node'];
$data = $roamingData->getData();
$data['__node_id_to_exec'] = $node_id_to_exec;
$data = $roamingData->setData($data);
$this->WorkflowModel->executeNode($concurrent_node, $roamingData);
}
}
public function _walk($node_id, $path_type=null, array $path_list=[], WorkflowRoamingData $roamingData)
{
$this->cursor = $node_id;
$node = $this->graph[$node_id];
$shouldExecuteLogicNode = $path_type != self::PATH_TYPE_INCLUDE_LOGIC;
if (!$shouldExecuteLogicNode) {
yield ['node' => $node, 'path_type' => $path_type, 'path_list' => $path_list];
} else if ($node['data']['module_type'] != 'trigger' && $node['data']['module_type'] != 'logic') { // trigger and logic nodes should not be returned as they are "control" nodes
yield ['node' => $node, 'path_type' => $path_type, 'path_list' => $path_list];
}
$allowedOutputs = $this->_evaluateOutputs($node, $roamingData, $shouldExecuteLogicNode);
foreach ($allowedOutputs as $output_id => $outputs) {
if ($shouldExecuteLogicNode) {
$path_type = $this->_getPathType($node_id, $path_type);
}
if (is_null($this->for_path) || $path_type == $this->for_path) {
foreach ($outputs as $connections) {
foreach ($connections as $connection_id => $connection) {
$next_node_id = (int)$connection['node'];
$current_path = $this->__genPathList($node_id, $output_id, $connection_id, $next_node_id);
if (in_array($current_path, $path_list)) { // avoid loops
continue;
}
$next_path_list = $path_list;
$next_path_list[] = $current_path;
yield from $this->_walk($next_node_id, $path_type, $next_path_list, $roamingData);
}
}
}
}
}
public function walk(WorkflowRoamingData $roamingData)
{
return $this->_walk($this->cursor, $this->for_path, [], $roamingData);
}
private function __genPathList($source_id, $output_id, $connection_id, $next_node_id)
{
return sprintf('%s:%s:%s:%s', $source_id, $output_id, $connection_id, $next_node_id);
}
public static function parsePathList($pathList): array
{
return array_map(function($path) {
$split = explode(':', $path);
return [
'source_id' => $split[0],
'output_id' => $split[1],
'connection_id' => $split[2],
'next_node_id' => $split[3],
];
}, $pathList);
}
}
class WorkflowRoamingData
{
private $workflow_user;
private $data;
private $workflow;
private $current_node;
public function __construct(array $workflow_user, array $data, array $workflow, int $current_node)
{
$this->workflow_user = $workflow_user;
$this->data = $data;
$this->workflow = $workflow;
$this->current_node = $current_node;
}
public function getUser(): array
{
return $this->workflow_user;
}
public function getData(): array
{
return $this->data;
}
public function getWorkflow(): array
{
return $this->workflow;
}
public function getCurrentNode(): int
{
return $this->current_node;
}
public function setData(array $data)
{
$this->data = $data;
}
public function setCurrentNode(int $current_node)
{
$this->current_node = $current_node;
}
}
class WorkflowGraphTool
{
/**
* extractTriggerFromWorkflow Return the trigger id (or full module) that are specified in the workflow
*
* @param array $workflow
* @param bool $fullNode
* @return int|array|null
*/
public static function extractTriggerFromWorkflow(array $graphData, bool $fullNode = false)
{
$triggers = self::extractTriggersFromWorkflow($graphData, $fullNode);
if (empty($triggers)) {
return null;
}
$node = $triggers[0];
return $node;
}
/**
* extractTriggersFromWorkflow Return the list of triggers id (or full module) that are specified in the workflow
*
* @param array $workflow
* @param bool $fullNode
* @return array
*/
public static function extractTriggersFromWorkflow(array $graphData, bool $fullNode = false): array
{
$triggers = [];
foreach ($graphData as $node) {
if ($node['data']['module_type'] == 'trigger') {
if (!empty($fullNode)) {
$triggers[] = $node;
} else {
$triggers[] = $node['data']['id'];
}
}
}
return $triggers;
}
/**
* extractConcurrentTasksFromWorkflow Return the list of concurrent-tasks's id (or full module) that are included in the workflow
*
* @param array $workflow
* @param bool $fullNode
* @return array
*/
public static function extractConcurrentTasksFromWorkflow(array $graphData, bool $fullNode = false): array
{
$nodes = [];
foreach ($graphData as $node) {
if ($node['data']['module_type'] == 'logic' && $node['data']['id'] == 'concurrent-task') {
if (!empty($fullNode)) {
$nodes[] = $node;
} else {
$nodes[] = $node['data']['id'];
}
}
}
return $nodes;
}
/**
* isAcyclic Return if the graph contains a cycle
*
* @param array $graphData
* @param array $cycles Get a list of cycle
* @return boolean
*/
public static function isAcyclic(array $graphData, array &$cycles=[]): bool
{
$graphUtil = new GraphUtil($graphData);
$result = $graphUtil->isCyclic();
$isCyclic = $result[0];
$cycles = $result[1];
return !$isCyclic;
}
/**
* hasMultipleOutputConnection Return if the graph has multiple connection from a node output
*
* @param array $graphData
* @param array $edges Get a list of edges from the same output
* @return boolean
*/
public static function hasMultipleOutputConnection(array $graphData, array &$edges=[]): bool
{
$graphUtil = new GraphUtil($graphData);
$result = $graphUtil->hasMultipleOutputConnection();
$hasMultipleOutputConnection = $result[0];
$edges = $result[1];
return $hasMultipleOutputConnection;
}
/**
* Undocumented getNodeIdForTrigger
*
* @param array $graphData
* @param string $trigger_id
* @return integer Return the ID of the node for the provided trigger and -1 if no nodes with this id was found.
*/
public static function getNodeIdForTrigger(array $graphData, $trigger_id): int
{
$trigger_node = WorkflowGraphTool::extractTriggerFromWorkflow($graphData, true);
if ($trigger_node['data']['id'] == $trigger_id) {
return $trigger_node['id'];
}
return -1;
}
public static function getRoamingData(array $user=[], array $data=[], array $workflow=[], int $node_id=-1)
{
return new WorkflowRoamingData($user, $data, $workflow, $node_id);
}
public static function getWalkerIterator(array $graphData, $WorkflowModel, $startNodeID, $path_type=null, WorkflowRoamingData $roamingData)
{
if (!in_array($path_type, GraphWalker::ALLOWED_PATH_TYPES)) {
return [];
}
$graphWalker = new GraphWalker($graphData, $WorkflowModel, $startNodeID, $path_type);
return $graphWalker->walk($roamingData);
}
}

View File

@ -0,0 +1,23 @@
<?php
include_once APP . 'Model/WorkflowModules/WorkflowBaseModule.php';
class Module_blueprint_action_module extends WorkflowBaseActionModule
{
public $blocking = false;
public $disabled = true;
public $id = 'blueprint-action-module';
public $name = 'Blueprint action module';
public $description = 'Lorem ipsum dolor, sit amet consectetur adipisicing elit.';
public $icon = 'shapes';
public $inputs = 1;
public $outputs = 1;
public $params = [];
public function exec(array $node, WorkflowRoamingData $roamingData, array &$errors = []): bool
{
parent::exec($node, $roamingData, $errors);
// If $this->blocking == true, returning `false` will stop the execution.
$errors[] = __('Execution stopped');
return false;
}
}

View File

@ -0,0 +1,23 @@
<?php
include_once APP . 'Model/WorkflowModules/WorkflowBaseModule.php';
class Module_blueprint_logic_module extends WorkflowBaseLogicModule
{
public $disabled = true;
public $id = 'blueprint-logic-module';
public $name = 'Blueprint logic module';
public $description = 'Lorem ipsum dolor, sit amet consectetur adipisicing elit.';
public $icon = 'shapes';
public $inputs = 1;
public $outputs = 2;
public $params = [];
public function exec(array $node, WorkflowRoamingData $roamingData, array &$errors = []): bool
{
parent::exec($node, $roamingData, $errors);
$params = $this->getParamsWithValues($node);
$data = $roamingData->getData();
// Returning true will make the execution flow take the first output of this module. Otherwise, the second output will be used.
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:10\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Czech\n"
"MIME-Version: 1.0\n"
@ -1476,13 +1476,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1492,7 +1492,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2363,100 +2363,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4579,7 +4579,7 @@ msgid "Base64 encoded certificate"
msgstr "Base64 kódovaný certifikát"
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5985,7 +5985,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8037,7 +8037,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:10\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Danish\n"
"MIME-Version: 1.0\n"
@ -1465,13 +1465,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1481,7 +1481,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2348,100 +2348,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4564,7 +4564,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5970,7 +5970,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8020,7 +8020,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:10\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@ -17,38 +17,38 @@ msgstr ""
#: Console/Command/APIShell.php:15
msgid "The following API documentation is derived directly from [MISP RestResponseComponent's source code](app/Controller/Component/RestResponseComponent.php)"
msgstr ""
msgstr "Die folgende API-Dokumentation wird direkt von [MISP RestResponseComponents source code](app/Controller/Component/RestResponseComponent.php) abgeleitet"
#: Console/Command/APIShell.php:46
msgid "Successfully saved API documentation"
msgstr ""
msgstr "API-Dokumentation erfolgreich gespeichert"
#: Console/Command/APIShell.php:48
msgid "Could not save API documentation"
msgstr ""
msgstr "API Dokumentation konnte nicht gespeichert werden"
#: Console/Command/APIShell.php:59
msgid "URL Parameters"
msgstr ""
msgstr "URL Parameter"
#: Console/Command/APIShell.php:63
#: View/DecayingModel/index.ctp:84
#: View/DecayingModel/view.ctp:40
msgid "Parameters"
msgstr ""
msgstr "Parameter"
#: Console/Command/APIShell.php:65
#: View/Elements/templateElements/templateRowAttribute.ctp:59
msgid "Mandatory"
msgstr ""
msgstr "Verpflichtend"
#: Console/Command/APIShell.php:70
msgid "Optional"
msgstr ""
msgstr "Optional"
#: Console/Command/APIShell.php:79
msgid "API Documentation"
msgstr ""
msgstr "API Dokumentation"
#: Console/Command/APIShell.php:88
#: View/Allowedlists/index.ctp:19
@ -191,31 +191,31 @@ msgstr "Aktualisieren Sie die JSON-Definitionen von MISP."
#: Console/Command/AdminShell.php:20
msgid "Set setting in PHP config file."
msgstr ""
msgstr "Einstellung in der PHP-Konfigurationsdatei festlegen."
#: Console/Command/AdminShell.php:23
msgid "Setting name"
msgstr ""
msgstr "Name der Einstellung"
#: Console/Command/AdminShell.php:24
msgid "Setting value"
msgstr ""
msgstr "Einstellungswert"
#: Console/Command/AdminShell.php:43
msgid "Set if MISP instance is live and accessible for users."
msgstr ""
msgstr "Legen Sie fest, ob MISP Instanz live und für Benutzer zugänglich ist."
#: Console/Command/AdminShell.php:46
msgid "Set Live state"
msgstr ""
msgstr "Live-Status festlegen"
#: Console/Command/AdminShell.php:51
msgid "Reencrypt encrypted values in database (authkeys and sensitive system settings)."
msgstr ""
msgstr "Verschlüssele verschlüsselte Werte in der Datenbank (authkeys und sensitive Systemeinstellungen)."
#: Console/Command/AdminShell.php:54
msgid "Old key. If not provided, current key will be used."
msgstr ""
msgstr "Alter Schlüssel. Wenn nicht angegeben wird, wird der aktuelle Schlüssel verwendet."
#: Console/Command/AdminShell.php:55
msgid "New key. If not provided, new key will be generated."
@ -1465,13 +1465,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1481,7 +1481,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2348,100 +2348,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4564,7 +4564,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5970,7 +5970,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8020,7 +8020,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:10\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
@ -21,11 +21,11 @@ msgstr ""
#: Console/Command/APIShell.php:46
msgid "Successfully saved API documentation"
msgstr ""
msgstr "Documentation de l'API enregistrée avec succès"
#: Console/Command/APIShell.php:48
msgid "Could not save API documentation"
msgstr ""
msgstr "Impossible d'enregistrer la documentation de l'API"
#: Console/Command/APIShell.php:59
msgid "URL Parameters"
@ -48,7 +48,7 @@ msgstr "Facultatif"
#: Console/Command/APIShell.php:79
msgid "API Documentation"
msgstr ""
msgstr "Documentation pour API"
#: Console/Command/APIShell.php:88
#: View/Allowedlists/index.ctp:19
@ -195,11 +195,11 @@ msgstr ""
#: Console/Command/AdminShell.php:23
msgid "Setting name"
msgstr ""
msgstr "Nom du paramètre"
#: Console/Command/AdminShell.php:24
msgid "Setting value"
msgstr ""
msgstr "Valeur de la configuration"
#: Console/Command/AdminShell.php:43
msgid "Set if MISP instance is live and accessible for users."
@ -1468,13 +1468,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1484,7 +1484,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2351,100 +2351,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr "JSON invalide"
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4567,7 +4567,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5973,7 +5973,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8023,7 +8023,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:08\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Italian\n"
"MIME-Version: 1.0\n"
@ -1466,13 +1466,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1482,7 +1482,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2349,100 +2349,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4565,7 +4565,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5971,7 +5971,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8021,7 +8021,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
@ -1460,13 +1460,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1476,7 +1476,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2341,100 +2341,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4557,7 +4557,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5963,7 +5963,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8012,7 +8012,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Korean\n"
"MIME-Version: 1.0\n"
@ -21,34 +21,34 @@ msgstr ""
#: Console/Command/APIShell.php:46
msgid "Successfully saved API documentation"
msgstr ""
msgstr "API 설명서를 저장함"
#: Console/Command/APIShell.php:48
msgid "Could not save API documentation"
msgstr ""
msgstr "API 설명서를 저장할 수 없음"
#: Console/Command/APIShell.php:59
msgid "URL Parameters"
msgstr ""
msgstr "URL 매개변수"
#: Console/Command/APIShell.php:63
#: View/DecayingModel/index.ctp:84
#: View/DecayingModel/view.ctp:40
msgid "Parameters"
msgstr ""
msgstr "매개변수"
#: Console/Command/APIShell.php:65
#: View/Elements/templateElements/templateRowAttribute.ctp:59
msgid "Mandatory"
msgstr ""
msgstr "필수 항목"
#: Console/Command/APIShell.php:70
msgid "Optional"
msgstr ""
msgstr "옵션"
#: Console/Command/APIShell.php:79
msgid "API Documentation"
msgstr ""
msgstr "API 설명서"
#: Console/Command/APIShell.php:88
#: View/Allowedlists/index.ctp:19
@ -104,7 +104,7 @@ msgstr ""
#: View/Warninglists/index.ctp:56
#: View/Warninglists/view.ctp:6
msgid "Name"
msgstr ""
msgstr "이름"
#: Console/Command/APIShell.php:88
#: View/Attributes/index.ctp:42
@ -135,7 +135,7 @@ msgstr ""
#: View/Warninglists/index.ctp:80
#: View/Warninglists/view.ctp:10
msgid "Type"
msgstr ""
msgstr "유형"
#: Console/Command/APIShell.php:88
#: View/Cerebrates/index.ctp:25
@ -183,7 +183,7 @@ msgstr ""
#: View/Warninglists/index.ctp:67
#: View/Warninglists/view.ctp:7
msgid "Description"
msgstr ""
msgstr "설명"
#: Console/Command/AdminShell.php:17
msgid "Update the JSON definitions of MISP."
@ -336,7 +336,7 @@ msgstr ""
#: Controller/UsersController.php:1357;2402
#: Model/Dashboard.php:129
msgid "Invalid user."
msgstr ""
msgstr "올바르지 않은 사용자."
#: Console/Command/AdminShell.php:668
msgid "User has to be a site admin."
@ -345,7 +345,8 @@ msgstr ""
#: Console/Command/AdminShell.php:692
msgid "\n"
"Error: %s\n"
msgstr ""
msgstr "\n"
"오류: %s\n"
#: Console/Command/AdminShell.php:694
msgid "%s events purged.\n"
@ -391,11 +392,11 @@ msgstr ""
#: Console/Command/DevShell.php:45
msgid "Something went wrong."
msgstr ""
msgstr "알 수 없는 오류가 발생했습니다."
#: Console/Command/EventShell.php:23
msgid "Import event from file into MISP."
msgstr ""
msgstr "파일에서 MISP로 이벤트를 가져옵니다."
#: Console/Command/EventShell.php:26
msgid "User ID that will owner of uploaded event."
@ -407,7 +408,7 @@ msgstr ""
#: Console/Command/EventShell.php:36
msgid "Generate event notification email in EML format."
msgstr ""
msgstr "EML 형식으로 이벤트 알림 이메일을 생성합니다."
#: Console/Command/EventShell.php:39
#: Controller/EventsController.php:1126
@ -419,19 +420,19 @@ msgstr ""
#: View/ShadowAttributes/index.ctp:40
#: View/Sightings/ajax/list_sightings.ctp:13
msgid "Event ID"
msgstr ""
msgstr "이벤트 ID"
#: Console/Command/EventShell.php:40
msgid "User ID"
msgstr ""
msgstr "사용자 ID"
#: Console/Command/EventShell.php:45
msgid "Show duplicate tags"
msgstr ""
msgstr "중복된 태그 표시"
#: Console/Command/EventShell.php:48
msgid "Merge tags"
msgstr ""
msgstr "태그 병합"
#: Console/Command/EventShell.php:51
msgid "Source tag ID or name. Source tag will be deleted."
@ -443,7 +444,7 @@ msgstr ""
#: Console/Command/EventShell.php:106
msgid "%s attribute or event tags changed"
msgstr ""
msgstr "%s 속성 또는 이벤트 태그가 변경되었습니다."
#: Console/Command/EventShell.php:125
#: Controller/AttributesController.php:112;1186;1258;1389
@ -457,7 +458,7 @@ msgstr "유효하지 않은 이벤트"
#: Console/Command/EventShell.php:593
msgid "Recovering event %s"
msgstr ""
msgstr "이벤트 %s 가 복구 중입니다."
#: Console/Command/EventShell.php:598
#: Controller/EventsController.php:5758
@ -471,7 +472,7 @@ msgstr ""
#: Console/Command/EventShell.php:656
#: Model/Job.php:156
msgid "Job done."
msgstr ""
msgstr "작업 완료."
#: Console/Command/LogShell.php:16
msgid "Show statistics from audit logs."
@ -487,27 +488,27 @@ msgstr ""
#: Console/Command/LogShell.php:25
msgid "Path to output file"
msgstr ""
msgstr "출력 파일 경로"
#: Console/Command/LogShell.php:106;130
msgid "Count:"
msgstr ""
msgstr "수:"
#: Console/Command/LogShell.php:107;131
msgid "First:"
msgstr ""
msgstr "첫번째:"
#: Console/Command/LogShell.php:108;132
msgid "Last:"
msgstr ""
msgstr "마지막:"
#: Console/Command/LogShell.php:111;135
msgid "Data size:"
msgstr ""
msgstr "데이터 크기:"
#: Console/Command/LogShell.php:112;136
msgid "Index size:"
msgstr ""
msgstr "색인 크기:"
#: Console/Command/LogShell.php:113;137
msgid "Reclaimable size:"
@ -515,15 +516,15 @@ msgstr ""
#: Console/Command/LogShell.php:146
msgid "Compressed items:"
msgstr ""
msgstr "압축된 항목:"
#: Console/Command/LogShell.php:147
msgid "Uncompressed size:"
msgstr ""
msgstr "압축해제된 크기:"
#: Console/Command/LogShell.php:148
msgid "Compressed size:"
msgstr ""
msgstr "압축된 크기:"
#: Console/Command/PasswordShell.php:47
msgid "override password change"
@ -573,7 +574,7 @@ msgstr ""
#: Console/Command/StatisticsShell.php:250
msgid "%s: %s %s%s"
msgstr ""
msgstr "%s: %s %s%s"
#: Console/Command/TrainingShell.php:682
msgid "verbose mode"
@ -605,7 +606,7 @@ msgstr ""
#: Console/Command/UserShell.php:34
msgid "Immediately block user."
msgstr ""
msgstr "사용자 즉시 차단."
#: Console/Command/UserShell.php:37;45;53;65;73
msgid "User ID or e-mail address."
@ -613,7 +614,7 @@ msgstr ""
#: Console/Command/UserShell.php:42
msgid "Unblock blocked user."
msgstr ""
msgstr "차단된 사용자 차단해제."
#: Console/Command/UserShell.php:50
msgid "Change user password."
@ -977,7 +978,7 @@ msgstr[0] ""
#: View/TagCollections/import.ctp:20
#: View/Users/admin_filter_user_index.ctp:62
msgid "Add"
msgstr ""
msgstr "추가"
#: Controller/AuditLogsController.php:76;118
#: View/DecayingModel/decaying_tool.ctp:137
@ -1030,11 +1031,11 @@ msgstr ""
#: View/Users/admin_index.ctp:269
#: View/Warninglists/index.ctp:165
msgid "Delete"
msgstr ""
msgstr "삭제"
#: Controller/AuditLogsController.php:79;121
msgid "Undelete"
msgstr ""
msgstr "삭제 취소"
#: Controller/AuditLogsController.php:80;81;122
#: Controller/EventsController.php:1127
@ -1042,7 +1043,7 @@ msgstr ""
#: View/Feeds/index.ctp:192
#: View/Taxonomies/ajax/taxonomy_tags.ctp:52
msgid "Tag"
msgstr ""
msgstr "태그"
#: Controller/AuditLogsController.php:82;83;123
#: View/Elements/ajaxAttributeTags.ctp:29
@ -1076,7 +1077,7 @@ msgstr ""
#: Controller/AuditLogsController.php:132
#: View/AuditLogs/admin_index.ctp:2
msgid "Audit logs"
msgstr ""
msgstr "감사 로그"
#: Controller/AuditLogsController.php:185
#: View/AuditLogs/event_index.ctp:2
@ -1153,15 +1154,15 @@ msgstr ""
#: View/Events/export.ctp:115;144
#: View/Galaxies/export.ctp:45
msgid "Download"
msgstr ""
msgstr "다운로드"
#: Controller/CerebratesController.php:301
msgid "Sharing Group downloaded."
msgstr ""
msgstr "공유 그룹이 다운로드되었습니다."
#: Controller/CerebratesController.php:309
msgid "Download sharing group information"
msgstr ""
msgstr "공유 그룹 정보 다운로드"
#: Controller/CerebratesController.php:310
msgid "Are you sure you want to download and add / update the remote sharing group?"
@ -1169,7 +1170,7 @@ msgstr ""
#: Controller/CommunitiesController.php:150
msgid "Request sent."
msgstr ""
msgstr "요청이 전송되었습니다."
#: Controller/CommunitiesController.php:150
msgid "Something went wrong and the request could not be sent."
@ -1460,13 +1461,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1476,7 +1477,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -1752,7 +1753,7 @@ msgstr ""
#: Controller/EventsController.php:2256
msgid "No file was uploaded."
msgstr ""
msgstr "업로드된 파일이 없습니다."
#: Controller/EventsController.php:2265
msgid "You may only upload MISP XML or MISP JSON files."
@ -1884,11 +1885,11 @@ msgstr "잘못된 이벤트 또는 권한이 없습니다."
#: Controller/EventsController.php:3501
msgid "Nothing to add."
msgstr ""
msgstr "추가할 사항이 없습니다."
#: Controller/EventsController.php:3517
msgid "Tag not found."
msgstr ""
msgstr "태그를 찾을 수 없습니다."
#: Controller/EventsController.php:3528
msgid "Tag is already attached to this event."
@ -1901,7 +1902,7 @@ msgstr ""
#: Controller/EventsController.php:3546
#: Controller/TagsController.php:843
msgid "Invalid Tag. This tag can only be set as a local tag."
msgstr ""
msgstr "잘못된 태그입니다. 이 태그는 로컬 태그로만 설정할 수 있습니다."
#: Controller/EventsController.php:3587
msgid ", but %s could not be added: %s"
@ -1917,7 +1918,7 @@ msgstr ""
#: Controller/EventsController.php:4132
msgid "Freetext Import"
msgstr ""
msgstr "Freetext 가져오기"
#: Controller/EventsController.php:4138
msgid "Populate using a Template"
@ -1925,11 +1926,11 @@ msgstr ""
#: Controller/EventsController.php:4144
msgid "OpenIOC Import"
msgstr ""
msgstr "OpenIOC 가져오기"
#: Controller/EventsController.php:4149
msgid "ThreatConnect Import"
msgstr ""
msgstr "ThreatConnect 가져오기"
#: Controller/EventsController.php:4154
msgid "(Experimental) Forensic analysis - Mactime"
@ -2043,11 +2044,11 @@ msgstr ""
#: Controller/EventsController.php:5489
msgid "background job"
msgstr ""
msgstr "백그라운드 작업"
#: Controller/EventsController.php:5491
msgid "external tool"
msgstr ""
msgstr "외부 도구"
#: Controller/EventsController.php:5497
msgid "<b>Warning</b>: This event view is outdated. Please reload page to see latest changes."
@ -2063,7 +2064,7 @@ msgstr ""
#: Controller/EventsController.php:5716
msgid "%s event(s) deleted."
msgstr ""
msgstr "%s 이벤트가 삭제되었습니다."
#: Controller/EventsController.php:5756
msgid "Recovery simulation complete. Event #%s can be recovered using %s log entries."
@ -2143,7 +2144,7 @@ msgstr "피드 가져 오기가 완료되었습니다."
#: Controller/FeedsController.php:607
msgid "No feed enabled."
msgstr ""
msgstr "활성화된 피드가 없습니다."
#: Controller/FeedsController.php:631;650
#: Controller/ServersController.php:132
@ -2216,7 +2217,7 @@ msgstr "잘못 된 피드 리스트를 받았습니다."
#: Controller/GalaxiesController.php:73
msgid "Galaxies updated."
msgstr ""
msgstr "Galaxies가 업데이트 되었습니다."
#: Controller/GalaxiesController.php:88
msgid "Default galaxy clusters dropped."
@ -2224,7 +2225,7 @@ msgstr ""
#: Controller/GalaxiesController.php:146
msgid "Galaxy deleted"
msgstr ""
msgstr "Galaxy가 삭제되었습니다."
#: Controller/GalaxiesController.php:154
msgid "Could not delete Galaxy."
@ -2268,7 +2269,7 @@ msgstr ""
#: Controller/GalaxiesController.php:327
msgid "All sharing groups"
msgstr ""
msgstr "모든 공유 그룹"
#: Controller/GalaxiesController.php:356
msgid "All clusters"
@ -2293,7 +2294,7 @@ msgstr ""
#: Controller/GalaxyClusterBlocklistsController.php:75;97
msgid "Invalid cluster IDs."
msgstr ""
msgstr "잘못된 클러스터 ID 입니다."
#: Controller/GalaxyClusterBlocklistsController.php:86
msgid "Failed to delete GalaxyCluster from GalaxyClusterBlocklist. Error: "
@ -2341,100 +2342,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
msgstr "잘못된 JSON 형식입니다."
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4557,7 +4558,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5963,7 +5964,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8012,7 +8013,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Norwegian\n"
"MIME-Version: 1.0\n"
@ -1465,13 +1465,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1481,7 +1481,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2348,100 +2348,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4564,7 +4564,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5970,7 +5970,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8020,7 +8020,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Polish\n"
"MIME-Version: 1.0\n"
@ -1476,13 +1476,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1492,7 +1492,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2363,100 +2363,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4579,7 +4579,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5985,7 +5985,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8037,7 +8037,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Portuguese, Brazilian\n"
"MIME-Version: 1.0\n"
@ -1466,13 +1466,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1482,7 +1482,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2349,100 +2349,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4565,7 +4565,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5971,7 +5971,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8021,7 +8021,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: misp\n"
"PO-Revision-Date: 2022-01-05 08:09\n"
"PO-Revision-Date: 2022-07-21 15:58\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
@ -1467,13 +1467,13 @@ msgid "Event Report %s %s deleted"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "hard"
msgstr ""
#: Controller/EventReportsController.php:133;136
#: Controller/GalaxyClustersController.php:721;731
#: Controller/GalaxyClustersController.php:722;732
#: View/Objects/group_attributes_into_object.ctp:129
msgid "soft"
msgstr ""
@ -1483,7 +1483,7 @@ msgid "Event Report %s could not be %s deleted.%sReasons: %s"
msgstr ""
#: Controller/EventReportsController.php:141;165;212;242;262;298
#: Controller/GalaxyClustersController.php:745
#: Controller/GalaxyClustersController.php:746
#: Controller/GalaxyElementsController.php:83
#: Controller/TaxonomiesController.php:531
#: Controller/WarninglistsController.php:434
@ -2350,100 +2350,100 @@ msgstr ""
msgid "Galaxy cluster relationship could not be deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:203
#: Controller/GalaxyClustersController.php:204
msgid "This cluster is not published. Users will not be able to use it"
msgstr ""
#: Controller/GalaxyClustersController.php:220;224
#: Controller/GalaxyClustersController.php:221;225
msgid "Invalid galaxy"
msgstr ""
#: Controller/GalaxyClustersController.php:283;284;391;392
#: Controller/GalaxyClustersController.php:284;285;392;393
msgid "Invalid JSON"
msgstr ""
#: Controller/GalaxyClustersController.php:314;427
#: Controller/GalaxyClustersController.php:315;428
msgid "Galaxy cluster saved"
msgstr ""
#: Controller/GalaxyClustersController.php:446
#: Controller/GalaxyClustersController.php:447
#: View/GalaxyClusters/add.ctp:72
msgid "Valid JSON array or comma separated"
msgstr ""
#: Controller/GalaxyClustersController.php:447
#: Controller/GalaxyClustersController.php:448
msgid "Valid JSON array composed from Object of the form {key: keyname, value: actualValue}"
msgstr ""
#: Controller/GalaxyClustersController.php:470
#: Controller/GalaxyClustersController.php:471
msgid "You can't publish a galaxy cluster that is already published"
msgstr ""
#: Controller/GalaxyClustersController.php:473
#: Controller/GalaxyClustersController.php:474
msgid "Default galaxy cluster cannot be published"
msgstr ""
#: Controller/GalaxyClustersController.php:479
#: Controller/GalaxyClustersController.php:480
msgid "Publish job queued. Job ID: %s"
msgstr ""
#: Controller/GalaxyClustersController.php:486
#: Controller/GalaxyClustersController.php:487
msgid "Could not publish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:493
#: Controller/GalaxyClustersController.php:494
msgid "Galaxy cluster published"
msgstr ""
#: Controller/GalaxyClustersController.php:516
#: Controller/GalaxyClustersController.php:517
msgid "You can't unpublish a galaxy cluster that is not published"
msgstr ""
#: Controller/GalaxyClustersController.php:519
#: Controller/GalaxyClustersController.php:520
msgid "Default galaxy cluster cannot be unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:525
#: Controller/GalaxyClustersController.php:526
msgid "Could not unpublish galaxy cluster"
msgstr ""
#: Controller/GalaxyClustersController.php:532
#: Controller/GalaxyClustersController.php:533
msgid "Galaxy cluster unpublished"
msgstr ""
#: Controller/GalaxyClustersController.php:719
#: Controller/GalaxyClustersController.php:720
msgid "Galaxy cluster successfuly %s deleted%s."
msgstr ""
#: Controller/GalaxyClustersController.php:722
#: Controller/GalaxyClustersController.php:723
msgid " and added to the block list"
msgstr ""
#: Controller/GalaxyClustersController.php:731
#: Controller/GalaxyClustersController.php:732
msgid "Galaxy cluster could not be %s deleted."
msgstr ""
#: Controller/GalaxyClustersController.php:757
#: Controller/GalaxyClustersController.php:758
msgid "Galaxy cluster successfuly restored."
msgstr ""
#: Controller/GalaxyClustersController.php:765
#: Controller/GalaxyClustersController.php:766
msgid "Galaxy cluster could not be %s restored."
msgstr ""
#: Controller/GalaxyClustersController.php:774
#: Controller/GalaxyClustersController.php:775
msgid "This function can only be reached via POST."
msgstr ""
#: Controller/GalaxyClustersController.php:917
#: Controller/GalaxyClustersController.php:918
msgid "Default galaxy cluster cannot be updated"
msgstr ""
#: Controller/GalaxyClustersController.php:920
#: Controller/GalaxyClustersController.php:921
msgid "Galaxy cluster is not a fork"
msgstr ""
#: Controller/GalaxyClustersController.php:951
#: Controller/GalaxyClustersController.php:952
msgid "Cluster updated to the newer version"
msgstr ""
@ -4566,7 +4566,7 @@ msgid "Base64 encoded certificate"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1620
msgid "A tad ID to attach to created events"
msgid "A tag ID to attach to created events"
msgstr ""
#: Controller/Component/RestResponseComponent.php:1633
@ -5972,7 +5972,7 @@ msgid "Event publish is not banned"
msgstr ""
#: Model/Event.php:7584
msgid "Reason: Could not reach redis to chech republish emailing ban status."
msgid "Reason: Could not reach redis to check republish emailing ban status."
msgstr ""
#: Model/Event.php:7597
@ -8022,7 +8022,7 @@ msgid "User is not banned to sent email notification"
msgstr ""
#: Model/User.php:1481
msgid "Reason: Could not reach redis to chech user email notification ban status."
msgid "Reason: Could not reach redis to check user email notification ban status."
msgstr ""
#: Model/User.php:1493

Some files were not shown because too many files have changed in this diff Show More