mirror of https://github.com/MISP/MISP
Merge branch 'develop' into 2.4
commit
1c0df3687a
|
@ -30,10 +30,6 @@ jobs:
|
|||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
# Stop mysql
|
||||
- name: Shutdown Ubuntu MySQL (SUDO)
|
||||
run: sudo service mysql stop
|
||||
|
||||
# Run mariadb
|
||||
- uses: getong/mariadb-action@v1.1
|
||||
with:
|
||||
|
@ -61,21 +57,22 @@ jobs:
|
|||
echo "USER=`id -u -n`" >> $GITHUB_ENV
|
||||
echo "HOST=localhost" >> $GITHUB_ENV
|
||||
|
||||
# Runs a set of commands using the runners shell
|
||||
- name: Install deps
|
||||
- name: Install system deps
|
||||
env:
|
||||
php_version: ${{ matrix.php }}
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
# Repo is missing for unknown reason
|
||||
LC_ALL=C.UTF-8 sudo apt-add-repository ppa:ondrej/php -y
|
||||
if [[ $php_version == "7.2" ]]; then
|
||||
# hotfix due to: https://bugs.php.net/bug.php?id=81640 TODO: remove after libpcre2-8-0:10.36 gets to stable channel
|
||||
sudo apt --fix-broken install
|
||||
fi
|
||||
sudo apt-get -y install curl python3 python3-zmq python3-requests python3-pip python3-nose python3-redis python3-lxml apache2 libapache2-mod-php$php_version
|
||||
sudo pip3 install virtualenv # virtualenv must be instaled from pip and not from ubuntu packages
|
||||
curl -sSL https://install.python-poetry.org | python -
|
||||
sudo apt-get -y update
|
||||
# Repo is missing for unknown reason
|
||||
LC_ALL=C.UTF-8 sudo apt-add-repository ppa:ondrej/php -y
|
||||
if [[ $php_version == "7.2" ]]; then
|
||||
# hotfix due to: https://bugs.php.net/bug.php?id=81640 TODO: remove after libpcre2-8-0:10.36 gets to stable channel
|
||||
sudo apt-get --fix-broken install
|
||||
fi
|
||||
sudo apt-get -y install curl python3 python3-pip python3-virtualenv apache2 libapache2-mod-php$php_version
|
||||
|
||||
# Runs a set of commands using the runners shell
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo chown $USER:www-data $HOME/.composer
|
||||
pushd app
|
||||
sudo -H -u $USER php composer.phar install --no-progress
|
||||
|
@ -149,32 +146,33 @@ jobs:
|
|||
|
||||
- name: Configure MISP
|
||||
run: |
|
||||
sudo -E su $USER -c 'app/Console/cake userInit -q | sudo tee ./key.txt'
|
||||
sudo -u $USER app/Console/cake userInit -q | sudo tee ./key.txt
|
||||
echo "AUTH=`cat key.txt`" >> $GITHUB_ENV
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Session.autoRegenerate" 0'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Session.timeout" 600'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Session.cookieTimeout" 3600'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.host_org_id" 1'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.email" "info@admin.test"'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.disable_emailing" false'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting --force "debug" true'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.CustomAuth_disable_logout" false'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.redis_host" "127.0.0.1"'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.redis_port" 6379'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.redis_database" 13'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.redis_password" ""'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "GnuPG.email" "info@admin.test"'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "GnuPG.homedir" "`pwd`/.gnupg"'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "GnuPG.password" "travistest"'
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Session.autoRegenerate" 0
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Session.timeout" 600
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Session.cookieTimeout" 3600
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.host_org_id" 1
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.email" "info@admin.test"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.disable_emailing" false
|
||||
sudo -u $USER app/Console/cake Admin setSetting --force "debug" true
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.CustomAuth_disable_logout" false
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.redis_host" "127.0.0.1"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.redis_port" 6379
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.redis_database" 13
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.redis_password" ""
|
||||
sudo -u $USER app/Console/cake Admin setSetting "GnuPG.email" "info@admin.test"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "GnuPG.homedir" "`pwd`/.gnupg"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "GnuPG.password" "travistest"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "MISP.download_gpg_from_homedir" 1
|
||||
|
||||
- name: Configure ZMQ
|
||||
run: |
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_host" "127.0.0.1"'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_port" 6379'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_database" 1'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_password" ""'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_enable" 1'
|
||||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" 1'
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_host" "127.0.0.1"
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_port" 6379
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_database" 1
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_redis_password" ""
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_enable" 1
|
||||
sudo -u $USER app/Console/cake Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" 1
|
||||
|
||||
- name: Update Galaxies
|
||||
run: sudo -E su $USER -c 'app/Console/cake Admin updateGalaxies'
|
||||
|
@ -209,16 +207,7 @@ jobs:
|
|||
sudo -E su $USER -c 'app/Console/cake Admin setSetting "MISP.python_bin" "$GITHUB_WORKSPACE/venv/bin/python"'
|
||||
. ./venv/bin/activate
|
||||
export PYTHONPATH=$PYTHONPATH:./app/files/scripts
|
||||
pushd ./app/files/scripts/cti-python-stix2
|
||||
pip install .
|
||||
popd
|
||||
pushd ./app/files/scripts/python-stix
|
||||
pip install .
|
||||
popd
|
||||
pushd PyMISP
|
||||
pip install .[fileobjects,email]
|
||||
popd
|
||||
pip install zmq redis plyara
|
||||
pip install ./PyMISP[fileobjects,email] ./app/files/scripts/python-stix ./app/files/scripts/cti-python-stix2 pyzmq redis plyara
|
||||
deactivate
|
||||
|
||||
- name: Test if apache is working
|
||||
|
@ -242,31 +231,32 @@ jobs:
|
|||
- name: Run PHP tests
|
||||
run: |
|
||||
./app/Vendor/bin/parallel-lint --exclude app/Lib/cakephp/ --exclude app/Vendor/ --exclude app/Lib/random_compat/ -e php,ctp app/
|
||||
./app/Vendor/bin/phpunit app/Test/
|
||||
sudo -u www-data ./app/Vendor/bin/phpunit app/Test/
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
export PATH=$HOME/.local/env:$PATH # enable poetry binary
|
||||
|
||||
pushd tests
|
||||
./curl_tests_GH.sh $AUTH $HOST
|
||||
popd
|
||||
|
||||
sudo chmod -R g+ws `pwd`/app/tmp/logs
|
||||
|
||||
. ./venv/bin/activate
|
||||
pushd PyMISP
|
||||
poetry install -E fileobjects -E openioc -E virustotal -E docs -E pdfexport -E email
|
||||
poetry run python tests/testlive_comprehensive.py
|
||||
poetry add lxml
|
||||
poetry run python ../tests/testlive_security.py -v
|
||||
poetry run python ../tests/testlive_sync.py
|
||||
poetry run python ../tests/testlive_comprehensive_local.py -v
|
||||
poetry run python tests/test_mispevent.py
|
||||
python tests/testlive_comprehensive.py
|
||||
popd
|
||||
python tests/testlive_security.py -v
|
||||
python tests/testlive_sync.py
|
||||
python tests/testlive_comprehensive_local.py -v
|
||||
pushd PyMISP
|
||||
python tests/test_mispevent.py
|
||||
popd
|
||||
cp PyMISP/tests/keys.py PyMISP/examples/events/
|
||||
pushd PyMISP/examples/events/
|
||||
poetry run python ./create_massive_dummy_events.py -l 5 -a 30
|
||||
python ./create_massive_dummy_events.py -l 5 -a 30
|
||||
popd
|
||||
python3 tools/misp-feed/validate.py
|
||||
python tools/misp-feed/validate.py
|
||||
deactivate
|
||||
|
||||
- name: Logs
|
||||
if: ${{ always() }}
|
||||
|
|
|
@ -107,3 +107,8 @@ vagrant/.vagrant/
|
|||
vagrant/*.log
|
||||
/app/Lib/Dashboard/Custom/*
|
||||
!/app/Lib/Dashboard/Custom/empty
|
||||
/app/View/Emails/html/Custom/*
|
||||
!/app/View/Emails/html/Custom/empty
|
||||
/app/View/Emails/text/Custom/*
|
||||
!/app/View/Emails/text/Custom/empty
|
||||
|
||||
|
|
|
@ -187,8 +187,9 @@ class EventShell extends AppShell
|
|||
$this->Job->id = $id;
|
||||
$export_type = $this->args[2];
|
||||
file_put_contents('/tmp/test', $export_type);
|
||||
$typeData = $this->Event->export_types[$export_type];
|
||||
if (!in_array($export_type, array_keys($this->Event->export_types))) {
|
||||
$exportTypes = $this->Event->exportTypes();
|
||||
$typeData = $exportTypes[$export_type];
|
||||
if (!in_array($export_type, array_keys($exportTypes))) {
|
||||
$this->Job->saveField('progress', 100);
|
||||
$timeDelta = (time()-$timeStart);
|
||||
$this->Job->saveField('message', 'Job Failed due to invalid export format. (in '.$timeDelta.'s)');
|
||||
|
@ -385,7 +386,7 @@ class EventShell extends AppShell
|
|||
// the special cache files containing all events
|
||||
$i = 0;
|
||||
foreach ($users as $user) {
|
||||
foreach ($this->Event->export_types as $k => $type) {
|
||||
foreach ($this->Event->exportTypes() as $k => $type) {
|
||||
if ($k == 'stix') continue;
|
||||
$this->Job->cache($k, $user['User']);
|
||||
$i++;
|
||||
|
|
|
@ -0,0 +1,361 @@
|
|||
<?php
|
||||
class Ls22Shell extends AppShell
|
||||
{
|
||||
public $uses = ['Server'];
|
||||
private $__servers = [];
|
||||
|
||||
private function __getInstances($path)
|
||||
{
|
||||
if (empty($path)) {
|
||||
$path = 'instances.csv';
|
||||
}
|
||||
$file = file_get_contents($path);
|
||||
$lines = explode(PHP_EOL, $file);
|
||||
foreach ($lines as $k => $line) {
|
||||
if ($k === 0) {
|
||||
continue;
|
||||
}
|
||||
$fields = explode(',', $line);
|
||||
if (count($fields) === 4 && $fields[1] === 'admin@admin.test') {
|
||||
$this->__servers[] = [
|
||||
'Server' => [
|
||||
'url' => trim($fields[0]),
|
||||
'authkey' => trim($fields[2])
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getOptionParser()
|
||||
{
|
||||
$parser = parent::getOptionParser();
|
||||
$parser->addSubcommand('enableTaxonomy', [
|
||||
'help' => __('Enable a taxonomy with all its tags.'),
|
||||
'parser' => array(
|
||||
'options' => array(
|
||||
'instances' => [
|
||||
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
|
||||
'short' => 'i',
|
||||
'required' => true
|
||||
],
|
||||
'taxonomy' => [
|
||||
'help' => 'The name of the taxonomy to enable, such as "tlp"',
|
||||
'short' => 't',
|
||||
'required' => true
|
||||
],
|
||||
'misp_url_filter' => [
|
||||
'help' => 'The url of the instance to enable it for - otherwise all are selected',
|
||||
'short' => 'm',
|
||||
'required' => false
|
||||
]
|
||||
),
|
||||
),
|
||||
]);
|
||||
$parser->addSubcommand('addWarninglist', [
|
||||
'help' => __('Inject warninglist'),
|
||||
'parser' => array(
|
||||
'options' => array(
|
||||
'instances' => [
|
||||
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
|
||||
'short' => 'i',
|
||||
'required' => true
|
||||
],
|
||||
'warninglist' => [
|
||||
'help' => 'Path to the warninglist file',
|
||||
'short' => 'w',
|
||||
'required' => true
|
||||
]
|
||||
),
|
||||
),
|
||||
]);
|
||||
$parser->addSubcommand('status', [
|
||||
'help' => __('Check if the instances are available / the API key works.'),
|
||||
'parser' => array(
|
||||
'options' => array(
|
||||
'instances' => [
|
||||
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
|
||||
'short' => 'i',
|
||||
'required' => true
|
||||
]
|
||||
),
|
||||
),
|
||||
]);
|
||||
$parser->addSubcommand('scores', [
|
||||
'help' => __('Generate the scores for all BTs.'),
|
||||
'parser' => array(
|
||||
'options' => array(
|
||||
'instances' => [
|
||||
'help' => 'Path to the instance file, by default "instances.csv" from the local directory',
|
||||
'short' => 'i',
|
||||
'required' => true
|
||||
],
|
||||
'server_url' => [
|
||||
'help' => 'URL of the server to query for the scores. If nothing is specified, the first valid entry from instances.csv is taken.',
|
||||
'short' => 's',
|
||||
'required' => false
|
||||
],
|
||||
'from' => [
|
||||
'help' => 'Lower bound of the date. Accepts timestamp or date distance (such as 1d or 5h). Defaults to unbounded.',
|
||||
'short' => 'f',
|
||||
'required' => false
|
||||
],
|
||||
'to' => [
|
||||
'help' => 'Upper bound of the date. Accepts timestamp or date distance (such as 1d or 5h). Defaults to unbounded.',
|
||||
'short' => 't',
|
||||
'required' => false
|
||||
]
|
||||
),
|
||||
),
|
||||
]);
|
||||
return $parser;
|
||||
}
|
||||
|
||||
public function enableTaxonomy()
|
||||
{
|
||||
$taxonomyToEnable = $this->param('taxonomy');
|
||||
$instanceFilter = $this->param('misp_url_filter');
|
||||
if (empty($taxonomyToEnable)) {
|
||||
$this->error('No taxonomy provided', 'Provide a taxonomy by specifying the -t or --taxonomy options.');
|
||||
}
|
||||
$this->__getInstances($this->param('instances'));
|
||||
$results = [];
|
||||
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'] . '/taxonomies/index', false, $request);
|
||||
if (!$response->isOk()) {
|
||||
$this->out($server['Server']['url'] . ': ' . '<error>Connection or auth failed</error>', 1, Shell::NORMAL);
|
||||
}
|
||||
$taxonomies = json_decode($response->body, true);
|
||||
$success = false;
|
||||
foreach ($taxonomies as $taxonomy) {
|
||||
if ($taxonomy['Taxonomy']['namespace'] === $taxonomyToEnable) {
|
||||
$response = $HttpSocket->post($server['Server']['url'] . '/taxonomies/enable/' . $taxonomy['Taxonomy']['id'], '{}', $request);
|
||||
if ($response->isOk()) {
|
||||
$response = $HttpSocket->post($server['Server']['url'] . '/taxonomies/addTag/' . $taxonomy['Taxonomy']['id'], '{}', $request);
|
||||
if ($response->isOk()) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$results[$server['Server']['url']] = $success ? 'Success' : 'Failed';
|
||||
$statusWrapped = sprintf(
|
||||
'<%s>%s</%s>',
|
||||
$success ? 'info' : 'error',
|
||||
$results[$server['Server']['url']],
|
||||
$success ? 'info' : 'error'
|
||||
);
|
||||
$this->out($server['Server']['url'] . ': ' . $statusWrapped, 1, Shell::NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
public function status()
|
||||
{
|
||||
$this->__getInstances($this->param('instances'));
|
||||
$results = [];
|
||||
foreach ($this->__servers as $server) {
|
||||
$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'
|
||||
);
|
||||
$this->out($server['Server']['url'] . ': ' . $statusWrapped, 1, Shell::NORMAL);
|
||||
$results[$server['Server']['url']] = $response->isOk() ? $execution_time : false;
|
||||
}
|
||||
}
|
||||
|
||||
public function addWarninglist()
|
||||
{
|
||||
$path = $this->param('warninglist');
|
||||
if (empty($path)) {
|
||||
$this->error('No warninglist provided', 'Provide a path to a file containing a warninglist JSON by specifying the -w or --warninglist options.');
|
||||
}
|
||||
$file = file_get_contents($path);
|
||||
$this->__getInstances($this->param('instances'));
|
||||
$results = [];
|
||||
foreach ($this->__servers as $server) {
|
||||
$HttpSocket = $this->Server->setupHttpSocket($server, null);
|
||||
$request = $this->Server->setupSyncRequest($server, 'Server');
|
||||
$start_time = microtime(true);
|
||||
$response = $HttpSocket->post($server['Server']['url'] . '/warninglists/add', $file, $request);
|
||||
$statusWrapped = sprintf(
|
||||
'<%s>%s</%s>',
|
||||
$response->isOk() ? 'info' : 'error',
|
||||
$response->isOk() ? 'OK' : 'Could not create warninglist',
|
||||
$response->isOk() ? 'info' : 'error'
|
||||
);
|
||||
$this->out($server['Server']['url'] . ': ' . $statusWrapped, 1, Shell::NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
public function scores()
|
||||
{
|
||||
$results = [];
|
||||
$this->__getInstances($this->param('instances'));
|
||||
$server = null;
|
||||
if (!empty($this->param['server_url'])) {
|
||||
foreach ($this->__servers as $temp_server) {
|
||||
if ($temp_server['Server']['url'] === $this->param['server_url']) {
|
||||
$server = $temp_server;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$server = $this->__servers[0];
|
||||
}
|
||||
$HttpSocket = $this->Server->setupHttpSocket($server, null);
|
||||
$request = $this->Server->setupSyncRequest($server);
|
||||
$response = $HttpSocket->get($server['Server']['url'] . '/organisations/index', 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') {
|
||||
continue;
|
||||
}
|
||||
$org_mapping[$org['Organisation']['name']] = $org['Organisation']['id'];
|
||||
}
|
||||
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
|
||||
];
|
||||
if (!empty($time_range)) {
|
||||
$params['publish_timestamp'] = $time_range;
|
||||
}
|
||||
$response = $HttpSocket->post($server['Server']['url'] . '/events/restSearch', json_encode($params), $request);
|
||||
$events = json_decode($response->body(), true);
|
||||
$this->out(__('Events fetched from %s. %d found.', $org_name, count($events['response'])), 1, Shell::VERBOSE);
|
||||
$results[$org_name] = [
|
||||
'attribute_count' => 0,
|
||||
'object_count' => 0,
|
||||
'connected_elements' => 0,
|
||||
'event_tags' => 0,
|
||||
'attribute_tags' => 0,
|
||||
'attack' => 0,
|
||||
'other' => 0,
|
||||
'attribute_attack' => 0,
|
||||
'attribute_other' => 0,
|
||||
'score' => 0
|
||||
];
|
||||
foreach ($events['response'] as $event) {
|
||||
if (!empty($event['Event']['Tag'])) {
|
||||
foreach ($event['Event']['Tag'] as $tag) {
|
||||
if (substr($tag['name'], 0, 32) === 'misp-galaxy:mitre-attack-pattern') {
|
||||
$results[$org_name]['attack'] += 1;
|
||||
} else {
|
||||
$results[$org_name]['other'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($event['Event']['Galaxy'])) {
|
||||
foreach ($event['Event']['Galaxy'] as $galaxy) {
|
||||
if ($galaxy['type'] === 'mitre-attack-pattern') {
|
||||
$results[$org_name]['attack'] += 1;
|
||||
} else {
|
||||
$results[$org_name]['other'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($event['Event']['Attribute'] as $attribute) {
|
||||
if (!empty($attribute['referenced_by'])) {
|
||||
$results[$org_name]['connected_elements'] +=1;
|
||||
}
|
||||
if (!empty($attribute['Tag'])) {
|
||||
foreach ($attribute['Tag'] as $tag) {
|
||||
if (substr($tag['name'], 0, 32) === 'misp-galaxy:mitre-attack-pattern') {
|
||||
$results[$org_name]['attribute_attack'] += 1;
|
||||
} else {
|
||||
$results[$org_name]['attribute_other'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$results[$org_name]['attribute_count'] += count($event['Event']['Attribute']);
|
||||
if (!empty($event['Event']['Object'])) {
|
||||
foreach ($event['Event']['Object'] as $object) {
|
||||
$results[$org_name]['attribute_count'] += count($object['Attribute']);
|
||||
$results[$org_name]['object_count'] += 1;
|
||||
if (!empty($object['ObjectReference'])) {
|
||||
$results[$org_name]['connected_elements'] += 1;
|
||||
}
|
||||
foreach ($object['Attribute'] as $attribute) {
|
||||
if (!empty($attribute['Tag'])) {
|
||||
foreach ($attribute['Tag'] as $tag) {
|
||||
if (substr($tag['name'], 0, 32) === 'misp-galaxy:mitre-attack-pattern') {
|
||||
$results[$org_name]['attribute_attack'] += 1;
|
||||
} else {
|
||||
$results[$org_name]['attribute_other'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$scores = [];
|
||||
foreach ($results as $k => $result) {
|
||||
$totalCount = $result['attribute_count'] + $result['object_count'];
|
||||
if ($totalCount) {
|
||||
$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) {
|
||||
if (empty($results[$k]['metrics'][$metric])) {
|
||||
$results[$k]['metrics'][$metric] = 0;
|
||||
}
|
||||
if ($results[$k]['metrics'][$metric] > 100) {
|
||||
$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'];
|
||||
}
|
||||
arsort($scores, SORT_DESC);
|
||||
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
|
||||
$this->out(sprintf(
|
||||
'| %s | %s | %s |',
|
||||
str_pad('Org', 10, ' ', STR_PAD_RIGHT),
|
||||
str_pad('Graph', 100, ' ', STR_PAD_RIGHT),
|
||||
str_pad('Score', 8, ' ', STR_PAD_RIGHT)
|
||||
), 1, Shell::NORMAL);
|
||||
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
|
||||
foreach ($scores as $org => $score) {
|
||||
$score_string = str_repeat('█', round($score));
|
||||
$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))
|
||||
),
|
||||
str_pad($score . '%', 8, ' ', STR_PAD_RIGHT)
|
||||
), 1, Shell::NORMAL);
|
||||
}
|
||||
$this->out(str_repeat('=', 128), 1, Shell::NORMAL);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
http://download.geonames.org/export/dump/countryInfo.txt
|
||||
|
||||
<?php
|
||||
class SupportShell extends AppShell {
|
||||
|
||||
|
|
|
@ -0,0 +1,302 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
class ApiController extends AppController
|
||||
{
|
||||
public function beforeFilter()
|
||||
{
|
||||
parent::beforeFilter();
|
||||
$this->Security->unlockedActions[] = 'getApiInfo';
|
||||
}
|
||||
|
||||
public function openapi()
|
||||
{
|
||||
$this->set('title_for_layout', __('OpenAPI'));
|
||||
}
|
||||
|
||||
public function viewDeprecatedFunctionUse()
|
||||
{
|
||||
$server = ClassRegistry::init('Server');
|
||||
$data = $this->Deprecation->getDeprecatedAccessList($server);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->layout = false;
|
||||
$this->set('data', $data);
|
||||
}
|
||||
}
|
||||
|
||||
public function getAllApis()
|
||||
{
|
||||
$allValidApis = $this->RestResponse->getAllApis($this->Auth->user());
|
||||
$allValidApisFieldsConstraint = $this->RestResponse->getAllApisFieldsConstraint($this->Auth->user());
|
||||
$output = [
|
||||
'allValidApis' => $allValidApis,
|
||||
'fieldsConstraint' => $allValidApisFieldsConstraint,
|
||||
];
|
||||
return $this->RestResponse->viewData($output, 'json');
|
||||
}
|
||||
|
||||
public function getApiInfo()
|
||||
{
|
||||
$relative_path = $this->request->data['url'];
|
||||
$result = $this->RestResponse->getApiInfo($relative_path);
|
||||
if ($this->_isRest()) {
|
||||
if (!empty($result)) {
|
||||
$result['api_info'] = $result;
|
||||
}
|
||||
return $this->RestResponse->viewData($result, $this->response->type());
|
||||
} else {
|
||||
if (empty($result)) {
|
||||
return $this->RestResponse->viewData(' ', $this->response->type());
|
||||
}
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->set('api_info', $result);
|
||||
$this->render('ajax/get_api_info');
|
||||
}
|
||||
}
|
||||
|
||||
public function rest()
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$request = $this->request->data;
|
||||
if (!empty($request['Server'])) {
|
||||
$request = $this->request->data['Server'];
|
||||
}
|
||||
$curl = '';
|
||||
$python = '';
|
||||
try {
|
||||
$result = $this->__doRestQuery($request, $curl, $python);
|
||||
$this->set('curl', $curl);
|
||||
$this->set('python', $python);
|
||||
if (!$result) {
|
||||
$this->Flash->error('Something went wrong. Make sure you set the http method, body (when sending POST requests) and URL correctly.');
|
||||
} else {
|
||||
$this->set('data', $result);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->Flash->error(__('Something went wrong. %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$header = sprintf(
|
||||
"Authorization: %s \nAccept: application/json\nContent-type: application/json",
|
||||
__('YOUR_API_KEY')
|
||||
);
|
||||
$this->set('header', $header);
|
||||
|
||||
$allAccessibleApis = $this->RestResponse->getAccessibleApis($this->Auth->user());
|
||||
$this->set('allAccessibleApis', $allAccessibleApis);
|
||||
$this->set('title_for_layout', __('REST client'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $request
|
||||
* @param string $curl
|
||||
* @param string $python
|
||||
* @return array|false
|
||||
*/
|
||||
private function __doRestQuery(array $request, &$curl = false, &$python = false)
|
||||
{
|
||||
$params = array();
|
||||
|
||||
$logHeaders = $request['header'];
|
||||
if (!empty(Configure::read('Security.advanced_authkeys'))) {
|
||||
$logHeaders = explode("\n", $request['header']);
|
||||
foreach ($logHeaders as $k => $header) {
|
||||
if (strpos($header, 'Authorization') !== false) {
|
||||
$logHeaders[$k] = 'Authorization: ' . __('YOUR_API_KEY');
|
||||
}
|
||||
}
|
||||
$logHeaders = implode("\n", $logHeaders);
|
||||
}
|
||||
|
||||
if (empty($request['body'])) {
|
||||
$historyBody = '';
|
||||
} else if (strlen($request['body']) > 65535) {
|
||||
$historyBody = ''; // body is too long to save into history table
|
||||
} else {
|
||||
$historyBody = $request['body'];
|
||||
}
|
||||
|
||||
$rest_history_item = array(
|
||||
'headers' => $logHeaders,
|
||||
'body' => $historyBody,
|
||||
'url' => $request['url'],
|
||||
'http_method' => $request['method'],
|
||||
'use_full_path' => empty($request['use_full_path']) ? false : $request['use_full_path'],
|
||||
'show_result' => $request['show_result'],
|
||||
'skip_ssl' => $request['skip_ssl_validation'],
|
||||
'bookmark' => $request['bookmark'],
|
||||
'bookmark_name' => $request['name'],
|
||||
'timestamp' => time(),
|
||||
);
|
||||
if (!empty($request['url'])) {
|
||||
if (empty($request['use_full_path']) || empty(Configure::read('Security.rest_client_enable_arbitrary_urls'))) {
|
||||
$path = preg_replace('#^(://|[^/?])+#', '', $request['url']);
|
||||
$url = empty(Configure::read('Security.rest_client_baseurl')) ? (Configure::read('MISP.baseurl') . $path) : (Configure::read('Security.rest_client_baseurl') . $path);
|
||||
unset($request['url']);
|
||||
} else {
|
||||
$url = $request['url'];
|
||||
}
|
||||
} else {
|
||||
throw new InvalidArgumentException('URL not set.');
|
||||
}
|
||||
if (!empty($request['skip_ssl_validation'])) {
|
||||
$params['ssl_verify_peer'] = false;
|
||||
$params['ssl_verify_host'] = false;
|
||||
$params['ssl_verify_peer_name'] = false;
|
||||
$params['ssl_allow_self_signed'] = true;
|
||||
}
|
||||
$params['timeout'] = 300;
|
||||
App::uses('HttpSocketExtended', 'Tools');
|
||||
$HttpSocket = new HttpSocketExtended($params);
|
||||
|
||||
$temp_headers = empty($request['header']) ? [] : explode("\n", $request['header']);
|
||||
$request['header'] = array(
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'User-Agent' => 'MISP REST Client',
|
||||
);
|
||||
foreach ($temp_headers as $header) {
|
||||
$header = explode(':', $header);
|
||||
$header[0] = trim($header[0]);
|
||||
$header[1] = trim($header[1]);
|
||||
$request['header'][$header[0]] = $header[1];
|
||||
}
|
||||
$start = microtime(true);
|
||||
if (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'GET'
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('get', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->get($url, false, array('header' => $request['header']));
|
||||
} elseif (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'POST' &&
|
||||
!empty($request['body'])
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('post', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->post($url, $request['body'], array('header' => $request['header']));
|
||||
} elseif (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'DELETE'
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('delete', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->delete($url, false, array('header' => $request['header']));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$viewData = [
|
||||
'duration' => round((microtime(true) - $start) * 1000, 2) . ' ms',
|
||||
'url' => $url,
|
||||
'code' => $response->code,
|
||||
'headers' => $response->headers,
|
||||
];
|
||||
|
||||
if (!empty($request['show_result'])) {
|
||||
$viewData['data'] = $response->body;
|
||||
} else {
|
||||
if ($response->isOk()) {
|
||||
$viewData['data'] = 'Success.';
|
||||
} else {
|
||||
$viewData['data'] = 'Something went wrong.';
|
||||
}
|
||||
}
|
||||
$rest_history_item['outcome'] = $response->code;
|
||||
|
||||
$this->loadModel('RestClientHistory');
|
||||
$this->RestClientHistory->insert($this->Auth->user(), $rest_history_item);
|
||||
|
||||
return $viewData;
|
||||
}
|
||||
|
||||
private function __generatePythonScript(array $request, $url)
|
||||
{
|
||||
$slashCounter = 0;
|
||||
$baseurl = '';
|
||||
$relative = '';
|
||||
$verifyCert = ($url[4] === 's') ? 'True' : 'False';
|
||||
for ($i = 0; $i < strlen($url); $i++) {
|
||||
//foreach ($url as $url[$i]) {
|
||||
if ($url[$i] === '/') {
|
||||
$slashCounter += 1;
|
||||
if ($slashCounter == 3) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($slashCounter < 3) {
|
||||
$baseurl .= $url[$i];
|
||||
} else {
|
||||
$relative .= $url[$i];
|
||||
}
|
||||
}
|
||||
$python_script =
|
||||
sprintf(
|
||||
'misp_url = \'%s\'
|
||||
misp_key = \'%s\'
|
||||
misp_verifycert = %s
|
||||
relative_path = \'%s\'
|
||||
body = %s
|
||||
|
||||
from pymisp import ExpandedPyMISP
|
||||
|
||||
misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)
|
||||
misp.direct_call(relative_path, body)
|
||||
',
|
||||
$baseurl,
|
||||
$request['header']['Authorization'],
|
||||
$verifyCert,
|
||||
$relative,
|
||||
(empty($request['body']) ? 'None' : $request['body'])
|
||||
);
|
||||
return $python_script;
|
||||
}
|
||||
|
||||
private function __generateCurlQuery($type, array $request, $url)
|
||||
{
|
||||
if ($type === 'get') {
|
||||
$curl = sprintf(
|
||||
'curl \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s %s',
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
} else {
|
||||
$curl = sprintf(
|
||||
'curl \%s -d \'%s\' \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s -X POST %s',
|
||||
PHP_EOL,
|
||||
json_encode(json_decode($request['body'])),
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
}
|
||||
return $curl;
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ class AppController extends Controller
|
|||
|
||||
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
|
||||
|
||||
private $__queryVersion = '138';
|
||||
private $__queryVersion = '139';
|
||||
public $pyMispVersion = '2.4.157';
|
||||
public $phpmin = '7.2';
|
||||
public $phprec = '7.4';
|
||||
|
@ -202,20 +202,7 @@ class AppController extends Controller
|
|||
if (empty($dataToDecode)) {
|
||||
return null;
|
||||
}
|
||||
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;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
return $this->_jsonDecode($dataToDecode);
|
||||
};
|
||||
// Throw exception if JSON in request is invalid. Default CakePHP behaviour would just ignore that error.
|
||||
$this->RequestHandler->addInputType('json', [$jsonDecode]);
|
||||
|
@ -376,7 +363,7 @@ class AppController extends Controller
|
|||
{
|
||||
// Notifications and homepage is not necessary for AJAX or REST requests
|
||||
$user = $this->Auth->user();
|
||||
if ($user && !$this->_isRest() && !$this->request->is('ajax')) {
|
||||
if ($user && !$this->_isRest() && isset($this->User) && !$this->request->is('ajax')) {
|
||||
$hasNotifications = $this->User->hasNotifications($user);
|
||||
$this->set('hasNotifications', $hasNotifications);
|
||||
|
||||
|
@ -1450,4 +1437,27 @@ class AppController extends Controller
|
|||
}
|
||||
return parent::_getViewObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode JSON with proper error handling.
|
||||
* @param string $dataToDecode
|
||||
* @return mixed
|
||||
*/
|
||||
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;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -940,22 +940,14 @@ class AttributesController extends AppController
|
|||
if (!$changed) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('errors'=> array('value' => 'nochange'))), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$date = new DateTime();
|
||||
$attribute['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$time = time();
|
||||
$attribute['Attribute']['timestamp'] = $time;
|
||||
|
||||
$fieldsToSave = ['timestamp'];
|
||||
if ($changedKey === 'value') {
|
||||
$fieldsToSave[] = 'value1';
|
||||
$fieldsToSave[] = 'value2';
|
||||
} else {
|
||||
$fieldsToSave[] = $changedKey;
|
||||
}
|
||||
|
||||
if ($this->Attribute->save($attribute, true, $fieldsToSave)) {
|
||||
$this->Attribute->Event->unpublishEvent($attribute['Attribute']['event_id'], false, $date->getTimestamp());
|
||||
if ($this->Attribute->save($attribute)) {
|
||||
$this->Attribute->Event->unpublishEvent($attribute['Attribute']['event_id'], false, $time);
|
||||
|
||||
if ($attribute['Attribute']['object_id'] != 0) {
|
||||
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $date->getTimestamp());
|
||||
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $time);
|
||||
}
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Field updated.', 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
|
||||
} else {
|
||||
|
@ -1982,12 +1974,6 @@ class AttributesController extends AppController
|
|||
$result = $this->Attribute->shortDist[$result];
|
||||
} elseif ($field === 'to_ids') {
|
||||
$result = ($result == 0 ? 'No' : 'Yes');
|
||||
} elseif ($field === 'timestamp') {
|
||||
if (isset($result)) {
|
||||
$result = date('Y-m-d', $result);
|
||||
} else {
|
||||
echo ' ';
|
||||
}
|
||||
} elseif ($field === 'value') {
|
||||
$this->loadModel('Warninglist');
|
||||
$attribute['Attribute'] = $this->Warninglist->checkForWarning($attribute['Attribute']);
|
||||
|
|
|
@ -141,10 +141,10 @@ class AuthKeysController extends AppController
|
|||
}
|
||||
$params = [
|
||||
'displayOnSuccess' => 'authkey_display',
|
||||
'saveModelVariable' => ['authkey_raw'],
|
||||
'override' => ['authkey' => null], // do not allow to use own key, always generate random one
|
||||
'afterFind' => function ($authKey) { // remove hashed key from response
|
||||
'afterFind' => function (array $authKey, array $savedData) { // remove hashed key from response
|
||||
unset($authKey['AuthKey']['authkey']);
|
||||
$authKey['AuthKey']['authkey_raw'] = $savedData['AuthKey']['authkey_raw'];
|
||||
return $authKey;
|
||||
}
|
||||
];
|
||||
|
@ -195,11 +195,10 @@ class AuthKeysController extends AppController
|
|||
if ($this->IndexFilter->isRest()) {
|
||||
return $this->restResponsePayload;
|
||||
}
|
||||
$this->loadModel('User');
|
||||
$dropdownData = [
|
||||
'user' => $this->User->find('list', [
|
||||
'user' => $this->AuthKey->User->find('list', [
|
||||
'sort' => ['username' => 'asc'],
|
||||
'conditions' => $selectConditions
|
||||
'conditions' => $selectConditions,
|
||||
])
|
||||
];
|
||||
$this->set(compact('dropdownData'));
|
||||
|
|
|
@ -19,6 +19,13 @@ class ACLComponent extends Component
|
|||
'queryACL' => array(),
|
||||
'restSearch' => array('*'),
|
||||
),
|
||||
'api' => [
|
||||
'rest' => ['perm_auth'],
|
||||
'viewDeprecatedFunctionUse' => [],
|
||||
'openapi' => ['*'],
|
||||
'getApiInfo' => ['*'],
|
||||
'getAllApis' => ['*'],
|
||||
],
|
||||
'attributes' => array(
|
||||
'add' => array('perm_add'),
|
||||
'add_attachment' => array('perm_add'),
|
||||
|
@ -505,7 +512,6 @@ class ACLComponent extends Component
|
|||
'eventBlockRule' => array(),
|
||||
'fetchServersForSG' => array('perm_sharing_group'),
|
||||
'filterEventIndex' => array(),
|
||||
'getApiInfo' => array('*'),
|
||||
'getAvailableSyncFilteringRules' => array('*'),
|
||||
'getInstanceUUID' => array('perm_sync'),
|
||||
'getPyMISPVersion' => array('*'),
|
||||
|
@ -531,8 +537,6 @@ class ACLComponent extends Component
|
|||
'releaseUpdateLock' => array(),
|
||||
'resetRemoteAuthKey' => array(),
|
||||
'removeOrphanedCorrelations' => array(),
|
||||
'rest' => array('perm_auth'),
|
||||
'openapi' => array('*'),
|
||||
'restartDeadWorkers' => array(),
|
||||
'restartWorkers' => array(),
|
||||
'serverSettings' => array(),
|
||||
|
@ -549,7 +553,6 @@ class ACLComponent extends Component
|
|||
'updateProgress' => array(),
|
||||
'updateSubmodule' => array(),
|
||||
'uploadFile' => array(),
|
||||
'viewDeprecatedFunctionUse' => array(),
|
||||
'killAllWorkers' => [],
|
||||
'cspReport' => ['*'],
|
||||
'pruneDuplicateUUIDs' => array(),
|
||||
|
@ -557,6 +560,7 @@ class ACLComponent extends Component
|
|||
'upgrade2324' => array(),
|
||||
'cleanModelCaches' => array(),
|
||||
'updateDatabase' => array(),
|
||||
'rest' => ['perm_auth'],
|
||||
),
|
||||
'shadowAttributes' => array(
|
||||
'accept' => array('perm_add'),
|
||||
|
|
|
@ -90,7 +90,8 @@ class CRUDComponent extends Component
|
|||
}
|
||||
/** @var Model $model */
|
||||
$model = $this->Controller->{$modelName};
|
||||
if ($model->save($data)) {
|
||||
$savedData = $model->save($data);
|
||||
if ($savedData) {
|
||||
if (isset($params['afterSave'])) {
|
||||
$params['afterSave']($data);
|
||||
}
|
||||
|
@ -100,15 +101,11 @@ class CRUDComponent extends Component
|
|||
'id' => $model->id
|
||||
]
|
||||
]);
|
||||
if (!empty($params['saveModelVariable'])) {
|
||||
foreach ($params['saveModelVariable'] as $var) {
|
||||
if (isset($model->$var)) {
|
||||
$data[$modelName][$var] = $model->$var;
|
||||
}
|
||||
}
|
||||
if (empty($data)) {
|
||||
throw new Exception("Something went wrong, saved data not found in database.");
|
||||
}
|
||||
if (isset($params['afterFind'])) {
|
||||
$data = $params['afterFind']($data);
|
||||
$data = $params['afterFind']($data, $savedData);
|
||||
}
|
||||
$message = __('%s added.', $modelName);
|
||||
if ($this->Controller->IndexFilter->isRest()) {
|
||||
|
|
|
@ -48,7 +48,7 @@ class RestResponseComponent extends Component
|
|||
'restSearch' => array(
|
||||
'description' => "Search MISP using a list of filter parameters and return the data in the selected format. The search is available on an event and an attribute level, just select the scope via the URL (/events/restSearch vs /attributes/restSearch). Besides the parameters listed, other, format specific ones can be passed along (for example: requested_attributes and includeContext for the CSV export). This API allows pagination via the page and limit parameters.",
|
||||
'mandatory' => array('returnFormat'),
|
||||
'optional' => array('page', 'limit', 'value' , 'type', 'category', 'org', 'tags', 'date', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'attribute_timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'includeEventTags', 'event_timestamp', 'threat_level_id', 'eventinfo', 'includeProposals', 'includeDecayScore', 'includeFullModel', 'decayingModel', 'excludeDecayed', 'score', 'first_seen', 'last_seen'),
|
||||
'optional' => array('page', 'limit', 'value' , 'type', 'category', 'org', 'tags', 'date', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'attribute_timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'includeEventTags', 'event_timestamp', 'threat_level_id', 'eventinfo', 'sharinggroup', 'includeProposals', 'includeDecayScore', 'includeFullModel', 'decayingModel', 'excludeDecayed', 'score', 'first_seen', 'last_seen'),
|
||||
'params' => array()
|
||||
),
|
||||
'addTag' => array(
|
||||
|
@ -88,7 +88,7 @@ class RestResponseComponent extends Component
|
|||
'restSearch' => array(
|
||||
'description' => "Search MISP using a list of filter parameters and return the data in the selected format. The search is available on an event and an attribute level, just select the scope via the URL (/events/restSearch vs /attributes/restSearch). Besides the parameters listed, other, format specific ones can be passed along (for example: requested_attributes and includeContext for the CSV export). This API allows pagination via the page and limit parameters.",
|
||||
'mandatory' => array('returnFormat'),
|
||||
'optional' => array('page', 'limit', 'value', 'type', 'category', 'org', 'tag', 'tags', 'searchall', 'date', 'last', 'eventid', 'withAttachments', 'metadata', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly', 'eventinfo', 'excludeLocalTags', 'threat_level_id'),
|
||||
'optional' => array('page', 'limit', 'value', 'type', 'category', 'org', 'tag', 'tags', 'searchall', 'date', 'last', 'eventid', 'withAttachments', 'metadata', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly', 'eventinfo', 'sharinggroup', 'excludeLocalTags', 'threat_level_id'),
|
||||
'params' => array()
|
||||
),
|
||||
'addTag' => array(
|
||||
|
@ -367,12 +367,7 @@ class RestResponseComponent extends Component
|
|||
$controller = $controller === 'EventGraph' ? 'event_graph' : Inflector::tableize($controller);
|
||||
foreach ($actions as $action => $data) {
|
||||
if ($this->ACL->canUserAccess($user, $controller, $action)) {
|
||||
$admin_routing = '';
|
||||
if (substr($action, 0, 6) === 'admin_') {
|
||||
$action = substr($action, 6);
|
||||
$admin_routing = 'admin/';
|
||||
}
|
||||
$url = $this->baseurl . '/' . $admin_routing . $controller . '/' . $action;
|
||||
$url = $this->generateUrl($controller, $action);
|
||||
$result[$url] = $data;
|
||||
}
|
||||
}
|
||||
|
@ -380,6 +375,25 @@ class RestResponseComponent extends Component
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $user
|
||||
* @return array
|
||||
*/
|
||||
public function getAccessibleApis(array $user)
|
||||
{
|
||||
$output = [];
|
||||
foreach ($this->__descriptions as $controller => $actions) {
|
||||
$controller = $controller === 'EventGraph' ? 'event_graph' : Inflector::tableize($controller);
|
||||
foreach ($actions as $action => $data) {
|
||||
if ($this->ACL->canUserAccess($user, $controller, $action)) {
|
||||
$url = $this->generateUrl($controller, $action);
|
||||
$output[$controller][$action] = $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getAllApis($user)
|
||||
{
|
||||
$this->__setup();
|
||||
|
@ -389,15 +403,10 @@ class RestResponseComponent extends Component
|
|||
$controller = $controller === 'EventGraph' ? 'event_graph' : Inflector::tableize($controller);
|
||||
foreach ($actions as $action => $data) {
|
||||
if ($this->ACL->canUserAccess($user, $controller, $action)) {
|
||||
$admin_routing = '';
|
||||
if (substr($action, 0, 6) === 'admin_') {
|
||||
$action = substr($action, 6);
|
||||
$admin_routing = 'admin/';
|
||||
}
|
||||
$data['api_name'] = '[' . $controller . '] ' . $action;
|
||||
$data['controller'] = $controller;
|
||||
$data['action'] = $action;
|
||||
$data['body'] = array();
|
||||
$body = [];
|
||||
$filter_types = array('mandatory', 'optional');
|
||||
foreach ($filter_types as $filter_type) {
|
||||
if (!empty($data[$filter_type])) {
|
||||
|
@ -407,16 +416,16 @@ class RestResponseComponent extends Component
|
|||
}
|
||||
foreach ($filter_items as $filter) {
|
||||
if ($filter === lcfirst($filter)) {
|
||||
$data['body'][$filter] = $filter_type;
|
||||
$body[$filter] = $filter_type;
|
||||
} else {
|
||||
$data['body'][$filter] = array($filter_type);
|
||||
$body[$filter] = array($filter_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['body'] = json_encode($data['body'], JSON_PRETTY_PRINT);
|
||||
$url = $this->baseurl . '/' . $admin_routing . $controller . '/' . $action;
|
||||
$data['body'] = $body;
|
||||
$url = $this->generateUrl($controller, $action);;
|
||||
$data['url'] = $url;
|
||||
if (!empty($data['params'])) {
|
||||
foreach ($data['params'] as $param) {
|
||||
|
@ -592,14 +601,14 @@ class RestResponseComponent extends Component
|
|||
}
|
||||
|
||||
if ($response instanceof TmpFileTool) {
|
||||
App::uses('CakeResponseFile', 'Tools');
|
||||
$cakeResponse = new CakeResponseFile(['status' => $code, 'type' => $type]);
|
||||
if ($this->signContents) {
|
||||
$this->CryptographicKey = ClassRegistry::init('CryptographicKey');
|
||||
$data = $response->intoString();
|
||||
$headers['x-pgp-signature'] = base64_encode($this->CryptographicKey->signWithInstanceKey($data));
|
||||
$cakeResponse = new CakeResponse(array('body' => $data, 'status' => $code, 'type' => $type));
|
||||
$cakeResponse = new CakeResponse(['body' => $data, 'status' => $code, 'type' => $type]);
|
||||
} else {
|
||||
App::uses('CakeResponseFile', 'Tools');
|
||||
$cakeResponse = new CakeResponseFile(['status' => $code, 'type' => $type]);
|
||||
$cakeResponse->file($response);
|
||||
}
|
||||
} else {
|
||||
|
@ -731,13 +740,8 @@ class RestResponseComponent extends Component
|
|||
$scopes = array('Event', 'Attribute', 'Sighting');
|
||||
foreach ($scopes as $scope) {
|
||||
$this->{$scope} = ClassRegistry::init($scope);
|
||||
$this->__descriptions[$scope]['restSearch'] = array(
|
||||
'description' => $this->__descriptions[$scope]['restSearch']['description'],
|
||||
'returnFormat' => array_keys($this->{$scope}->validFormats),
|
||||
'mandatory' => $this->__descriptions[$scope]['restSearch']['mandatory'],
|
||||
'optional' => $this->__descriptions[$scope]['restSearch']['optional'],
|
||||
'params' => $this->__descriptions[$scope]['restSearch']['params']
|
||||
);
|
||||
$returnFormat = array_keys($this->{$scope}->validFormats);
|
||||
$this->__descriptions[$scope]['restSearch']['returnFormat'] = $returnFormat;
|
||||
}
|
||||
$this->__configureFieldConstraints();
|
||||
$this->__setupFieldsConstraint();
|
||||
|
@ -1938,7 +1942,8 @@ class RestResponseComponent extends Component
|
|||
if ($values === null) {
|
||||
$tagModel = ClassRegistry::init("Tag");
|
||||
$tags = $tagModel->find('column', array(
|
||||
'fields' => array('Tag.name')
|
||||
'fields' => array('Tag.name'),
|
||||
'callbacks' => false,
|
||||
));
|
||||
$values = [];
|
||||
foreach ($tags as $tag) {
|
||||
|
@ -1963,19 +1968,40 @@ class RestResponseComponent extends Component
|
|||
private function __overwriteAction($scope, $action, &$field) {
|
||||
$field['values'] = array_keys(ClassRegistry::init("Log")->actionDefinitions);
|
||||
}
|
||||
private function __overwriteRoleId($scope, $action, &$field) {
|
||||
$this->{$scope} = ClassRegistry::init("Role");
|
||||
$roles = $this->{$scope}->find('list', array(
|
||||
'fields' => array('id', 'name')
|
||||
));
|
||||
$field['values'] = [];
|
||||
foreach ($roles as $id => $name) {
|
||||
$field['values'][] = ['label' => $name, 'value' => $id];
|
||||
|
||||
private function __overwriteRoleId($scope, $action, &$field)
|
||||
{
|
||||
static $values;
|
||||
if ($values === null) {
|
||||
$roleModel = ClassRegistry::init("Role");
|
||||
$roles = $roleModel->find('list', array(
|
||||
'fields' => array('id', 'name')
|
||||
));
|
||||
$values = [];
|
||||
foreach ($roles as $id => $name) {
|
||||
$values[] = ['label' => $name, 'value' => $id];
|
||||
}
|
||||
}
|
||||
$field['values'] = $values;
|
||||
}
|
||||
private function __overwriteSeen($scope, $action, &$field) {
|
||||
if ($action == 'restSearch') {
|
||||
$field['help'] = __('Seen within the last x amount of time, where x can be defined in days, hours, minutes (for example 5d or 12h or 30m)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controller
|
||||
* @param string $action
|
||||
* @return string
|
||||
*/
|
||||
private function generateUrl($controller, $action)
|
||||
{
|
||||
$admin_routing = '';
|
||||
if (substr($action, 0, 6) === 'admin_') {
|
||||
$action = substr($action, 6);
|
||||
$admin_routing = 'admin/';
|
||||
}
|
||||
return '/' . $admin_routing . $controller . '/' . $action;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1109,6 +1109,7 @@ class EventsController extends AppController
|
|||
'eventid' => array('OR' => array(), 'NOT' => array()),
|
||||
'date' => array('from' => "", 'until' => ""),
|
||||
'eventinfo' => array('OR' => array(), 'NOT' => array()),
|
||||
'all' => array('OR' => array(), 'NOT' => array()),
|
||||
'threatlevel' => array('OR' => array(), 'NOT' => array()),
|
||||
'distribution' => array('OR' => array(), 'NOT' => array()),
|
||||
'sharinggroup' => array('OR' => array(), 'NOT' => array()),
|
||||
|
@ -1187,6 +1188,7 @@ class EventsController extends AppController
|
|||
'hasproposal' => __('Has proposal'),
|
||||
'timestamp' => __('Last change at'),
|
||||
'publishtimestamp' => __('Published at'),
|
||||
'all' => __('Search in all fields'),
|
||||
];
|
||||
|
||||
if ($this->_isSiteAdmin()) {
|
||||
|
@ -1402,6 +1404,8 @@ 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('mayPublish', $this->__canPublishEvent($event));
|
||||
$this->response->disableCache();
|
||||
|
||||
// Remove `focus` attribute from URI
|
||||
|
@ -3211,7 +3215,8 @@ class EventsController extends AppController
|
|||
'order' => 'Event.timestamp DESC',
|
||||
));
|
||||
$this->loadModel('Job');
|
||||
foreach ($this->Event->export_types as $k => $type) {
|
||||
$exportTypes = $this->Event->exportTypes();
|
||||
foreach ($exportTypes as $k => $type) {
|
||||
if ($type['requiresPublished']) {
|
||||
$tempNewestEvent = $newestEventPublished;
|
||||
} else {
|
||||
|
@ -3235,10 +3240,10 @@ class EventsController extends AppController
|
|||
if (!$file->readable()) {
|
||||
if (empty($tempNewestEvent)) {
|
||||
$lastModified = 'No valid events';
|
||||
$this->Event->export_types[$k]['recommendation'] = 0;
|
||||
$exportTypes[$k]['recommendation'] = 0;
|
||||
} else {
|
||||
$lastModified = 'N/A';
|
||||
$this->Event->export_types[$k]['recommendation'] = 1;
|
||||
$exportTypes[$k]['recommendation'] = 1;
|
||||
}
|
||||
} else {
|
||||
$filesize = $file->size();
|
||||
|
@ -3247,32 +3252,31 @@ class EventsController extends AppController
|
|||
$filesize_unit_index++;
|
||||
$filesize = $filesize / 1024;
|
||||
}
|
||||
$this->Event->export_types[$k]['filesize'] = round($filesize, 1) . $filesize_units[$filesize_unit_index];
|
||||
$exportTypes[$k]['filesize'] = round($filesize, 1) . $filesize_units[$filesize_unit_index];
|
||||
$fileChange = $file->lastChange();
|
||||
$lastModified = $this->__timeDifference($now, $fileChange);
|
||||
if (empty($tempNewestEvent) || $fileChange > $tempNewestEvent['Event']['timestamp']) {
|
||||
if (empty($tempNewestEvent)) {
|
||||
$lastModified = 'No valid events';
|
||||
}
|
||||
$this->Event->export_types[$k]['recommendation'] = 0;
|
||||
$exportTypes[$k]['recommendation'] = 0;
|
||||
} else {
|
||||
$this->Event->export_types[$k]['recommendation'] = 1;
|
||||
$exportTypes[$k]['recommendation'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$this->Event->export_types[$k]['lastModified'] = $lastModified;
|
||||
$exportTypes[$k]['lastModified'] = $lastModified;
|
||||
if (!empty($job)) {
|
||||
$this->Event->export_types[$k]['job_id'] = $job['Job']['id'];
|
||||
$this->Event->export_types[$k]['progress'] = $job['Job']['progress'];
|
||||
$exportTypes[$k]['job_id'] = $job['Job']['id'];
|
||||
$exportTypes[$k]['progress'] = $job['Job']['progress'];
|
||||
} else {
|
||||
$this->Event->export_types[$k]['job_id'] = -1;
|
||||
$this->Event->export_types[$k]['progress'] = 0;
|
||||
$exportTypes[$k]['job_id'] = -1;
|
||||
$exportTypes[$k]['progress'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->loadModel('Attribute');
|
||||
$this->set('sigTypes', array_keys($this->Attribute->typeDefinitions));
|
||||
$this->set('export_types', $this->Event->export_types);
|
||||
$this->set('sigTypes', array_keys($this->Event->Attribute->typeDefinitions));
|
||||
$this->set('export_types', $exportTypes);
|
||||
}
|
||||
|
||||
public function downloadExport($type, $extra = null)
|
||||
|
@ -3289,8 +3293,9 @@ class EventsController extends AppController
|
|||
if ($extra != null) {
|
||||
$extra = '_' . $extra;
|
||||
}
|
||||
$this->response->type($this->Event->export_types[$type]['extension']);
|
||||
$path = 'tmp/cached_exports/' . $type . DS . 'misp.' . strtolower($this->Event->export_types[$type]['type']) . $extra . '.' . $org . $this->Event->export_types[$type]['extension'];
|
||||
$exportType = $this->Event->exportTypes()[$type];
|
||||
$this->response->type($exportType['extension']);
|
||||
$path = 'tmp/cached_exports/' . $type . DS . 'misp.' . strtolower($exportType['type']) . $extra . '.' . $org . $exportType['extension'];
|
||||
$this->response->file($path, array('download' => true));
|
||||
}
|
||||
|
||||
|
@ -3920,17 +3925,18 @@ class EventsController extends AppController
|
|||
*/
|
||||
public function freeTextImport($id, $adhereToWarninglists = false, $returnMetaAttributes = false)
|
||||
{
|
||||
$this->request->allowMethod(['post', 'get']);
|
||||
|
||||
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
|
||||
if (empty($event)) {
|
||||
throw new MethodNotAllowedException(__('Invalid event.'));
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$this->set('event_id', $event['Event']['id']);
|
||||
if ($this->request->is('get')) {
|
||||
$this->layout = 'ajax';
|
||||
$this->request->data['Attribute']['event_id'] = $event['Event']['id'];
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
} else if ($this->request->is('post')) {
|
||||
App::uses('ComplexTypeTool', 'Tools');
|
||||
$complexTypeTool = new ComplexTypeTool();
|
||||
$this->loadModel('Warninglist');
|
||||
|
@ -3944,16 +3950,16 @@ class EventsController extends AppController
|
|||
if (isset($this->request->data['Attribute']['adhereToWarninglists'])) {
|
||||
$adhereToWarninglists = $this->request->data['Attribute']['adhereToWarninglists'];
|
||||
}
|
||||
$resultArray = $complexTypeTool->checkComplexRouter($this->request->data['Attribute']['value'], 'freetext');
|
||||
foreach ($resultArray as $key => $r) {
|
||||
$temp = array();
|
||||
foreach ($r['types'] as $type) {
|
||||
$temp[$type] = $type;
|
||||
}
|
||||
$resultArray[$key]['types'] = $temp;
|
||||
}
|
||||
|
||||
$resultArray = $complexTypeTool->checkFreeText($this->request->data['Attribute']['value']);
|
||||
if ($this->_isRest()) {
|
||||
// Keep this 'types' format for rest response, but it is not necessary for UI
|
||||
foreach ($resultArray as $key => $r) {
|
||||
$temp = array();
|
||||
foreach ($r['types'] as $type) {
|
||||
$temp[$type] = $type;
|
||||
}
|
||||
$resultArray[$key]['types'] = $temp;
|
||||
}
|
||||
if ($returnMetaAttributes || !empty($this->request->data['Attribute']['returnMetaAttributes'])) {
|
||||
return $this->RestResponse->viewData($resultArray, $this->response->type());
|
||||
} else {
|
||||
|
@ -3967,7 +3973,6 @@ class EventsController extends AppController
|
|||
}
|
||||
}
|
||||
$this->Event->Attribute->fetchRelated($this->Auth->user(), $resultArray);
|
||||
$resultArray = array_values($resultArray);
|
||||
$typeCategoryMapping = array();
|
||||
foreach ($this->Event->Attribute->categoryDefinitions as $k => $cat) {
|
||||
foreach ($cat['types'] as $type) {
|
||||
|
@ -3987,15 +3992,10 @@ class EventsController extends AppController
|
|||
$this->set('mayModify', $this->__canModifyEvent($event));
|
||||
$this->set('typeDefinitions', $this->Event->Attribute->typeDefinitions);
|
||||
$this->set('typeCategoryMapping', $typeCategoryMapping);
|
||||
foreach ($typeCategoryMapping as $k => $v) {
|
||||
$typeCategoryMapping[$k] = array_values($v);
|
||||
}
|
||||
$this->set('mapping', $typeCategoryMapping);
|
||||
$this->set('resultArray', $resultArray);
|
||||
$this->set('importComment', '');
|
||||
$this->set('title_for_layout', __('Freetext Import Results'));
|
||||
$this->set('title', __('Freetext Import Results'));
|
||||
$this->loadModel('Warninglist');
|
||||
$this->set('missingTldLists', $this->Warninglist->missingTldLists());
|
||||
$this->render('resolved_attributes');
|
||||
}
|
||||
|
@ -4038,19 +4038,17 @@ class EventsController extends AppController
|
|||
|
||||
public function saveFreeText($id)
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
throw new MethodNotAllowedException('This endpoint requires a POST request.');
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
|
||||
if (!$event) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
|
||||
$this->Event->insertLock($this->Auth->user(), $id);
|
||||
$attributes = json_decode($this->request->data['Attribute']['JsonObject'], true);
|
||||
$default_comment = $this->request->data['Attribute']['default_comment'];
|
||||
$attributes = $this->_jsonDecode($this->request->data['Attribute']['JsonObject']);
|
||||
$defaultComment = $this->request->data['Attribute']['default_comment'];
|
||||
$proposals = !$this->__canModifyEvent($event) || (isset($this->request->data['Attribute']['force']) && $this->request->data['Attribute']['force']);
|
||||
$flashMessage = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, $default_comment, $proposals);
|
||||
$flashMessage = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, $defaultComment, $proposals);
|
||||
$this->Flash->info($flashMessage);
|
||||
|
||||
if ($this->request->is('ajax')) {
|
||||
|
@ -6139,7 +6137,7 @@ class EventsController extends AppController
|
|||
|
||||
/**
|
||||
* @param array $event
|
||||
* @return CakeResponseTmp
|
||||
* @return CakeResponseFile
|
||||
* @throws Exception
|
||||
*/
|
||||
private function __restResponse(array $event)
|
||||
|
@ -6171,23 +6169,24 @@ class EventsController extends AppController
|
|||
|
||||
public function protect($id)
|
||||
{
|
||||
$this->__toggleProtect($id, true);
|
||||
return $this->__toggleProtect($id, true);
|
||||
}
|
||||
|
||||
public function unprotect($id)
|
||||
{
|
||||
$this->__toggleProtect($id, false);
|
||||
return $this->__toggleProtect($id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $id Event ID or UUID
|
||||
* @param bool $protect
|
||||
* @return CakeResponse|void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function __toggleProtect($id, $protect)
|
||||
{
|
||||
$id = $this->Toolbox->findIdByUuid($this->Event, $id);
|
||||
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id, ['contain' => ['Orgc']]);
|
||||
if (
|
||||
(!$this->_isSiteAdmin && $event['Event']['orgc_id'] !== $this->Auth->user('org_id')) ||
|
||||
!$event ||
|
||||
!$this->__canModifyEvent($event)
|
||||
) {
|
||||
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
|
||||
if (empty($event) || !$this->__canModifyEvent($event)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
if ($this->request->is('post')) {
|
||||
|
@ -6197,7 +6196,7 @@ class EventsController extends AppController
|
|||
if ($this->Event->save($event)) {
|
||||
$message = __('Event switched to %s mode.', $protect ? __('protected') : __('unprotected'));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('events', $protect ? 'protect' : 'unprotect', $id, false, $message);
|
||||
return $this->RestResponse->saveSuccessResponse('events', $protect ? 'protect' : 'unprotect', $event['Event']['id'], false, $message);
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(['controller' => 'events', 'action' => 'view', $id]);
|
||||
|
@ -6205,14 +6204,14 @@ class EventsController extends AppController
|
|||
} else {
|
||||
$message = __('Something went wrong - could not switch event to %s mode.', $protect ? __('protected') : __('unprotected'));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Events', $protect ? 'protect' : 'unprotect', false, $message, $this->response->type());
|
||||
return $this->RestResponse->saveFailResponse('Events', $protect ? 'protect' : 'unprotect', $event['Event']['id'], $message);
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect(['controller' => 'events', 'action' => 'view', $id]);
|
||||
$this->redirect(['controller' => 'events', 'action' => 'view', $event['Event']['id']]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->set('id', $id);
|
||||
$this->set('id', $event['Event']['id']);
|
||||
$this->set('title', $protect ? __('Protect event') : __('Remove event protection'));
|
||||
$this->set(
|
||||
'question',
|
||||
|
|
|
@ -298,6 +298,9 @@ class FeedsController extends AppController
|
|||
$tags = $this->Event->EventTag->Tag->find('list', array('fields' => array('Tag.name'), 'order' => array('lower(Tag.name) asc')));
|
||||
$tags[0] = 'None';
|
||||
|
||||
$this->loadModel('Server');
|
||||
$allTypes = $this->Server->getAllTypes();
|
||||
|
||||
$dropdownData = [
|
||||
'orgs' => $this->Event->Orgc->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
|
@ -309,9 +312,12 @@ class FeedsController extends AppController
|
|||
'distributionLevels' => $distributionLevels,
|
||||
'inputSources' => $inputSources
|
||||
];
|
||||
$this->set('allAttributeTypes', $allTypes['attribute']);
|
||||
$this->set('allObjectTypes', $allTypes['object']);
|
||||
$this->set(compact('dropdownData'));
|
||||
$this->set('defaultPullRules', json_encode(Feed::DEFAULT_FEED_PULL_RULES));
|
||||
$this->set('menuData', array('menuList' => 'feeds', 'menuItem' => 'add'));
|
||||
$this->set('pull_scope', 'feed');
|
||||
}
|
||||
|
||||
private function __checkRegex($pattern)
|
||||
|
@ -346,10 +352,14 @@ class FeedsController extends AppController
|
|||
'delete_local_file',
|
||||
'lookup_visible',
|
||||
'headers',
|
||||
'orgc_id'
|
||||
'orgc_id',
|
||||
'fixed_event'
|
||||
],
|
||||
'afterFind' => function (array $feed) {
|
||||
$feed['Feed']['settings'] = json_decode($feed['Feed']['settings'], true);
|
||||
if ($feed['Feed']['source_format'] == 'misp' && empty($feed['Feed']['rules'])) {
|
||||
$feed['Feed']['rules'] = json_encode(Feed::DEFAULT_FEED_PULL_RULES);
|
||||
}
|
||||
|
||||
return $feed;
|
||||
},
|
||||
|
@ -437,6 +447,12 @@ class FeedsController extends AppController
|
|||
$tags = $this->Event->EventTag->Tag->find('list', array('fields' => array('Tag.name'), 'order' => array('lower(Tag.name) asc')));
|
||||
$tags[0] = 'None';
|
||||
|
||||
$this->loadModel('Server');
|
||||
$allTypes = $this->Server->getAllTypes();
|
||||
$this->set('allAttributeTypes', $allTypes['attribute']);
|
||||
$this->set('allObjectTypes', $allTypes['object']);
|
||||
$this->set('supportedUrlparams', Feed::SUPPORTED_URL_PARAM_FILTERS);
|
||||
|
||||
$dropdownData = [
|
||||
'orgs' => $this->Event->Orgc->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
|
@ -458,6 +474,7 @@ class FeedsController extends AppController
|
|||
if(!empty($this->request->data['Feed']['rules'])){
|
||||
$this->request->data['Feed']['pull_rules'] = $this->request->data['Feed']['rules'];
|
||||
}
|
||||
$this->set('pull_scope', 'feed');
|
||||
$this->render('add');
|
||||
}
|
||||
|
||||
|
|
|
@ -573,21 +573,21 @@ class ObjectsController extends AppController
|
|||
public function fetchViewValue($id, $field = null)
|
||||
{
|
||||
$validFields = array('timestamp', 'comment', 'distribution', 'first_seen', 'last_seen');
|
||||
if (!isset($field) || !in_array($field, $validFields)) {
|
||||
if (!isset($field) || !in_array($field, $validFields, true)) {
|
||||
throw new MethodNotAllowedException('Invalid field requested.');
|
||||
}
|
||||
if (!$this->request->is('ajax')) {
|
||||
throw new MethodNotAllowedException('This function can only be accessed via AJAX.');
|
||||
}
|
||||
$params = array(
|
||||
'conditions' => array('Object.id' => $id),
|
||||
'fields' => array('id', 'distribution', 'event_id', $field),
|
||||
'contain' => array(
|
||||
'Event' => array(
|
||||
'fields' => array('distribution', 'id', 'org_id'),
|
||||
)
|
||||
),
|
||||
'flatten' => 1
|
||||
'conditions' => array('Object.id' => $id),
|
||||
'fields' => array('id', 'distribution', 'event_id', $field),
|
||||
'contain' => array(
|
||||
'Event' => array(
|
||||
'fields' => array('distribution', 'id', 'org_id'),
|
||||
)
|
||||
),
|
||||
'flatten' => 1
|
||||
);
|
||||
$object = $this->MispObject->fetchObjectSimple($this->Auth->user(), $params);
|
||||
if (empty($object)) {
|
||||
|
@ -595,10 +595,11 @@ class ObjectsController extends AppController
|
|||
}
|
||||
$object = $object[0];
|
||||
$result = $object['Object'][$field];
|
||||
if ($field == 'distribution') {
|
||||
$result=$this->MispObject->shortDist[$result];
|
||||
if ($field === 'distribution') {
|
||||
$result = $this->MispObject->shortDist[$result];
|
||||
}
|
||||
$this->set('value', $result);
|
||||
$this->set('field', $field);
|
||||
$this->layout = 'ajax';
|
||||
$this->render('ajax/objectViewFieldForm');
|
||||
}
|
||||
|
|
|
@ -392,7 +392,7 @@ class OrganisationsController extends AppController
|
|||
{
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->set('id', $id);
|
||||
$this->set('id', (int)$id);
|
||||
$this->set('removable', $removable);
|
||||
$this->set('extend', $extend);
|
||||
$this->render('ajax/sg_org_row_empty');
|
||||
|
|
|
@ -30,7 +30,12 @@ class PagesController extends AppController
|
|||
public function display()
|
||||
{
|
||||
$path = func_get_args();
|
||||
|
||||
foreach ($path as $k => $part) {
|
||||
if (strpos($part, '..') !== false || strpos($part, '/') !== false) {
|
||||
unset($path[$k]);
|
||||
}
|
||||
}
|
||||
$path = array_values($path);
|
||||
$count = count($path);
|
||||
if (!$count) {
|
||||
$this->redirect('/');
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
/**
|
||||
* @property RestClientHistory $RestClientHistory
|
||||
*/
|
||||
class RestClientHistoryController extends AppController
|
||||
{
|
||||
public $components = array(
|
||||
|
@ -37,19 +39,16 @@ class RestClientHistoryController extends AppController
|
|||
}
|
||||
if ($this->_isRest()) {
|
||||
$list = $this->RestClientHistory->find('all', $params);
|
||||
} else {
|
||||
$this->paginate = array_merge($this->paginate, $params);
|
||||
$list = $this->paginate();
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($list, $this->response->type());
|
||||
} else {
|
||||
$this->set('bookmarked', $bookmarked);
|
||||
$this->set('list', $list);
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->render('index');
|
||||
}
|
||||
|
||||
$this->paginate = array_merge($this->paginate, $params);
|
||||
$list = $this->paginate();
|
||||
$this->set('bookmarked', $bookmarked);
|
||||
$this->set('list', array_column($list, 'RestClientHistory'));
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->render('index');
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
|
|
|
@ -39,7 +39,6 @@ class ServersController extends AppController
|
|||
$this->Auth->allow(['cspReport']); // cspReport must work without authentication
|
||||
|
||||
parent::beforeFilter();
|
||||
$this->Security->unlockedActions[] = 'getApiInfo';
|
||||
$this->Security->unlockedActions[] = 'cspReport';
|
||||
// permit reuse of CSRF tokens on some pages.
|
||||
switch ($this->request->params['action']) {
|
||||
|
@ -443,20 +442,7 @@ class ServersController extends AppController
|
|||
$allOrgs[] = array('id' => $o['Organisation']['id'], 'name' => $o['Organisation']['name']);
|
||||
}
|
||||
|
||||
$allTypes = [];
|
||||
$this->loadModel('Attribute');
|
||||
$this->loadModel('ObjectTemplate');
|
||||
$objects = $this->ObjectTemplate->find('all', [
|
||||
'recursive' => -1,
|
||||
'fields' => ['uuid', 'name'],
|
||||
'group' => ['uuid', 'name'],
|
||||
]);
|
||||
$allTypes = [
|
||||
'attribute' => array_unique(Hash::extract(Hash::extract($this->Attribute->categoryDefinitions, '{s}.types'), '{n}.{n}')),
|
||||
'object' => Hash::map($objects, '{n}.ObjectTemplate', function ($item) {
|
||||
return ['id' => $item['uuid'], 'name' => sprintf('%s (%s)', $item['name'], $item['uuid'])];
|
||||
})
|
||||
];
|
||||
$allTypes = $this->Server->getAllTypes();
|
||||
|
||||
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
|
||||
$this->set('organisationOptions', $organisationOptions);
|
||||
|
@ -468,6 +454,7 @@ class ServersController extends AppController
|
|||
|
||||
$this->set('allTags', $this->__getTags());
|
||||
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
|
||||
$this->set('pull_scope', 'server');
|
||||
$this->render('edit');
|
||||
}
|
||||
}
|
||||
|
@ -641,20 +628,7 @@ class ServersController extends AppController
|
|||
$allOrgs[] = array('id' => $o['Organisation']['id'], 'name' => $o['Organisation']['name']);
|
||||
}
|
||||
|
||||
$allTypes = [];
|
||||
$this->loadModel('Attribute');
|
||||
$this->loadModel('ObjectTemplate');
|
||||
$objects = $this->ObjectTemplate->find('all', [
|
||||
'recursive' => -1,
|
||||
'fields' => ['uuid', 'name'],
|
||||
'group' => ['uuid', 'name'],
|
||||
]);
|
||||
$allTypes = [
|
||||
'attribute' => array_unique(Hash::extract(Hash::extract($this->Attribute->categoryDefinitions, '{s}.types'), '{n}.{n}')),
|
||||
'object' => Hash::map($objects, '{n}.ObjectTemplate', function ($item) {
|
||||
return ['id' => $item['uuid'], 'name' => sprintf('%s (%s)', $item['name'], $item['uuid'])];
|
||||
})
|
||||
];
|
||||
$allTypes = $this->Server->getAllTypes();
|
||||
|
||||
$oldRemoteSetting = 0;
|
||||
if (!$this->Server->data['RemoteOrg']['local']) {
|
||||
|
@ -675,6 +649,7 @@ class ServersController extends AppController
|
|||
$this->set('server', $s);
|
||||
$this->set('id', $id);
|
||||
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
|
||||
$this->set('pull_scope', 'server');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1996,280 +1971,6 @@ class ServersController extends AppController
|
|||
return $this->RestResponse->viewData(array('uuid' => Configure::read('MISP.uuid')), $this->response->type());
|
||||
}
|
||||
|
||||
public function rest()
|
||||
{
|
||||
$allValidApis = $this->RestResponse->getAllApis($this->Auth->user());
|
||||
$allValidApisFieldsContraint = $this->RestResponse->getAllApisFieldsConstraint($this->Auth->user());
|
||||
if ($this->request->is('post')) {
|
||||
$request = $this->request->data;
|
||||
if (!empty($request['Server'])) {
|
||||
$request = $this->request->data['Server'];
|
||||
}
|
||||
$curl = '';
|
||||
$python = '';
|
||||
try {
|
||||
$result = $this->__doRestQuery($request, $curl, $python);
|
||||
$this->set('curl', $curl);
|
||||
$this->set('python', $python);
|
||||
if (!$result) {
|
||||
$this->Flash->error('Something went wrong. Make sure you set the http method, body (when sending POST requests) and URL correctly.');
|
||||
} else {
|
||||
$this->set('data', $result);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->Flash->error(__('Something went wrong. %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$header = sprintf(
|
||||
"Authorization: %s \nAccept: application/json\nContent-type: application/json",
|
||||
__('YOUR_API_KEY')
|
||||
);
|
||||
$this->set('header', $header);
|
||||
$this->set('allValidApis', $allValidApis);
|
||||
// formating for optgroup
|
||||
$allValidApisFormated = array();
|
||||
foreach ($allValidApis as $endpoint_url => $endpoint_data) {
|
||||
$allValidApisFormated[$endpoint_data['controller']][] = array('url' => $endpoint_url, 'action' => $endpoint_data['action']);
|
||||
}
|
||||
$this->set('allValidApisFormated', $allValidApisFormated);
|
||||
$this->set('allValidApisFieldsContraint', $allValidApisFieldsContraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $request
|
||||
* @param string $curl
|
||||
* @param string $python
|
||||
* @return array|false
|
||||
*/
|
||||
private function __doRestQuery(array $request, &$curl = false, &$python = false)
|
||||
{
|
||||
App::uses('SyncTool', 'Tools');
|
||||
$params = array();
|
||||
|
||||
$logHeaders = $request['header'];
|
||||
if (!empty(Configure::read('Security.advanced_authkeys'))) {
|
||||
$logHeaders = explode("\n", $request['header']);
|
||||
foreach ($logHeaders as $k => $header) {
|
||||
if (strpos($header, 'Authorization') !== false) {
|
||||
$logHeaders[$k] = 'Authorization: ' . __('YOUR_API_KEY');
|
||||
}
|
||||
}
|
||||
$logHeaders = implode("\n", $logHeaders);
|
||||
}
|
||||
|
||||
if (empty($request['body'])) {
|
||||
$historyBody = '';
|
||||
} else if (strlen($request['body']) > 65535) {
|
||||
$historyBody = ''; // body is too long to save into history table
|
||||
} else {
|
||||
$historyBody = $request['body'];
|
||||
}
|
||||
|
||||
$rest_history_item = array(
|
||||
'org_id' => $this->Auth->user('org_id'),
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'headers' => $logHeaders,
|
||||
'body' => $historyBody,
|
||||
'url' => $request['url'],
|
||||
'http_method' => $request['method'],
|
||||
'use_full_path' => empty($request['use_full_path']) ? false : $request['use_full_path'],
|
||||
'show_result' => $request['show_result'],
|
||||
'skip_ssl' => $request['skip_ssl_validation'],
|
||||
'bookmark' => $request['bookmark'],
|
||||
'bookmark_name' => $request['name'],
|
||||
'timestamp' => time(),
|
||||
);
|
||||
if (!empty($request['url'])) {
|
||||
if (empty($request['use_full_path']) || empty(Configure::read('Security.rest_client_enable_arbitrary_urls'))) {
|
||||
$path = preg_replace('#^(://|[^/?])+#', '', $request['url']);
|
||||
$url = empty(Configure::read('Security.rest_client_baseurl')) ? (Configure::read('MISP.baseurl') . $path) : (Configure::read('Security.rest_client_baseurl') . $path);
|
||||
unset($request['url']);
|
||||
} else {
|
||||
$url = $request['url'];
|
||||
}
|
||||
} else {
|
||||
throw new InvalidArgumentException('URL not set.');
|
||||
}
|
||||
if (!empty($request['skip_ssl_validation'])) {
|
||||
$params['ssl_verify_peer'] = false;
|
||||
$params['ssl_verify_host'] = false;
|
||||
$params['ssl_verify_peer_name'] = false;
|
||||
$params['ssl_allow_self_signed'] = true;
|
||||
}
|
||||
$params['timeout'] = 300;
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket($params);
|
||||
|
||||
$temp_headers = empty($request['header']) ? [] : explode("\n", $request['header']);
|
||||
$request['header'] = array(
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'User-Agent' => 'MISP REST Client',
|
||||
);
|
||||
foreach ($temp_headers as $header) {
|
||||
$header = explode(':', $header);
|
||||
$header[0] = trim($header[0]);
|
||||
$header[1] = trim($header[1]);
|
||||
$request['header'][$header[0]] = $header[1];
|
||||
}
|
||||
$start = microtime(true);
|
||||
if (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'GET'
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('get', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->get($url, false, array('header' => $request['header']));
|
||||
} elseif (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'POST' &&
|
||||
!empty($request['body'])
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('post', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->post($url, $request['body'], array('header' => $request['header']));
|
||||
} elseif (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'DELETE'
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('delete', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->delete($url, false, array('header' => $request['header']));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$viewData = [
|
||||
'duration' => round((microtime(true) - $start) * 1000, 2) . ' ms',
|
||||
'url' => $url,
|
||||
'code' => $response->code,
|
||||
'headers' => $response->headers,
|
||||
];
|
||||
|
||||
if (!empty($request['show_result'])) {
|
||||
$viewData['data'] = $response->body;
|
||||
} else {
|
||||
if ($response->isOk()) {
|
||||
$viewData['data'] = 'Success.';
|
||||
} else {
|
||||
$viewData['data'] = 'Something went wrong.';
|
||||
}
|
||||
}
|
||||
$rest_history_item['outcome'] = $response->code;
|
||||
|
||||
$this->loadModel('RestClientHistory');
|
||||
$this->RestClientHistory->create();
|
||||
$this->RestClientHistory->save($rest_history_item);
|
||||
$this->RestClientHistory->cleanup($this->Auth->user('id'));
|
||||
|
||||
return $viewData;
|
||||
}
|
||||
|
||||
private function __generatePythonScript($request, $url)
|
||||
{
|
||||
$slashCounter = 0;
|
||||
$baseurl = '';
|
||||
$relative = '';
|
||||
$verifyCert = ($url[4] === 's') ? 'True' : 'False';
|
||||
for ($i = 0; $i < strlen($url); $i++) {
|
||||
//foreach ($url as $url[$i]) {
|
||||
if ($url[$i] === '/') {
|
||||
$slashCounter += 1;
|
||||
if ($slashCounter == 3) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($slashCounter < 3) {
|
||||
$baseurl .= $url[$i];
|
||||
} else {
|
||||
$relative .= $url[$i];
|
||||
}
|
||||
}
|
||||
$python_script =
|
||||
sprintf(
|
||||
'misp_url = \'%s\'
|
||||
misp_key = \'%s\'
|
||||
misp_verifycert = %s
|
||||
relative_path = \'%s\'
|
||||
body = %s
|
||||
|
||||
from pymisp import ExpandedPyMISP
|
||||
|
||||
misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)
|
||||
misp.direct_call(relative_path, body)
|
||||
',
|
||||
$baseurl,
|
||||
$request['header']['Authorization'],
|
||||
$verifyCert,
|
||||
$relative,
|
||||
(empty($request['body']) ? 'None' : $request['body'])
|
||||
);
|
||||
return $python_script;
|
||||
}
|
||||
|
||||
private function __generateCurlQuery($type, $request, $url)
|
||||
{
|
||||
if ($type === 'get') {
|
||||
$curl = sprintf(
|
||||
'curl \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s %s',
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
} else {
|
||||
$curl = sprintf(
|
||||
'curl \%s -d \'%s\' \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s -X POST %s',
|
||||
PHP_EOL,
|
||||
json_encode(json_decode($request['body'])),
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
}
|
||||
return $curl;
|
||||
}
|
||||
|
||||
public function getApiInfo()
|
||||
{
|
||||
$relative_path = $this->request->data['url'];
|
||||
$result = $this->RestResponse->getApiInfo($relative_path);
|
||||
if ($this->_isRest()) {
|
||||
if (!empty($result)) {
|
||||
$result['api_info'] = $result;
|
||||
}
|
||||
return $this->RestResponse->viewData($result, $this->response->type());
|
||||
} else {
|
||||
if (empty($result)) {
|
||||
return $this->RestResponse->viewData(' ', $this->response->type());
|
||||
}
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->set('api_info', $result);
|
||||
$this->render('ajax/get_api_info');
|
||||
}
|
||||
}
|
||||
|
||||
public function cache($id = 'all')
|
||||
{
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
|
@ -2525,17 +2226,6 @@ misp.direct_call(relative_path, body)
|
|||
return new CakeResponse(['status' => 204]);
|
||||
}
|
||||
|
||||
public function viewDeprecatedFunctionUse()
|
||||
{
|
||||
$data = $this->Deprecation->getDeprecatedAccessList($this->Server);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->layout = false;
|
||||
$this->set('data', $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all tags for the rule picker.
|
||||
*
|
||||
|
@ -2590,9 +2280,6 @@ misp.direct_call(relative_path, body)
|
|||
return $this->RestResponse->viewData($syncFilteringRules);
|
||||
}
|
||||
|
||||
public function openapi() {
|
||||
}
|
||||
|
||||
public function pruneDuplicateUUIDs()
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
|
@ -2762,4 +2449,13 @@ misp.direct_call(relative_path, body)
|
|||
}
|
||||
return $this->RestResponse->viewData($users, $this->response->type());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return void
|
||||
*/
|
||||
public function rest()
|
||||
{
|
||||
$this->redirect(['controller' => 'api', 'action' => 'rest']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,27 +183,17 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function enable($id)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() || !$this->request->is('Post')) {
|
||||
throw new MethodNotAllowedException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
|
||||
$taxonomy = $this->Taxonomy->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
));
|
||||
$taxonomy['Taxonomy']['enabled'] = true;
|
||||
$this->Taxonomy->save($taxonomy);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'enable',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy enabled',
|
||||
'change' => $taxonomy['Taxonomy']['namespace'] . ' - enabled',
|
||||
));
|
||||
|
||||
$this->__log('enable', $id, 'Taxonomy enabled', $taxonomy['Taxonomy']['namespace'] . ' - enabled');
|
||||
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Taxonomy', 'enable', $id, $this->response->type());
|
||||
} else {
|
||||
|
@ -214,28 +204,18 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function disable($id)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() || !$this->request->is('Post')) {
|
||||
throw new MethodNotAllowedException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
|
||||
$taxonomy = $this->Taxonomy->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
));
|
||||
$this->Taxonomy->disableTags($id);
|
||||
$taxonomy['Taxonomy']['enabled'] = 0;
|
||||
$this->Taxonomy->save($taxonomy);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'disable',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy disabled',
|
||||
'change' => $taxonomy['Taxonomy']['namespace'] . ' - disabled',
|
||||
));
|
||||
|
||||
$this->__log('disable', $id, 'Taxonomy disabled', $taxonomy['Taxonomy']['namespace'] . ' - disabled');
|
||||
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Taxonomy', 'disable', $id, $this->response->type());
|
||||
} else {
|
||||
|
@ -246,9 +226,8 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function import()
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
throw new MethodNotAllowedException('This endpoint requires a POST request.');
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
|
||||
try {
|
||||
$id = $this->Taxonomy->import($this->request->data);
|
||||
return $this->view($id);
|
||||
|
@ -260,7 +239,6 @@ class TaxonomiesController extends AppController
|
|||
public function update()
|
||||
{
|
||||
$result = $this->Taxonomy->update();
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$fails = 0;
|
||||
$successes = 0;
|
||||
if (!empty($result)) {
|
||||
|
@ -271,50 +249,19 @@ class TaxonomiesController extends AppController
|
|||
} else {
|
||||
$change = $success['namespace'] . ' v' . $success['new'] . ' installed';
|
||||
}
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy updated',
|
||||
'change' => $change,
|
||||
));
|
||||
$this->__log('update', $id, 'Taxonomy updated', $change);
|
||||
$successes++;
|
||||
}
|
||||
}
|
||||
if (isset($result['fails'])) {
|
||||
foreach ($result['fails'] as $id => $fail) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy failed to update',
|
||||
'change' => $fail['namespace'] . ' could not be installed/updated. Error: ' . $fail['fail'],
|
||||
));
|
||||
$this->__log('update', $id, 'Taxonomy failed to update', $fail['namespace'] . ' could not be installed/updated. Error: ' . $fail['fail']);
|
||||
$fails++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => 0,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy update (nothing to update)',
|
||||
'change' => 'Executed an update of the taxonomy library, but there was nothing to update.',
|
||||
));
|
||||
$this->__log('update', 0, 'Taxonomy update (nothing to update)', 'Executed an update of the taxonomy library, but there was nothing to update.');
|
||||
}
|
||||
$message = '';
|
||||
if ($successes == 0 && $fails == 0) {
|
||||
$flashType = 'info';
|
||||
$message = __('All taxonomy libraries are up to date already.');
|
||||
|
@ -338,9 +285,6 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function addTag($taxonomy_id = false)
|
||||
{
|
||||
if ((!$this->_isSiteAdmin() && !$this->userRole['perm_tagger'])) {
|
||||
throw new NotFoundException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
if ($this->request->is('get')) {
|
||||
if (empty($taxonomy_id) && !empty($this->request->params['named']['taxonomy_id'])) {
|
||||
$taxonomy_id = $this->request->params['named']['taxonomy_id'];
|
||||
|
@ -391,9 +335,8 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function hideTag($taxonomy_id = false)
|
||||
{
|
||||
if ((!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) || !$this->request->is('post')) {
|
||||
throw new NotFoundException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
|
||||
if ($taxonomy_id) {
|
||||
$result = $this->Taxonomy->hideTags($taxonomy_id);
|
||||
} else {
|
||||
|
@ -421,9 +364,8 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function unhideTag($taxonomy_id = false)
|
||||
{
|
||||
if ((!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) || !$this->request->is('post')) {
|
||||
throw new NotFoundException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
$this->request->allowMethod(['post']);
|
||||
|
||||
if ($taxonomy_id) {
|
||||
$result = $this->Taxonomy->unhideTags($taxonomy_id);
|
||||
} else {
|
||||
|
@ -451,9 +393,6 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public function disableTag($taxonomy_id = false)
|
||||
{
|
||||
if ((!$this->_isSiteAdmin() && !$this->userRole['perm_tagger'])) {
|
||||
throw new NotFoundException(__('You don\'t have permission to do that.'));
|
||||
}
|
||||
if ($this->request->is('get')) {
|
||||
if (empty($taxonomy_id) && !empty($this->request->params['named']['taxonomy_id'])) {
|
||||
$taxonomy_id = $this->request->params['named']['taxonomy_id'];
|
||||
|
@ -559,6 +498,21 @@ class TaxonomiesController extends AppController
|
|||
$this->render('ajax/toggle_required');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param int $modelId
|
||||
* @param string $title
|
||||
* @param string $change
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function __log($action, $modelId, $title, $change)
|
||||
{
|
||||
/** @var Log $log */
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), $action, 'Taxonomy', $modelId, $title, $change);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach tag counts.
|
||||
* @param array $taxonomies
|
||||
|
|
|
@ -154,7 +154,7 @@ class UsersController extends AppController
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!$abortPost && !$this->_isRest()) {
|
||||
if (!$abortPost && (!$this->_isRest() || empty($this->request->header('Authorization')))) {
|
||||
if (Configure::read('Security.require_password_confirmation')) {
|
||||
if (!empty($this->request->data['User']['current_password'])) {
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['current_password']);
|
||||
|
@ -853,7 +853,7 @@ class UsersController extends AppController
|
|||
$this->request->data['User'] = $this->request->data;
|
||||
}
|
||||
$abortPost = false;
|
||||
if (!$this->_isRest()) {
|
||||
if (!$this->_isRest() || empty($this->request->header('Authorization'))) {
|
||||
if (Configure::read('Security.require_password_confirmation')) {
|
||||
if (!empty($this->request->data['User']['current_password'])) {
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['current_password']);
|
||||
|
|
|
@ -40,9 +40,6 @@ class ComplexTypeTool
|
|||
128 => array('single' => array('sha512'), 'composite' => array('filename|sha512'))
|
||||
);
|
||||
|
||||
// algorithms to run through in order, without Hashes that are checked separately
|
||||
const CHECKS = array('Email', 'IP', 'DomainOrFilename', 'SimpleRegex', 'AS', 'BTC');
|
||||
|
||||
private $__tlds = null;
|
||||
|
||||
public static function refangValue($value, $type)
|
||||
|
@ -179,6 +176,9 @@ class ComplexTypeTool
|
|||
continue;
|
||||
}
|
||||
foreach ($row as $elementPos => $element) {
|
||||
if (empty($element)) {
|
||||
continue;
|
||||
}
|
||||
if (empty($values) || in_array(($elementPos + 1), $values)) {
|
||||
$element = trim($element, " \t\n\r\0\x0B\"\'");
|
||||
if (empty($element)) {
|
||||
|
@ -198,23 +198,28 @@ class ComplexTypeTool
|
|||
return $iocArray;
|
||||
}
|
||||
|
||||
public function checkFreeText($input, $settings = array())
|
||||
/**
|
||||
* @param string $input
|
||||
* @param array $settings
|
||||
* @return array
|
||||
*/
|
||||
public function checkFreeText($input, array $settings = [])
|
||||
{
|
||||
$charactersToTrim = '\'".,() ' . "\t\n\r\0\x0B"; // custom + default PHP trim
|
||||
$input = str_replace("\xc2\xa0", ' ', $input); // non breaking space to normal space
|
||||
$input = preg_replace('/\p{C}+/u', ' ', $input);
|
||||
$iocArray = preg_split("/\r\n|\n|\r|\s|\s+|,|\<|\>|;/", $input);
|
||||
|
||||
preg_match_all('/\"([^\"]*)\"/', $input, $matches);
|
||||
foreach ($matches[1] as $match) {
|
||||
if ($match !== '') {
|
||||
$iocArray[] = $match;
|
||||
}
|
||||
}
|
||||
preg_match_all('/\"([^\"]*)\"/', $input, $matches);
|
||||
foreach ($matches[1] as $match) {
|
||||
if ($match !== '') {
|
||||
$iocArray[] = $match;
|
||||
}
|
||||
}
|
||||
unset($matches);
|
||||
|
||||
$resultArray = [];
|
||||
foreach ($iocArray as $ioc) {
|
||||
$ioc = trim($ioc, $charactersToTrim);
|
||||
$ioc = trim($ioc, '\'".,() ' . "\t\n\r\0\x0B"); // custom + default PHP trim
|
||||
if (empty($ioc)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -251,23 +256,37 @@ class ComplexTypeTool
|
|||
];
|
||||
}
|
||||
|
||||
$input = array('raw' => $raw_input);
|
||||
$input = ['raw' => $raw_input];
|
||||
|
||||
// Check hashes before refang and port extracting, it is not necessary for hashes. This speedups parsing
|
||||
// freetexts or CSVs with a lot of hashes.
|
||||
$hashes = $this->__checkForHashes($input);
|
||||
if ($hashes) {
|
||||
return $hashes;
|
||||
if ($result = $this->__checkForHashes($input)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$input = $this->__refangInput($input);
|
||||
$input = $this->__extractPort($input);
|
||||
|
||||
foreach (self::CHECKS as $check) {
|
||||
$result = $this->{'__checkFor' . $check}($input);
|
||||
if ($result) {
|
||||
return $result;
|
||||
}
|
||||
// Check email before port extracting, it is not necessary for email. This speedups parsing
|
||||
// freetexts or CSVs with a lot of emails.
|
||||
if ($result = $this->__checkForEmail($input)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$input = $this->__extractPort($input);
|
||||
if ($result = $this->__checkForIP($input)) {
|
||||
return $result;
|
||||
}
|
||||
if ($result = $this->__checkForDomainOrFilename($input)) {
|
||||
return $result;
|
||||
}
|
||||
if ($result = $this->__checkForSimpleRegex($input)) {
|
||||
return $result;
|
||||
}
|
||||
if ($result = $this->__checkForAS($input)) {
|
||||
return $result;
|
||||
}
|
||||
if ($result = $this->__checkForBTC($input)) {
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -290,7 +309,12 @@ class ComplexTypeTool
|
|||
// quick filter for an @ to see if we should validate a potential e-mail address
|
||||
if (strpos($input['refanged'], '@') !== false) {
|
||||
if (filter_var($input['refanged'], FILTER_VALIDATE_EMAIL)) {
|
||||
return array('types' => array('email', 'email-src', 'email-dst', 'target-email', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input['refanged']);
|
||||
return [
|
||||
'types' => array('email', 'email-src', 'email-dst', 'target-email', 'whois-registrant-email'),
|
||||
'to_ids' => true,
|
||||
'default_type' => 'email-src',
|
||||
'value' => $input['refanged'],
|
||||
];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -356,17 +380,17 @@ class ComplexTypeTool
|
|||
|
||||
private function __refangInput($input)
|
||||
{
|
||||
$input['refanged'] = $input['raw'];
|
||||
$refanged = $input['raw'];
|
||||
foreach (self::REFANG_REGEX_TABLE as $regex) {
|
||||
$input['refanged'] = preg_replace($regex['from'], $regex['to'], $input['refanged']);
|
||||
$refanged = preg_replace($regex['from'], $regex['to'], $refanged);
|
||||
}
|
||||
$input['refanged'] = rtrim($input['refanged'], ".");
|
||||
$refanged = rtrim($refanged, ".");
|
||||
$input['refanged'] = preg_replace_callback(
|
||||
'/\[.\]/',
|
||||
function ($matches) {
|
||||
return trim($matches[0], '[]');
|
||||
},
|
||||
$input['refanged']
|
||||
$refanged
|
||||
);
|
||||
return $input;
|
||||
}
|
||||
|
|
|
@ -173,4 +173,21 @@ class CryptGpgExtended extends Crypt_GPG
|
|||
|
||||
return $armored;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @param bool $isFile
|
||||
* @param bool $allowEmpty
|
||||
* @return resource|string|null
|
||||
* @throws Crypt_GPG_FileException
|
||||
* @throws Crypt_GPG_NoDataException
|
||||
*/
|
||||
protected function _prepareInput($data, $isFile = false, $allowEmpty = true)
|
||||
{
|
||||
if ($isFile && $data instanceof TmpFileTool) {
|
||||
return $data->resource();
|
||||
}
|
||||
|
||||
return parent::_prepareInput($data, $isFile, $allowEmpty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
class GpgTool
|
||||
{
|
||||
/** @var CryptGpgExtended */
|
||||
private $gpg;
|
||||
|
||||
/**
|
||||
* @return CryptGpgExtended
|
||||
* @throws Exception
|
||||
|
@ -22,19 +25,16 @@ class GpgTool
|
|||
throw new Exception("Configuration option 'GnuPG.homedir' is not set, Crypt_GPG cannot be initialized.");
|
||||
}
|
||||
|
||||
$options = array(
|
||||
$options = [
|
||||
'homedir' => $homedir,
|
||||
'gpgconf' => Configure::read('GnuPG.gpgconf'),
|
||||
'binary' => Configure::read('GnuPG.binary') ?: '/usr/bin/gpg',
|
||||
);
|
||||
];
|
||||
|
||||
return new CryptGpgExtended($options);
|
||||
}
|
||||
|
||||
/** @var CryptGpgExtended */
|
||||
private $gpg;
|
||||
|
||||
public function __construct($gpg)
|
||||
public function __construct(CryptGpgExtended $gpg = null)
|
||||
{
|
||||
$this->gpg = $gpg;
|
||||
}
|
||||
|
@ -47,11 +47,13 @@ class GpgTool
|
|||
public function searchGpgKey($search)
|
||||
{
|
||||
$uri = 'https://openpgp.circl.lu/pks/lookup?search=' . urlencode($search) . '&op=index&fingerprint=on&options=mr';
|
||||
$response = $this->keyServerLookup($uri);
|
||||
if ($response->code == 404) {
|
||||
return array(); // no keys found
|
||||
} else if ($response->code != 200) {
|
||||
throw new Exception("Fetching the '$uri' failed with HTTP error {$response->code}: {$response->reasonPhrase}");
|
||||
try {
|
||||
$response = $this->keyServerLookup($uri);
|
||||
} catch (HttpSocketHttpException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return [];
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return $this->extractKeySearch($response->body);
|
||||
}
|
||||
|
@ -64,11 +66,13 @@ class GpgTool
|
|||
public function fetchGpgKey($fingerprint)
|
||||
{
|
||||
$uri = 'https://openpgp.circl.lu/pks/lookup?search=0x' . urlencode($fingerprint) . '&op=get&options=mr';
|
||||
$response = $this->keyServerLookup($uri);
|
||||
if ($response->code == 404) {
|
||||
return null; // key with given fingerprint not found
|
||||
} else if ($response->code != 200) {
|
||||
throw new Exception("Fetching the '$uri' failed with HTTP error {$response->code}: {$response->reasonPhrase}");
|
||||
try {
|
||||
$response = $this->keyServerLookup($uri);
|
||||
} catch (HttpSocketHttpException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return null;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$key = $response->body;
|
||||
|
@ -169,30 +173,20 @@ class GpgTool
|
|||
$advancedUrl = "https://openpgpkey.$domain/.well-known/openpgpkey/" . strtolower($domain) . "/hu/$localPartHash";
|
||||
try {
|
||||
$response = $this->keyServerLookup($advancedUrl);
|
||||
return $this->processWkdResponse($response);
|
||||
return $this->gpg->enarmor($response->body());
|
||||
} catch (Exception $e) {
|
||||
// pass, continue to direct method
|
||||
}
|
||||
|
||||
$directUrl = "https://$domain/.well-known/openpgpkey/hu/$localPartHash";
|
||||
$response = $this->keyServerLookup($directUrl);
|
||||
return $this->processWkdResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param HttpSocketResponse $response
|
||||
* @return string
|
||||
* @throws Crypt_GPG_Exception
|
||||
* @throws Crypt_GPG_InvalidOperationException
|
||||
*/
|
||||
private function processWkdResponse(HttpSocketResponse $response)
|
||||
{
|
||||
if ($response->code == 404) {
|
||||
throw new NotFoundException("Key not found");
|
||||
} else if (!$response->isOk()) {
|
||||
throw new Exception("Fetching the WKD failed with HTTP error {$response->code}: {$response->reasonPhrase}");
|
||||
try {
|
||||
$response = $this->keyServerLookup($directUrl);
|
||||
} catch (HttpSocketHttpException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
throw new NotFoundException("Key not found");
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this->gpg->enarmor($response->body());
|
||||
}
|
||||
|
||||
|
@ -232,17 +226,18 @@ class GpgTool
|
|||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @return HttpSocketResponse
|
||||
* @return HttpSocketResponseExtended
|
||||
* @throws HttpSocketHttpException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function keyServerLookup($uri)
|
||||
{
|
||||
App::uses('SyncTool', 'Tools');
|
||||
$syncTool = new SyncTool();
|
||||
$HttpSocket = $syncTool->setupHttpSocket();
|
||||
$HttpSocket = $syncTool->createHttpSocket(['compress' => true]);
|
||||
$response = $HttpSocket->get($uri);
|
||||
if ($response === false) {
|
||||
throw new Exception("Could not fetch '$uri'.");
|
||||
if (!$response->isOk()) {
|
||||
throw new HttpSocketHttpException($response, $uri);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ class JSONConverterTool
|
|||
if ($raw) {
|
||||
return $result;
|
||||
}
|
||||
return json_encode($result, JSON_PRETTY_PRINT);
|
||||
return json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +127,7 @@ class JSONConverterTool
|
|||
}
|
||||
}
|
||||
if (isset($event['errors'])) {
|
||||
yield '},"errors":' . json_encode($event['errors']) . '}';
|
||||
yield '},"errors":' . json_encode($event['errors'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '}';
|
||||
} else {
|
||||
yield "}}";
|
||||
}
|
||||
|
|
|
@ -26,7 +26,15 @@ class JsonTool
|
|||
*/
|
||||
public static function decode($value)
|
||||
{
|
||||
$flags = defined('JSON_THROW_ON_ERROR') ? JSON_THROW_ON_ERROR : 0; // Throw exception on error if supported
|
||||
return json_decode($value, true, 512, $flags);
|
||||
if (defined('JSON_THROW_ON_ERROR')) {
|
||||
// JSON_THROW_ON_ERROR is supported since PHP 7.3
|
||||
return json_decode($value, true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
$decoded = json_decode($value, true);
|
||||
if ($decoded === null) {
|
||||
throw new UnexpectedValueException('Could not parse JSON: ' . json_last_error_msg(), json_last_error());
|
||||
}
|
||||
return $decoded;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class RandomTool
|
|||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function random_str($crypto_secure = true, $length = 32, $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||
public static function random_str($crypto_secure = true, $length = 32, $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||
{
|
||||
// Type checks:
|
||||
if (!is_bool($crypto_secure)) {
|
||||
|
|
|
@ -71,14 +71,26 @@ class SendEmailTemplate
|
|||
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'html';
|
||||
try {
|
||||
$html = $View->render($this->viewName);
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'html' . DS . 'Custom';
|
||||
$html = $View->render($this->viewName); // Attempt to load a custom template if it exists
|
||||
} catch (MissingViewException $e) {
|
||||
$html = null; // HTMl template is optional
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'html';
|
||||
try {
|
||||
$html = $View->render($this->viewName);
|
||||
} catch (MissingViewException $e) {
|
||||
$html = null; // HTMl template is optional
|
||||
}
|
||||
}
|
||||
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'text';
|
||||
|
||||
$View->hasRendered = false;
|
||||
$text = $View->render($this->viewName);
|
||||
try {
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'text' . DS . 'Custom';
|
||||
$text = $View->render($this->viewName); // Attempt to load a custom template if it exists
|
||||
} catch (MissingViewException $e) {
|
||||
$View->viewPath = $View->layoutPath = 'Emails' . DS . 'text';
|
||||
$text = $View->render($this->viewName);
|
||||
}
|
||||
|
||||
// Template can change default subject.
|
||||
if ($View->get('subject')) {
|
||||
|
|
|
@ -20,6 +20,9 @@ class ServerSyncTool
|
|||
/** @var HttpSocketExtended */
|
||||
private $socket;
|
||||
|
||||
/** @var CryptographicKey */
|
||||
private $cryptographicKey;
|
||||
|
||||
/** @var array|null */
|
||||
private $info;
|
||||
|
||||
|
@ -418,8 +421,10 @@ class ServerSyncTool
|
|||
throw new Exception(__('Remote instance is not protected event aware yet (< 2.4.156), aborting.'));
|
||||
}
|
||||
|
||||
$this->CryptographicKey = ClassRegistry::init('CryptographicKey');
|
||||
$signature = $this->CryptographicKey->signWithInstanceKey($data);
|
||||
if (!$this->cryptographicKey) {
|
||||
$this->cryptographicKey = ClassRegistry::init('CryptographicKey');
|
||||
}
|
||||
$signature = $this->cryptographicKey->signWithInstanceKey($data);
|
||||
if (empty($signature)) {
|
||||
throw new Exception(__("Invalid signing key. This should never happen."));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
class TmpFileTool
|
||||
{
|
||||
/** @var resource */
|
||||
/** @var resource|null */
|
||||
private $tmpfile;
|
||||
|
||||
/** @var string */
|
||||
private $separator;
|
||||
|
||||
/**
|
||||
* @param int $maxInMemory How many bytes should keep in memory before creating file on disk. By default is is 2 MB.
|
||||
* @param int $maxInMemory How many bytes should keep in memory before creating file on disk. By default is is 5 MB.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($maxInMemory = null)
|
||||
|
@ -88,7 +88,7 @@ class TmpFileTool
|
|||
* @param string $delimiter
|
||||
* @param string $enclosure
|
||||
* @param string $escape
|
||||
* @return Generator
|
||||
* @return Generator<array>
|
||||
* @throws Exception
|
||||
*/
|
||||
public function intoParsedCsv($delimiter = ',', $enclosure = '"', $escape = "\\")
|
||||
|
@ -144,20 +144,17 @@ class TmpFileTool
|
|||
}
|
||||
|
||||
/**
|
||||
* @param boolean $close
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function intoString($close = true)
|
||||
public function intoString()
|
||||
{
|
||||
$this->rewind();
|
||||
$string = stream_get_contents($this->tmpfile);
|
||||
if ($string === false) {
|
||||
throw new Exception('Could not read from temporary file.');
|
||||
}
|
||||
if ($close) {
|
||||
$this->close();
|
||||
}
|
||||
$this->close();
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
@ -175,6 +172,16 @@ class TmpFileTool
|
|||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource
|
||||
* @throws Exception
|
||||
*/
|
||||
public function resource()
|
||||
{
|
||||
$this->rewind();
|
||||
return $this->tmpfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws Exception
|
||||
|
|
|
@ -51,6 +51,9 @@ class AppModel extends Model
|
|||
{
|
||||
parent::__construct($id, $table, $ds);
|
||||
$this->findMethods['column'] = true;
|
||||
if (in_array('phar', stream_get_wrappers())) {
|
||||
stream_wrapper_unregister('phar');
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated, use $db_changes
|
||||
|
@ -2585,6 +2588,7 @@ class AppModel extends Model
|
|||
App::uses('KafkaPubTool', 'Tools');
|
||||
$kafkaPubTool = new KafkaPubTool();
|
||||
$rdkafkaIni = Configure::read('Plugin.Kafka_rdkafka_config');
|
||||
$rdkafkaIni = mb_ereg_replace("/\:\/\//", '', $rdkafkaIni);
|
||||
$kafkaConf = array();
|
||||
if (!empty($rdkafkaIni)) {
|
||||
$kafkaConf = parse_ini_file($rdkafkaIni);
|
||||
|
@ -2780,7 +2784,7 @@ class AppModel extends Model
|
|||
* @return array[]
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function setupSyncRequest(array $server, $model = 'Server')
|
||||
public function setupSyncRequest(array $server, $model = 'Server')
|
||||
{
|
||||
$version = implode('.', $this->checkMISPVersion());
|
||||
$commit = $this->checkMIPSCommit();
|
||||
|
@ -3197,16 +3201,7 @@ class AppModel extends Model
|
|||
*/
|
||||
public function jsonDecode($json)
|
||||
{
|
||||
if (defined('JSON_THROW_ON_ERROR')) {
|
||||
// JSON_THROW_ON_ERROR is supported since PHP 7.3
|
||||
$decoded = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
|
||||
} else {
|
||||
$decoded = json_decode($json, true);
|
||||
if ($decoded === null) {
|
||||
throw new UnexpectedValueException('Could not parse JSON: ' . json_last_error_msg(), json_last_error());
|
||||
}
|
||||
}
|
||||
|
||||
$decoded = JsonTool::decode($json);
|
||||
if (!is_array($decoded)) {
|
||||
throw new UnexpectedValueException('JSON must be array type, get ' . gettype($decoded));
|
||||
}
|
||||
|
|
|
@ -1023,7 +1023,7 @@ class Attribute extends AppModel
|
|||
'order' => false,
|
||||
'limit' => 11,
|
||||
'flatten' => 1,
|
||||
'contain' => ['AttributeTag' => false],
|
||||
'contain' => ['AttributeTag' => false, 'Object' => false],
|
||||
);
|
||||
$resultArray[$key]['related'] = $this->fetchAttributes($user, $options);
|
||||
}
|
||||
|
@ -3154,6 +3154,7 @@ class Attribute extends AppModel
|
|||
}
|
||||
$simple_params = array(
|
||||
'Attribute' => array(
|
||||
'sharinggroup' => array('function' => 'set_filter_sharing_group'),
|
||||
'value' => array('function' => 'set_filter_value'),
|
||||
'category' => array('function' => 'set_filter_simple_attribute'),
|
||||
'type' => array('function' => 'set_filter_type'),
|
||||
|
@ -3169,6 +3170,7 @@ class Attribute extends AppModel
|
|||
'comment' => array('function' => 'set_filter_comment')
|
||||
),
|
||||
'Event' => array(
|
||||
'sharinggroup' => array('function' => 'set_filter_sharing_group'),
|
||||
'eventid' => array('function' => 'set_filter_eventid'),
|
||||
'eventinfo' => array('function' => 'set_filter_eventinfo'),
|
||||
'ignore' => array('function' => 'set_filter_ignore'),
|
||||
|
|
|
@ -272,7 +272,7 @@ class AuditLog extends AppModel
|
|||
if ($title) {
|
||||
$entry .= " -- $title";
|
||||
}
|
||||
$this->syslog->write('info', $entry);
|
||||
$this->syslog->write(LOG_INFO, $entry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('RandomTool', 'Tools');
|
||||
App::uses('CidrTool', 'Tools');
|
||||
App::uses('JsonTool', 'Tools');
|
||||
App::uses('BlowfishConstantPasswordHasher', 'Controller/Component/Auth');
|
||||
|
||||
/**
|
||||
|
@ -15,9 +13,10 @@ class AuthKey extends AppModel
|
|||
public $actsAs = array(
|
||||
'AuditLog',
|
||||
'SysLogLogable.SysLogLogable' => array(
|
||||
'userModel' => 'User',
|
||||
'userKey' => 'user_id',
|
||||
'change' => 'full'),
|
||||
'userModel' => 'User',
|
||||
'userKey' => 'user_id',
|
||||
'change' => 'full'
|
||||
),
|
||||
'Containable',
|
||||
);
|
||||
|
||||
|
@ -25,9 +24,20 @@ class AuthKey extends AppModel
|
|||
'User'
|
||||
);
|
||||
|
||||
public $authkey_raw = false;
|
||||
public $validate = [
|
||||
'uuid' => [
|
||||
'rule' => 'uuid',
|
||||
'message' => 'Please provide a valid RFC 4122 UUID',
|
||||
],
|
||||
'user_id' => [
|
||||
'rule' => 'userExists',
|
||||
'message' => 'User doesn\'t exists',
|
||||
],
|
||||
'read_only' => [
|
||||
'rule' => 'boolean',
|
||||
],
|
||||
];
|
||||
|
||||
// massage the data before we send it off for validation before saving anything
|
||||
public function beforeValidate($options = array())
|
||||
{
|
||||
if (empty($this->data['AuthKey']['id'])) {
|
||||
|
@ -35,16 +45,14 @@ class AuthKey extends AppModel
|
|||
$this->data['AuthKey']['uuid'] = CakeText::uuid();
|
||||
}
|
||||
if (empty($this->data['AuthKey']['authkey'])) {
|
||||
$authkey = (new RandomTool())->random_str(true, 40);
|
||||
$authkey = RandomTool::random_str(true, 40);
|
||||
} else {
|
||||
$authkey = $this->data['AuthKey']['authkey'];
|
||||
}
|
||||
$passwordHasher = $this->getHasher();
|
||||
$this->data['AuthKey']['authkey'] = $passwordHasher->hash($authkey);
|
||||
$this->data['AuthKey']['authkey'] = $this->getHasher()->hash($authkey);
|
||||
$this->data['AuthKey']['authkey_start'] = substr($authkey, 0, 4);
|
||||
$this->data['AuthKey']['authkey_end'] = substr($authkey, -4);
|
||||
$this->data['AuthKey']['authkey_raw'] = $authkey;
|
||||
$this->authkey_raw = $authkey;
|
||||
}
|
||||
|
||||
if (!empty($this->data['AuthKey']['allowed_ips'])) {
|
||||
|
@ -54,6 +62,7 @@ class AuthKey extends AppModel
|
|||
if (empty($allowedIps)) {
|
||||
$allowedIps = [];
|
||||
} else {
|
||||
// Split by new line char or by comma
|
||||
$allowedIps = preg_split('/([\n,])/', $allowedIps);
|
||||
$allowedIps = array_map('trim', $allowedIps);
|
||||
}
|
||||
|
@ -336,6 +345,16 @@ class AuthKey extends AppModel
|
|||
$this->User->updateAll(['date_modified' => time()], ['User.id' => $userId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation
|
||||
* @param array $check
|
||||
* @return bool
|
||||
*/
|
||||
public function userExists(array $check)
|
||||
{
|
||||
return $this->User->hasAny(['id' => $check['user_id']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractPasswordHasher
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,9 @@ class CryptographicKey extends AppModel
|
|||
|
||||
public $validate = [];
|
||||
|
||||
/** @var CryptGpgExtended|null */
|
||||
private $gpg;
|
||||
|
||||
public function __construct($id = false, $table = null, $ds = null)
|
||||
{
|
||||
parent::__construct($id, $table, $ds);
|
||||
|
@ -44,6 +47,12 @@ class CryptographicKey extends AppModel
|
|||
$this->gpg = null;
|
||||
}
|
||||
$this->validate = [
|
||||
'uuid' => [
|
||||
'uuid' => [
|
||||
'rule' => 'uuid',
|
||||
'message' => 'Please provide a valid RFC 4122 UUID',
|
||||
],
|
||||
],
|
||||
'type' => [
|
||||
'rule' => ['inList', $this->validTypes],
|
||||
'message' => __('Invalid key type'),
|
||||
|
@ -76,16 +85,32 @@ class CryptographicKey extends AppModel
|
|||
$this->data['CryptographicKey']['uuid'] = CakeText::uuid();
|
||||
$this->data['CryptographicKey']['fingerprint'] = $this->extractKeyData($this->data['CryptographicKey']['type'], $this->data['CryptographicKey']['key_data']);
|
||||
}
|
||||
$existingKeyForObject = $this->find('first', [
|
||||
'recursive'
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Instance key fingerprint
|
||||
* @throws Crypt_GPG_BadPassphraseException
|
||||
* @throws Crypt_GPG_Exception
|
||||
*/
|
||||
public function ingestInstanceKey()
|
||||
{
|
||||
// If instance just key stored just in GPG homedir, use that key.
|
||||
if (Configure::read('MISP.download_gpg_from_homedir')) {
|
||||
if (!$this->gpg) {
|
||||
throw new Exception("Could not initiate GPG");
|
||||
}
|
||||
/** @var Crypt_GPG_Key[] $keys */
|
||||
$keys = $this->gpg->getKeys(Configure::read('GnuPG.email'));
|
||||
if (empty($keys)) {
|
||||
return false;
|
||||
}
|
||||
$this->gpg->addSignKey($keys[0], Configure::read('GnuPG.password'));
|
||||
return $keys[0]->getPrimaryKey()->getFingerprint();
|
||||
}
|
||||
|
||||
try {
|
||||
$redis = $this->setupRedis();
|
||||
$redis = $this->setupRedisWithException();
|
||||
} catch (Exception $e) {
|
||||
$redis = false;
|
||||
}
|
||||
|
@ -123,25 +148,29 @@ class CryptographicKey extends AppModel
|
|||
return $fingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return false|string
|
||||
* @throws Crypt_GPG_BadPassphraseException
|
||||
* @throws Crypt_GPG_Exception
|
||||
* @throws Crypt_GPG_KeyNotFoundException
|
||||
*/
|
||||
public function signWithInstanceKey($data)
|
||||
{
|
||||
if (!$this->ingestInstanceKey()) {
|
||||
return false;
|
||||
}
|
||||
$data = preg_replace("/\s+/", "", $data);
|
||||
$signature = $this->gpg->sign($data, Crypt_GPG::SIGN_MODE_DETACHED);
|
||||
return $signature;
|
||||
}
|
||||
|
||||
public function signFileWithInstanceKey($path)
|
||||
{
|
||||
if (!$this->ingestInstanceKey()) {
|
||||
return false;
|
||||
}
|
||||
$signature = $this->gpg->signFile($path, Crypt_GPG::SIGN_MODE_DETACHED);
|
||||
$signature = $this->gpg->sign($data, Crypt_GPG::SIGN_MODE_DETACHED, Crypt_GPG::ARMOR_BINARY);
|
||||
return $signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @param string $signature
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function verifySignature($data, $signature, $key)
|
||||
{
|
||||
$this->error = false;
|
||||
|
@ -217,20 +246,15 @@ class CryptographicKey extends AppModel
|
|||
|
||||
public function uniqueKeyForElement($data)
|
||||
{
|
||||
$existingKey = $this->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'parent_type' => $this->data['CryptographicKey']['parent_type'],
|
||||
'parent_id' => $this->data['CryptographicKey']['parent_id'],
|
||||
'key_data' => $this->data['CryptographicKey']['key_data'],
|
||||
'type' => $this->data['CryptographicKey']['type']
|
||||
],
|
||||
'fields' => ['id']
|
||||
return !$this->hasAny([
|
||||
'parent_type' => $this->data['CryptographicKey']['parent_type'],
|
||||
'parent_id' => $this->data['CryptographicKey']['parent_id'],
|
||||
'key_data' => $this->data['CryptographicKey']['key_data'],
|
||||
'type' => $this->data['CryptographicKey']['type'],
|
||||
]);
|
||||
return empty($existingKey);
|
||||
}
|
||||
|
||||
public function validateProtectedEvent($raw_data, $user, $pgp_signature, $event)
|
||||
public function validateProtectedEvent($raw_data, array $user, $pgp_signature, array $event)
|
||||
{
|
||||
$eventCryptoGraphicKey = [];
|
||||
if (!empty($event['Event']['CryptographicKey'])) { // Depending if $event comes from fetchEvent or from pushed data
|
||||
|
@ -240,8 +264,7 @@ class CryptographicKey extends AppModel
|
|||
}
|
||||
if (empty($eventCryptoGraphicKey)) {
|
||||
$message = __('No valid signatures found for validating the signature.');
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->createLogEntry($user, 'validateSig', 'Event', $event['Event']['id'], $message);
|
||||
$this->loadLog()->createLogEntry($user, 'validateSig', 'Event', $event['Event']['id'], $message);
|
||||
return false;
|
||||
}
|
||||
foreach ($eventCryptoGraphicKey as $supplied_key) {
|
||||
|
@ -249,19 +272,26 @@ class CryptographicKey extends AppModel
|
|||
return true;
|
||||
}
|
||||
}
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$message = __('Could not validate the signature.');
|
||||
$this->Log->createLogEntry($user, 'validateSig', 'Event', $event['Event']['id'], $message);
|
||||
$this->loadLog()->createLogEntry($user, 'validateSig', 'Event', $event['Event']['id'], $message);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function captureCryptographicKeyUpdate($user, $cryptographicKeys, $parent_id, $type)
|
||||
/**
|
||||
* @param array $user
|
||||
* @param array $cryptographicKeys
|
||||
* @param int $parent_id
|
||||
* @param string $type
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function captureCryptographicKeyUpdate(array $user, array $cryptographicKeys, $parent_id, $type)
|
||||
{
|
||||
$existingKeys = $this->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'parent_type' => $type,
|
||||
'parent_id' => $parent_id
|
||||
'parent_id' => $parent_id,
|
||||
],
|
||||
'fields' => [
|
||||
'id',
|
||||
|
@ -269,15 +299,14 @@ class CryptographicKey extends AppModel
|
|||
'parent_type',
|
||||
'parent_id',
|
||||
'revoked',
|
||||
'fingerprint'
|
||||
'fingerprint',
|
||||
]
|
||||
]);
|
||||
$toRemove = [];
|
||||
$results = ['add' => [], 'remove' => []];
|
||||
foreach ($existingKeys as $k => $existingKey) {
|
||||
foreach ($existingKeys as $existingKey) {
|
||||
foreach ($cryptographicKeys as $k2 => $cryptographicKey) {
|
||||
if ($existingKey['fingerprint'] === $cryptographicKey['fingerprint']) {
|
||||
$found = true;
|
||||
if ($cryptographicKey['revoked'] && !$existingKey['CryptographicKey']['revoked']) {
|
||||
$existingKey['CryptographicKey']['revoked'] = 1;
|
||||
$this->save($existingKey['CryptographicKey']);
|
||||
|
@ -314,7 +343,6 @@ class CryptographicKey extends AppModel
|
|||
$parent_id
|
||||
);
|
||||
$this->deleteAll(['CryptographicKey.id' => $toRemove]);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->createLogEntry($user, 'updateCryptoKeys', $cryptographicKey['parent_type'], $cryptographicKey['parent_id'], $message);
|
||||
$this->loadLog()->createLogEntry($user, 'updateCryptoKeys', $cryptographicKey['parent_type'], $cryptographicKey['parent_id'], $message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,8 +94,6 @@ class Event extends AppModel
|
|||
|
||||
public $shortDist = array(0 => 'Organisation', 1 => 'Community', 2 => 'Connected', 3 => 'All', 4 => ' sharing Group');
|
||||
|
||||
public $export_types = [];
|
||||
|
||||
public $validFormats = array(
|
||||
'attack' => array('html', 'AttackExport', 'html'),
|
||||
'attack-sightings' => array('json', 'AttackSightingsExport', 'json'),
|
||||
|
@ -301,118 +299,6 @@ class Event extends AppModel
|
|||
]
|
||||
);
|
||||
|
||||
public function __construct($id = false, $table = null, $ds = null)
|
||||
{
|
||||
parent::__construct($id, $table, $ds);
|
||||
|
||||
$this->export_types = array(
|
||||
'json' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'JSON',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 0,
|
||||
'params' => array('includeAttachments' => 1, 'ignore' => 1, 'returnFormat' => 'json'),
|
||||
'description' => __('Click this to download all events and attributes that you have access to in MISP JSON format.'),
|
||||
),
|
||||
'xml' => array(
|
||||
'extension' => '.xml',
|
||||
'type' => 'XML',
|
||||
'scope' => 'Event',
|
||||
'params' => array('includeAttachments' => 1, 'ignore' => 1, 'returnFormat' => 'xml'),
|
||||
'requiresPublished' => 0,
|
||||
'description' => __('Click this to download all events and attributes that you have access to in MISP XML format.'),
|
||||
),
|
||||
'csv_sig' => array(
|
||||
'extension' => '.csv',
|
||||
'type' => 'CSV_Sig',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('published' => 1, 'to_ids' => 1, 'returnFormat' => 'csv'),
|
||||
'description' => __('Click this to download all attributes that are indicators and that you have access to (except file attachments) in CSV format.'),
|
||||
),
|
||||
'csv_all' => array(
|
||||
'extension' => '.csv',
|
||||
'type' => 'CSV_All',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 0,
|
||||
'params' => array('ignore' => 1, 'returnFormat' => 'csv'),
|
||||
'description' => __('Click this to download all attributes that you have access to (except file attachments) in CSV format.'),
|
||||
),
|
||||
'suricata' => array(
|
||||
'extension' => '.rules',
|
||||
'type' => 'Suricata',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'suricata'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Suricata rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'snort' => array(
|
||||
'extension' => '.rules',
|
||||
'type' => 'Snort',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'snort'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Snort rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'bro' => array(
|
||||
'extension' => '.intel',
|
||||
'type' => 'Bro',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'bro'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Bro rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'stix' => array(
|
||||
'extension' => '.xml',
|
||||
'type' => 'STIX',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'stix', 'includeAttachments' => 1),
|
||||
'description' => __('Click this to download a STIX document containing the STIX version of all events and attributes that you have access to.')
|
||||
),
|
||||
'stix2' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'STIX2',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'stix2', 'includeAttachments' => 1),
|
||||
'description' => __('Click this to download a STIX2 document containing the STIX2 version of all events and attributes that you have access to.')
|
||||
),
|
||||
'rpz' => array(
|
||||
'extension' => '.txt',
|
||||
'type' => 'RPZ',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'rpz'),
|
||||
'description' => __('Click this to download an RPZ Zone file generated from all ip-src/ip-dst, hostname, domain attributes. This can be useful for DNS level firewalling. Only published events and attributes marked as IDS Signature are exported.')
|
||||
),
|
||||
'text' => array(
|
||||
'extension' => '.txt',
|
||||
'type' => 'TEXT',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'text', 'includeAttachments' => 1),
|
||||
'description' => __('Click on one of the buttons below to download all the attributes with the matching type. This list can be used to feed forensic software when searching for susipicious files. Only published events and attributes marked as IDS Signature are exported.')
|
||||
),
|
||||
'yara' => array(
|
||||
'extension' => '.yara',
|
||||
'type' => 'Yara',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'yara'),
|
||||
'description' => __('Click this to download Yara rules generated from all relevant attributes.')
|
||||
),
|
||||
'yara-json' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'Yara',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'yara-json'),
|
||||
'description' => __('Click this to download Yara rules generated from all relevant attributes. Rules are returned in a JSON format with information about origin (generated or parsed) and validity.')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private $assetCache = [];
|
||||
|
||||
public function beforeDelete($cascade = true)
|
||||
|
@ -2667,6 +2553,19 @@ class Event extends AppModel
|
|||
return $container;
|
||||
}
|
||||
|
||||
public function set_filter_sharing_group(&$params, $conditions, $options)
|
||||
{
|
||||
if (!empty($params['sharinggroup'])) {
|
||||
$params['sharinggroup'] = $this->convert_filters($params['sharinggroup']);
|
||||
if ($options['scope'] === 'Attribute') {
|
||||
$conditions = $this->generic_add_filter($conditions, $params['sharinggroup'], ['Event.sharing_group_id', 'Attribute.sharing_group_id']);
|
||||
} else {
|
||||
$conditions = $this->generic_add_filter($conditions, $params['sharinggroup'], 'Event.sharing_group_id');
|
||||
}
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
public function set_filter_org(&$params, $conditions, $options)
|
||||
{
|
||||
if (!empty($params['org'])) {
|
||||
|
@ -5581,7 +5480,7 @@ class Event extends AppModel
|
|||
}
|
||||
$this->Warninglist = ClassRegistry::init('Warninglist');
|
||||
$complexTypeTool->setTLDs($this->Warninglist->fetchTLDLists());
|
||||
$freetextResults = array_merge($freetextResults, $complexTypeTool->checkComplexRouter($value, 'FreeText'));
|
||||
$freetextResults = array_merge($freetextResults, $complexTypeTool->checkFreeText($value));
|
||||
if (!empty($freetextResults)) {
|
||||
foreach ($freetextResults as &$ft) {
|
||||
$temp = array();
|
||||
|
@ -6772,7 +6671,7 @@ class Event extends AppModel
|
|||
return $attribute_save;
|
||||
}
|
||||
|
||||
public function processFreeTextDataRouter($user, $attributes, $id, $default_comment = '', $proposals = false, $adhereToWarninglists = false, $returnRawResults = false)
|
||||
public function processFreeTextDataRouter(array $user, array $attributes, $id, $default_comment = '', $proposals = false, $adhereToWarninglists = false, $returnRawResults = false)
|
||||
{
|
||||
if (Configure::read('MISP.background_jobs') && count($attributes) > 5) { // on background process just big attributes batch
|
||||
/** @var Job $job */
|
||||
|
@ -7588,4 +7487,118 @@ class Event extends AppModel
|
|||
$banStatus['message'] = __('Emailing republishing ban setting is not enabled');
|
||||
return $banStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @deprecated
|
||||
*/
|
||||
public function exportTypes()
|
||||
{
|
||||
return array(
|
||||
'json' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'JSON',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 0,
|
||||
'params' => array('includeAttachments' => 1, 'ignore' => 1, 'returnFormat' => 'json'),
|
||||
'description' => __('Click this to download all events and attributes that you have access to in MISP JSON format.'),
|
||||
),
|
||||
'xml' => array(
|
||||
'extension' => '.xml',
|
||||
'type' => 'XML',
|
||||
'scope' => 'Event',
|
||||
'params' => array('includeAttachments' => 1, 'ignore' => 1, 'returnFormat' => 'xml'),
|
||||
'requiresPublished' => 0,
|
||||
'description' => __('Click this to download all events and attributes that you have access to in MISP XML format.'),
|
||||
),
|
||||
'csv_sig' => array(
|
||||
'extension' => '.csv',
|
||||
'type' => 'CSV_Sig',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('published' => 1, 'to_ids' => 1, 'returnFormat' => 'csv'),
|
||||
'description' => __('Click this to download all attributes that are indicators and that you have access to (except file attachments) in CSV format.'),
|
||||
),
|
||||
'csv_all' => array(
|
||||
'extension' => '.csv',
|
||||
'type' => 'CSV_All',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 0,
|
||||
'params' => array('ignore' => 1, 'returnFormat' => 'csv'),
|
||||
'description' => __('Click this to download all attributes that you have access to (except file attachments) in CSV format.'),
|
||||
),
|
||||
'suricata' => array(
|
||||
'extension' => '.rules',
|
||||
'type' => 'Suricata',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'suricata'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Suricata rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'snort' => array(
|
||||
'extension' => '.rules',
|
||||
'type' => 'Snort',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'snort'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Snort rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'bro' => array(
|
||||
'extension' => '.intel',
|
||||
'type' => 'Bro',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'bro'),
|
||||
'description' => __('Click this to download all network related attributes that you have access to under the Bro rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a allowedlist containing host, domain name and IP numbers to exclude from the NIDS export.'),
|
||||
),
|
||||
'stix' => array(
|
||||
'extension' => '.xml',
|
||||
'type' => 'STIX',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'stix', 'includeAttachments' => 1),
|
||||
'description' => __('Click this to download a STIX document containing the STIX version of all events and attributes that you have access to.')
|
||||
),
|
||||
'stix2' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'STIX2',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'stix2', 'includeAttachments' => 1),
|
||||
'description' => __('Click this to download a STIX2 document containing the STIX2 version of all events and attributes that you have access to.')
|
||||
),
|
||||
'rpz' => array(
|
||||
'extension' => '.txt',
|
||||
'type' => 'RPZ',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'rpz'),
|
||||
'description' => __('Click this to download an RPZ Zone file generated from all ip-src/ip-dst, hostname, domain attributes. This can be useful for DNS level firewalling. Only published events and attributes marked as IDS Signature are exported.')
|
||||
),
|
||||
'text' => array(
|
||||
'extension' => '.txt',
|
||||
'type' => 'TEXT',
|
||||
'scope' => 'Attribute',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'text', 'includeAttachments' => 1),
|
||||
'description' => __('Click on one of the buttons below to download all the attributes with the matching type. This list can be used to feed forensic software when searching for susipicious files. Only published events and attributes marked as IDS Signature are exported.')
|
||||
),
|
||||
'yara' => array(
|
||||
'extension' => '.yara',
|
||||
'type' => 'Yara',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'yara'),
|
||||
'description' => __('Click this to download Yara rules generated from all relevant attributes.')
|
||||
),
|
||||
'yara-json' => array(
|
||||
'extension' => '.json',
|
||||
'type' => 'Yara',
|
||||
'scope' => 'Event',
|
||||
'requiresPublished' => 1,
|
||||
'params' => array('returnFormat' => 'yara-json'),
|
||||
'description' => __('Click this to download Yara rules generated from all relevant attributes. Rules are returned in a JSON format with information about origin (generated or parsed) and validity.')
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,11 @@ class Feed extends AppModel
|
|||
'url_params' => ''
|
||||
];
|
||||
|
||||
const SUPPORTED_URL_PARAM_FILTERS = [
|
||||
'timestamp',
|
||||
'publish_timestamp',
|
||||
];
|
||||
|
||||
const CACHE_DIR = APP . 'tmp' . DS . 'cache' . DS . 'feeds' . DS;
|
||||
|
||||
/*
|
||||
|
@ -126,12 +131,13 @@ class Feed extends AppModel
|
|||
public function urlOrExistingFilepath($fields)
|
||||
{
|
||||
if ($this->isFeedLocal($this->data)) {
|
||||
$path = mb_ereg_replace("/\:\/\//", '', $this->data['Feed']['url']);
|
||||
if ($this->data['Feed']['source_format'] == 'misp') {
|
||||
if (!is_dir($this->data['Feed']['url'])) {
|
||||
if (!is_dir($path)) {
|
||||
return 'For MISP type local feeds, please specify the containing directory.';
|
||||
}
|
||||
} else {
|
||||
if (!file_exists($this->data['Feed']['url'])) {
|
||||
if (!file_exists($path)) {
|
||||
return 'Invalid path or file not found. Make sure that the path points to an existing file that is readable and watch out for typos.';
|
||||
}
|
||||
}
|
||||
|
@ -776,6 +782,10 @@ class Feed extends AppModel
|
|||
}
|
||||
}
|
||||
}
|
||||
$url_params = !empty($filterRules['url_params']) ? $filterRules['url_params'] : [];
|
||||
if (!$this->passesURLParamFilters($url_params, $event['Event'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -813,7 +823,7 @@ class Feed extends AppModel
|
|||
}
|
||||
}
|
||||
if (!$found) {
|
||||
unset($k);
|
||||
unset($events[$k]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -828,14 +838,48 @@ class Feed extends AppModel
|
|||
}
|
||||
}
|
||||
if ($found) {
|
||||
unset($k);
|
||||
unset($events[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$url_params = !empty($filterRules['url_params']) ? $filterRules['url_params'] : [];
|
||||
if (!$this->passesURLParamFilters($url_params, $event)) {
|
||||
unset($events[$k]);
|
||||
}
|
||||
}
|
||||
return $events;
|
||||
}
|
||||
|
||||
private function passesURLParamFilters($url_params, $event): bool
|
||||
{
|
||||
$this->Attribute = ClassRegistry::init('Attribute');
|
||||
if (!empty($url_params['timestamp'])) {
|
||||
$timestamps = $this->Attribute->setTimestampConditions($url_params['timestamp'], [], '', true);
|
||||
if (is_array($timestamps)) {
|
||||
if ($event['timestamp'] < $timestamps[0] || $event['timestamp'] > $timestamps[1]) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($event['timestamp'] < $timestamps) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($url_params['publish_timestamp'])) {
|
||||
$timestamps = $this->Attribute->setTimestampConditions($url_params['publish_timestamp'], [], '', true);
|
||||
if (is_array($timestamps)) {
|
||||
if ($event['timestamp'] < $timestamps[0] || $event['timestamp'] > $timestamps[1]) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($event['timestamp'] < $timestamps) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $feed
|
||||
* @param string $uuid
|
||||
|
@ -997,6 +1041,7 @@ class Feed extends AppModel
|
|||
if ($filterRules === null) {
|
||||
throw new Exception('Could not parse feed filter rules JSON: ' . json_last_error_msg(), json_last_error());
|
||||
}
|
||||
$filterRules['url_params'] = !empty($filterRules['url_params']) ? $this->jsonDecode($filterRules['url_params']) : [];
|
||||
}
|
||||
return $filterRules;
|
||||
}
|
||||
|
@ -1929,6 +1974,7 @@ class Feed extends AppModel
|
|||
private function feedGetUri($feed, $uri, HttpSocket $HttpSocket = null)
|
||||
{
|
||||
if ($this->isFeedLocal($feed)) {
|
||||
$uri = mb_ereg_replace("/\:\/\//", '', $uri);
|
||||
if (file_exists($uri)) {
|
||||
return FileAccessTool::readFromFile($uri);
|
||||
} else {
|
||||
|
|
|
@ -101,6 +101,11 @@ class Galaxy extends AppModel
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $galaxies
|
||||
* @param array $cluster_package
|
||||
* @return array
|
||||
*/
|
||||
private function __getPreExistingClusters(array $galaxies, array $cluster_package)
|
||||
{
|
||||
$temp = $this->GalaxyCluster->find('all', array(
|
||||
|
@ -110,11 +115,7 @@ class Galaxy extends AppModel
|
|||
'recursive' => -1,
|
||||
'fields' => array('version', 'id', 'value', 'uuid')
|
||||
));
|
||||
$existingClusters = [];
|
||||
foreach ($temp as $v) {
|
||||
$existingClusters[$v['GalaxyCluster']['value']] = $v;
|
||||
}
|
||||
return $existingClusters;
|
||||
return array_column(array_column($temp, 'GalaxyCluster'), null, 'value');
|
||||
}
|
||||
|
||||
private function __deleteOutdated(bool $force, array $cluster_package, array $existingClusters)
|
||||
|
@ -132,19 +133,20 @@ class Galaxy extends AppModel
|
|||
} else {
|
||||
$cluster_package['values'][$k]['version'] = 0;
|
||||
}
|
||||
if (!empty($existingClusters[$cluster['value']])) {
|
||||
if ($force || $existingClusters[$cluster['value']]['GalaxyCluster']['version'] < $cluster_package['values'][$k]['version']) {
|
||||
$cluster_ids_to_delete[] = $existingClusters[$cluster['value']]['GalaxyCluster']['id'];
|
||||
$cluster_uuids_to_delete[] = $existingClusters[$cluster['value']]['GalaxyCluster']['uuid'];
|
||||
if (isset($existingClusters[$cluster['value']])) {
|
||||
$existing = $existingClusters[$cluster['value']];
|
||||
if ($force || $existing['version'] < $cluster_package['values'][$k]['version']) {
|
||||
$cluster_ids_to_delete[] = $existing['id'];
|
||||
$cluster_uuids_to_delete[] = $existing['uuid'];
|
||||
} else {
|
||||
unset($cluster_package['values'][$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($cluster_ids_to_delete)) {
|
||||
$this->GalaxyCluster->GalaxyElement->deleteAll(array('GalaxyElement.galaxy_cluster_id' => $cluster_ids_to_delete), false, false);
|
||||
$this->GalaxyCluster->GalaxyClusterRelation->deleteRelations(array('GalaxyClusterRelation.galaxy_cluster_uuid' => $cluster_uuids_to_delete));
|
||||
$this->GalaxyCluster->deleteAll(array('GalaxyCluster.id' => $cluster_ids_to_delete), false, false);
|
||||
$this->GalaxyCluster->GalaxyElement->deleteAll(array('GalaxyElement.galaxy_cluster_id' => $cluster_ids_to_delete), false);
|
||||
$this->GalaxyCluster->GalaxyClusterRelation->deleteAll(array('GalaxyClusterRelation.galaxy_cluster_uuid' => $cluster_uuids_to_delete));
|
||||
$this->GalaxyCluster->deleteAll(array('GalaxyCluster.id' => $cluster_ids_to_delete), false);
|
||||
}
|
||||
return $cluster_package;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ App::uses('TmpFileTool', 'Tools');
|
|||
/**
|
||||
* @property Tag $Tag
|
||||
* @property GalaxyClusterRelation $GalaxyClusterRelation
|
||||
* @property GalaxyElement $GalaxyElement
|
||||
*/
|
||||
class GalaxyCluster extends AppModel
|
||||
{
|
||||
|
@ -108,10 +109,10 @@ class GalaxyCluster extends AppModel
|
|||
if (!isset($cluster['published'])) {
|
||||
$cluster['published'] = false;
|
||||
}
|
||||
if (!isset($cluster['authors']) || $cluster['authors'] === null) {
|
||||
if (!isset($cluster['authors'])) {
|
||||
$cluster['authors'] = '';
|
||||
} elseif (is_array($cluster['authors'])) {
|
||||
$cluster['authors'] = json_encode($cluster['authors']);
|
||||
$cluster['authors'] = JsonTool::encode($cluster['authors']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -120,24 +121,24 @@ class GalaxyCluster extends AppModel
|
|||
{
|
||||
foreach ($results as $k => $result) {
|
||||
if (isset($result[$this->alias]['authors'])) {
|
||||
$results[$k][$this->alias]['authors'] = json_decode($results[$k][$this->alias]['authors'], true);
|
||||
$results[$k][$this->alias]['authors'] = json_decode($result[$this->alias]['authors'], true);
|
||||
}
|
||||
if (isset($result[$this->alias]['distribution']) && $results[$k][$this->alias]['distribution'] != 4) {
|
||||
if (isset($result[$this->alias]['distribution']) && $result[$this->alias]['distribution'] != 4) {
|
||||
unset($results[$k]['SharingGroup']);
|
||||
}
|
||||
if (isset($result[$this->alias]['org_id']) && $results[$k][$this->alias]['org_id'] == 0) {
|
||||
if (isset($result[$this->alias]['org_id']) && $result[$this->alias]['org_id'] == 0) {
|
||||
if (isset($results[$k]['Org'])) {
|
||||
$results[$k]['Org'] = Organisation::GENERIC_MISP_ORGANISATION;
|
||||
}
|
||||
}
|
||||
if (isset($result[$this->alias]['orgc_id']) && $results[$k][$this->alias]['orgc_id'] == 0) {
|
||||
if (isset($result[$this->alias]['orgc_id']) && $result[$this->alias]['orgc_id'] == 0) {
|
||||
if (isset($results[$k]['Orgc'])) {
|
||||
$results[$k]['Orgc'] = Organisation::GENERIC_MISP_ORGANISATION;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($result['GalaxyClusterRelation'])) {
|
||||
foreach ($results[$k]['GalaxyClusterRelation'] as $i => $relation) {
|
||||
foreach ($result['GalaxyClusterRelation'] as $i => $relation) {
|
||||
if (isset($relation['distribution']) && $relation['distribution'] != 4) {
|
||||
unset($results[$k]['GalaxyClusterRelation'][$i]['SharingGroup']);
|
||||
}
|
||||
|
|
|
@ -157,11 +157,6 @@ class GalaxyClusterRelation extends AppModel
|
|||
return array_unique(array_merge($existingRelationships, $objectRelationships));
|
||||
}
|
||||
|
||||
public function deleteRelations($conditions)
|
||||
{
|
||||
$this->deleteAll($conditions, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* saveRelations
|
||||
*
|
||||
|
|
|
@ -43,7 +43,7 @@ class Job extends AppModel
|
|||
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
|
||||
if (in_array($type, array_keys($this->Event->export_types)) && $type !== 'bro') {
|
||||
if (in_array($type, array_keys($this->Event->exportTypes())) && $type !== 'bro') {
|
||||
|
||||
$this->getBackgroundJobsTool()->enqueue(
|
||||
BackgroundJobsTool::CACHE_QUEUE,
|
||||
|
|
|
@ -204,7 +204,7 @@ class Log extends AppModel
|
|||
*/
|
||||
public function createLogEntry($user, $action, $model, $modelId = 0, $title = '', $change = '')
|
||||
{
|
||||
if (in_array($action, ['tag', 'galaxy', 'publish', 'publish_sightings'], true) && Configure::read('MISP.log_new_audit')) {
|
||||
if (in_array($action, ['tag', 'galaxy', 'publish', 'publish_sightings', 'enable'], true) && Configure::read('MISP.log_new_audit')) {
|
||||
return; // Do not store tag changes when new audit is enabled
|
||||
}
|
||||
if ($user === 'SYSTEM') {
|
||||
|
@ -383,13 +383,13 @@ class Log extends AppModel
|
|||
}
|
||||
}
|
||||
if ($this->syslog) {
|
||||
$action = 'info';
|
||||
$action = LOG_INFO;
|
||||
if (isset($data['Log']['action'])) {
|
||||
if (in_array($data['Log']['action'], self::ERROR_ACTIONS, true)) {
|
||||
$action = 'err';
|
||||
$action = LOG_ERR;
|
||||
}
|
||||
if (in_array($data['Log']['action'], self::WARNING_ACTIONS, true)) {
|
||||
$action = 'warning';
|
||||
$action = LOG_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,19 +4,35 @@ App::uses('AppModel', 'Model');
|
|||
class RestClientHistory extends AppModel
|
||||
{
|
||||
public $belongsTo = array(
|
||||
'Org' => array(
|
||||
'className' => 'Organisation',
|
||||
'foreignKey' => 'org_id',
|
||||
'order' => array(),
|
||||
'fields' => array('id', 'name', 'uuid')
|
||||
),
|
||||
'User' => array(
|
||||
'className' => 'User',
|
||||
'foreignKey' => 'user_id',
|
||||
'order' => array(),
|
||||
'fields' => array('id', 'email')
|
||||
),
|
||||
);
|
||||
'Org' => array(
|
||||
'className' => 'Organisation',
|
||||
'foreignKey' => 'org_id',
|
||||
'order' => array(),
|
||||
'fields' => array('id', 'name', 'uuid')
|
||||
),
|
||||
'User' => array(
|
||||
'className' => 'User',
|
||||
'foreignKey' => 'user_id',
|
||||
'order' => array(),
|
||||
'fields' => array('id', 'email')
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @param array $user
|
||||
* @param array $history
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function insert(array $user, array $history)
|
||||
{
|
||||
$history['org_id'] = $user['org_id'];
|
||||
$history['user_id'] = $user['id'];
|
||||
|
||||
$this->create();
|
||||
$this->save($history, ['atomic' => false]);
|
||||
$this->cleanup($user['id']);
|
||||
}
|
||||
|
||||
public function cleanup($user_id)
|
||||
{
|
||||
|
@ -35,6 +51,6 @@ class RestClientHistory extends AppModel
|
|||
'NOT' => array(
|
||||
'RestClientHistory.id' => $keepIds
|
||||
)
|
||||
));
|
||||
), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1980,7 +1980,7 @@ class Server extends AppModel
|
|||
App::uses('Folder', 'Utility');
|
||||
App::uses('File', 'Utility');
|
||||
// delete all cache files
|
||||
foreach ($this->Event->export_types as $type => $settings) {
|
||||
foreach ($this->Event->exportTypes() as $type => $settings) {
|
||||
$dir = new Folder(APP . 'tmp/cached_exports/' . $type);
|
||||
// No caches created for this type of export, move on
|
||||
if ($dir == null) {
|
||||
|
@ -4614,6 +4614,28 @@ class Server extends AppModel
|
|||
return $this->saveMany($toSave, ['validate' => false, 'fields' => ['authkey']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all Attribute and Object types
|
||||
*/
|
||||
public function getAllTypes(): array
|
||||
{
|
||||
$allTypes = [];
|
||||
$this->Attribute = ClassRegistry::init('Attribute');
|
||||
$this->ObjectTemplate = ClassRegistry::init('ObjectTemplate');
|
||||
$objects = $this->ObjectTemplate->find('all', [
|
||||
'recursive' => -1,
|
||||
'fields' => ['uuid', 'name'],
|
||||
'group' => ['uuid', 'name'],
|
||||
]);
|
||||
$allTypes = [
|
||||
'attribute' => array_unique(Hash::extract(Hash::extract($this->Attribute->categoryDefinitions, '{s}.types'), '{n}.{n}')),
|
||||
'object' => Hash::map($objects, '{n}.ObjectTemplate', function ($item) {
|
||||
return ['id' => $item['uuid'], 'name' => sprintf('%s (%s)', $item['name'], $item['uuid'])];
|
||||
})
|
||||
];
|
||||
return $allTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate config.php from php opcode cache
|
||||
*/
|
||||
|
@ -5666,6 +5688,15 @@ class Server extends AppModel
|
|||
'type' => 'boolean',
|
||||
'null' => true,
|
||||
],
|
||||
'download_gpg_from_homedir' => [
|
||||
'level' => self::SETTING_OPTIONAL,
|
||||
'description' => __('Fetch GPG instance key from GPG homedir.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true,
|
||||
'cli_only' => true,
|
||||
],
|
||||
),
|
||||
'GnuPG' => array(
|
||||
'branch' => 1,
|
||||
|
|
|
@ -4,6 +4,7 @@ App::uses('AuthComponent', 'Controller/Component');
|
|||
App::uses('RandomTool', 'Tools');
|
||||
App::uses('GpgTool', 'Tools');
|
||||
App::uses('SendEmail', 'Tools');
|
||||
App::uses('SendEmailTemplate', 'Tools');
|
||||
App::uses('BlowfishConstantPasswordHasher', 'Controller/Component/Auth');
|
||||
|
||||
/**
|
||||
|
@ -832,6 +833,7 @@ class User extends AppModel
|
|||
|
||||
$gpg = $this->initializeGpg();
|
||||
$sendEmail = new SendEmail($gpg);
|
||||
$result = $sendEmail->sendToUser($user, $subject, $body, $bodyNoEnc,$replyToUser ?: []);
|
||||
try {
|
||||
$result = $sendEmail->sendToUser($user, $subject, $body, $bodyNoEnc,$replyToUser ?: []);
|
||||
|
||||
|
@ -867,16 +869,6 @@ class User extends AppModel
|
|||
return true;
|
||||
}
|
||||
|
||||
public function adminMessageResolve($message)
|
||||
{
|
||||
$resolveVars = array('$contact' => 'MISP.contact', '$org' => 'MISP.org', '$misp' => 'MISP.baseurl');
|
||||
foreach ($resolveVars as $k => $v) {
|
||||
$v = Configure::read($v);
|
||||
$message = str_replace($k, $v, $message);
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
* @return array
|
||||
|
@ -955,24 +947,15 @@ class User extends AppModel
|
|||
public function initiatePasswordReset($user, $firstTime = false, $simpleReturn = false, $fixedPassword = false)
|
||||
{
|
||||
$org = Configure::read('MISP.org');
|
||||
$options = array('newUserText', 'passwordResetText');
|
||||
$subjects = array('[' . $org . ' MISP] New user registration', '[' . $org . ' MISP] Password reset');
|
||||
$textToFetch = $options[($firstTime ? 0 : 1)];
|
||||
$subject = $subjects[($firstTime ? 0 : 1)];
|
||||
$this->Server = ClassRegistry::init('Server');
|
||||
$body = Configure::read('MISP.' . $textToFetch);
|
||||
if (!$body) {
|
||||
$body = $this->Server->serverSettings['MISP'][$textToFetch]['value'];
|
||||
}
|
||||
$body = $this->adminMessageResolve($body);
|
||||
if ($fixedPassword) {
|
||||
$password = $fixedPassword;
|
||||
} else {
|
||||
$password = $this->generateRandomPassword();
|
||||
}
|
||||
$body = str_replace('$password', $password, $body);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
$body = str_replace('\n', PHP_EOL, $body);
|
||||
$body = $this->preparePasswordResetEmail($user, $password, $firstTime, $subject);
|
||||
$result = $this->sendEmail($user, $body, false, $subject);
|
||||
if ($result) {
|
||||
$this->id = $user['User']['id'];
|
||||
|
@ -991,6 +974,22 @@ class User extends AppModel
|
|||
}
|
||||
}
|
||||
|
||||
private function preparePasswordResetEmail($user, $password, $firstTime, $subject)
|
||||
{
|
||||
$textToFetch = $firstTime ? 'newUserText': 'passwordResetText';
|
||||
$this->Server = ClassRegistry::init('Server');
|
||||
$bodyTemplate = Configure::read('MISP.' . $textToFetch);
|
||||
if (!$bodyTemplate) {
|
||||
$bodyTemplate = $this->Server->serverSettings['MISP'][$textToFetch]['value'];
|
||||
}
|
||||
$template = new SendEmailTemplate('password_reset');
|
||||
$template->set('body', $bodyTemplate);
|
||||
$template->set('user', $user);
|
||||
$template->set('password', $password);
|
||||
$template->subject($subject);
|
||||
return $template;
|
||||
}
|
||||
|
||||
public function getOrgAdminsForOrg($org_id, $excludeUserId = false)
|
||||
{
|
||||
$adminRoles = $this->Role->find('column', array(
|
||||
|
@ -1223,13 +1222,12 @@ class User extends AppModel
|
|||
}
|
||||
|
||||
// query
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$result = $this->Log->createLogEntry($user, $action, $model, $modelId, $description, $fieldsResult);
|
||||
$result = $this->loadLog()->createLogEntry($user, $action, $model, $modelId, $description, $fieldsResult);
|
||||
|
||||
// write to syslogd as well
|
||||
App::import('Lib', 'SysLog.SysLog');
|
||||
$syslog = new SysLog();
|
||||
$syslog->write('notice', "$description -- $action" . (empty($fieldsResult) ? '' : ' -- ' . $result['Log']['change']));
|
||||
$syslog->write(LOG_NOTICE, "$description -- $action" . (empty($fieldsResult) ? '' : ' -- ' . $result['Log']['change']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -383,7 +383,7 @@ class Warninglist extends AppModel
|
|||
|
||||
$keys = array_keys($list['list']);
|
||||
if ($keys === array_keys($keys)) {
|
||||
foreach (array_chunk($list['list'], 500) as $chunk) {
|
||||
foreach (array_chunk($list['list'], 1000) as $chunk) {
|
||||
$valuesToInsert = [];
|
||||
foreach ($chunk as $value) {
|
||||
if (!empty($value)) {
|
||||
|
@ -393,7 +393,7 @@ class Warninglist extends AppModel
|
|||
$result = $db->insertMulti('warninglist_entries', ['value', 'warninglist_id'], $valuesToInsert);
|
||||
}
|
||||
} else { // import warninglist with comments
|
||||
foreach (array_chunk($list['list'], 500, true) as $chunk) {
|
||||
foreach (array_chunk($list['list'], 1000, true) as $chunk) {
|
||||
$valuesToInsert = [];
|
||||
foreach ($chunk as $value => $comment) {
|
||||
if (!empty($value)) {
|
||||
|
|
|
@ -21,274 +21,275 @@ App::uses('BaseAuthenticate', 'Controller/Component/Auth');
|
|||
|
||||
class CertificateAuthenticate extends BaseAuthenticate
|
||||
{
|
||||
/**
|
||||
* Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $ca;
|
||||
/**
|
||||
* Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $ca;
|
||||
|
||||
/**
|
||||
* Holds the certificate user information (available at SSL_CLIENT_S_DN)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $client;
|
||||
/**
|
||||
* Holds the certificate user information (available at SSL_CLIENT_S_DN)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $client;
|
||||
|
||||
/**
|
||||
* Holds the user information
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $user;
|
||||
/**
|
||||
* Holds the user information
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $user;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* This should only be called once per request, so it doesn't need to store values in
|
||||
* the instance. Simply checks if the certificate is valid (against configured valid issuers)
|
||||
* and returns the user information encoded.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::$ca = self::$client = false;
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* This should only be called once per request, so it doesn't need to store values in
|
||||
* the instance. Simply checks if the certificate is valid (against configured valid issuers)
|
||||
* and returns the user information encoded.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::$ca = self::$client = false;
|
||||
|
||||
if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
|
||||
$CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
|
||||
// only valid CAs, if this was configured
|
||||
if ($ca=Configure::read('CertAuth.ca')) {
|
||||
$k = Configure::read('CertAuth.caId');
|
||||
if (!$k) $k = 'CN';
|
||||
$id = (isset($CA[$k]))?($CA[$k]):(false);
|
||||
if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
|
||||
$CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
|
||||
// only valid CAs, if this was configured
|
||||
if ($ca=Configure::read('CertAuth.ca')) {
|
||||
$k = Configure::read('CertAuth.caId');
|
||||
if (!$k) $k = 'CN';
|
||||
$id = (isset($CA[$k]))?($CA[$k]):(false);
|
||||
|
||||
if (!$id) {
|
||||
$CA = false;
|
||||
} else if (is_array($ca)) {
|
||||
if (!in_array($id, $ca)) $CA = false;
|
||||
} else if ($ca!=$id) {
|
||||
$CA = false;
|
||||
}
|
||||
unset($id, $k);
|
||||
}
|
||||
self::$ca = $CA;
|
||||
unset($CA, $ca);
|
||||
}
|
||||
if (!$id) {
|
||||
$CA = false;
|
||||
} else if (is_array($ca)) {
|
||||
if (!in_array($id, $ca)) $CA = false;
|
||||
} else if ($ca!=$id) {
|
||||
$CA = false;
|
||||
}
|
||||
unset($id, $k);
|
||||
}
|
||||
self::$ca = $CA;
|
||||
unset($CA, $ca);
|
||||
}
|
||||
|
||||
if (self::$ca) {
|
||||
$map = Configure::read('CertAuth.map');
|
||||
if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
|
||||
self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
|
||||
} else {
|
||||
self::$client = array();
|
||||
}
|
||||
foreach($map as $n=>$d) {
|
||||
if(isset($_SERVER[$n])) {
|
||||
self::$client[$d] = $_SERVER[$n];
|
||||
}
|
||||
unset($map[$n], $n, $d);
|
||||
}
|
||||
unset($map);
|
||||
if(!self::$client) {
|
||||
self::$client = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self::$ca) {
|
||||
$map = Configure::read('CertAuth.map');
|
||||
if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
|
||||
self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
|
||||
} else {
|
||||
self::$client = array();
|
||||
}
|
||||
foreach($map as $n=>$d) {
|
||||
if(isset($_SERVER[$n])) {
|
||||
self::$client[$d] = $_SERVER[$n];
|
||||
}
|
||||
unset($map[$n], $n, $d);
|
||||
}
|
||||
unset($map);
|
||||
if(!self::$client) {
|
||||
self::$client = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse certificate extensions
|
||||
*
|
||||
* @TODO this should properly address the RFC
|
||||
* @param string $s text to be parsed
|
||||
* @param (optional) array $map array of mapping extension to User fields
|
||||
* @return array parsed values
|
||||
*/
|
||||
private static function parse($s, $map=null)
|
||||
{
|
||||
$r=array();
|
||||
if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
|
||||
foreach ($m[2] as $i=>$k) {
|
||||
if ($map) {
|
||||
if (isset($map[$k])) {
|
||||
$k = $map[$k];
|
||||
} else {
|
||||
$k = null;
|
||||
}
|
||||
}
|
||||
if ($k) {
|
||||
$v = $m[3][$i];
|
||||
$r[$k] = $v;
|
||||
}
|
||||
unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
/**
|
||||
* Parse certificate extensions
|
||||
*
|
||||
* @TODO this should properly address the RFC
|
||||
* @param string $s text to be parsed
|
||||
* @param (optional) array $map array of mapping extension to User fields
|
||||
* @return array parsed values
|
||||
*/
|
||||
private static function parse($s, $map=null)
|
||||
{
|
||||
$r=array();
|
||||
if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
|
||||
foreach ($m[2] as $i=>$k) {
|
||||
if ($map) {
|
||||
if (isset($map[$k])) {
|
||||
$k = $map[$k];
|
||||
} else {
|
||||
$k = null;
|
||||
}
|
||||
}
|
||||
if ($k) {
|
||||
$v = $m[3][$i];
|
||||
$r[$k] = $v;
|
||||
}
|
||||
unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
// to enable stateless authentication
|
||||
public function getUser(CakeRequest $request)
|
||||
{
|
||||
if (empty(self::$user)) {
|
||||
if (self::$client) {
|
||||
self::$user = self::$client;
|
||||
// If $sync is true, allow the creation of the user from the certificate
|
||||
$sync = Configure::read('CertAuth.syncUser');
|
||||
$url = Configure::read('CertAuth.restApi.url');
|
||||
if ($sync && $url) {
|
||||
if (!self::getRestUser()) return false;
|
||||
}
|
||||
// to enable stateless authentication
|
||||
public function getUser(CakeRequest $request)
|
||||
{
|
||||
if (empty(self::$user)) {
|
||||
if (self::$client) {
|
||||
self::$user = self::$client;
|
||||
// If $sync is true, allow the creation of the user from the certificate
|
||||
$sync = Configure::read('CertAuth.syncUser');
|
||||
$url = Configure::read('CertAuth.restApi.url');
|
||||
if ($sync && $url) {
|
||||
if (!self::getRestUser()) return false;
|
||||
}
|
||||
|
||||
// find and fill user with model
|
||||
$userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
|
||||
$userDefaults = Configure::read('CertAuth.userDefaults');
|
||||
$this->User = ClassRegistry::init('User');
|
||||
if (!empty(self::$user[$userModelKey])) {
|
||||
$existingUser = $this->User->find('first', array(
|
||||
'conditions' => array($userModelKey => self::$user[$userModelKey]),
|
||||
'recursive' => false
|
||||
));
|
||||
}
|
||||
if ($existingUser) {
|
||||
if ($sync) {
|
||||
if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
|
||||
self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
|
||||
// reset user defaults in case it's a different org_id
|
||||
if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
|
||||
if ($userDefaults && is_array($userDefaults)) {
|
||||
self::$user = array_merge($userDefaults + self::$user);
|
||||
}
|
||||
}
|
||||
unset(self::$user['org']);
|
||||
}
|
||||
$write = array();
|
||||
foreach (self::$user as $k => $v) {
|
||||
if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
|
||||
$write[] = $k;
|
||||
$existingUser['User'][$k] = trim($v);
|
||||
}
|
||||
}
|
||||
if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
|
||||
CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
|
||||
}
|
||||
}
|
||||
self::$user = $this->User->getAuthUser($existingUser['User']['id']);
|
||||
if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
|
||||
} else if ($sync && !empty(self::$user)) {
|
||||
$org = isset(self::$client['org']) ? self::$client['org'] : null;
|
||||
if ($org == null) return false;
|
||||
if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
|
||||
self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
|
||||
unset(self::$user['org']);
|
||||
}
|
||||
if ($userDefaults && is_array($userDefaults)) {
|
||||
self::$user = array_merge(self::$user, $userDefaults);
|
||||
}
|
||||
$this->User->create();
|
||||
if ($this->User->save(self::$user)) {
|
||||
$id = $this->User->id;
|
||||
self::$user = $this->User->getAuthUser($id);
|
||||
if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
|
||||
} else {
|
||||
CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
|
||||
}
|
||||
} else {
|
||||
// No match -- User doesn't exist !!!
|
||||
self::$user = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$user;
|
||||
}
|
||||
// find and fill user with model
|
||||
$userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
|
||||
$userDefaults = Configure::read('CertAuth.userDefaults');
|
||||
$this->User = ClassRegistry::init('User');
|
||||
if (!empty(self::$user[$userModelKey])) {
|
||||
$existingUser = $this->User->find('first', array(
|
||||
'conditions' => array($userModelKey => self::$user[$userModelKey]),
|
||||
'recursive' => false
|
||||
));
|
||||
}
|
||||
if ($existingUser) {
|
||||
if ($sync) {
|
||||
if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
|
||||
self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
|
||||
// reset user defaults in case it's a different org_id
|
||||
if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
|
||||
if ($userDefaults && is_array($userDefaults)) {
|
||||
self::$user = array_merge($userDefaults + self::$user);
|
||||
}
|
||||
}
|
||||
unset(self::$user['org']);
|
||||
}
|
||||
$write = array();
|
||||
foreach (self::$user as $k => $v) {
|
||||
if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
|
||||
$write[] = $k;
|
||||
$existingUser['User'][$k] = trim($v);
|
||||
}
|
||||
}
|
||||
if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
|
||||
CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
|
||||
}
|
||||
}
|
||||
self::$user = $this->User->getAuthUser($existingUser['User']['id']);
|
||||
if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
|
||||
} else if ($sync && !empty(self::$user)) {
|
||||
$org = isset(self::$client['org']) ? self::$client['org'] : null;
|
||||
if ($org == null) return false;
|
||||
if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
|
||||
self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
|
||||
unset(self::$user['org']);
|
||||
}
|
||||
if ($userDefaults && is_array($userDefaults)) {
|
||||
self::$user = array_merge(self::$user, $userDefaults);
|
||||
}
|
||||
$this->User->create();
|
||||
if ($this->User->save(self::$user)) {
|
||||
$id = $this->User->id;
|
||||
self::$user = $this->User->getAuthUser($id);
|
||||
if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
|
||||
} else {
|
||||
CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
|
||||
}
|
||||
} else {
|
||||
// No match -- User doesn't exist !!!
|
||||
self::$user = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$user;
|
||||
}
|
||||
|
||||
// to enable stateless authentication
|
||||
public function authenticate(CakeRequest $request, CakeResponse $response)
|
||||
{
|
||||
return self::getUser($request);
|
||||
}
|
||||
// to enable stateless authentication
|
||||
public function authenticate(CakeRequest $request, CakeResponse $response)
|
||||
{
|
||||
return self::getUser($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches user information from external REST API
|
||||
*
|
||||
* Valid options (should be configured under CertAuth.restApi):
|
||||
*
|
||||
* @param (optional) array $options API configuration
|
||||
* url (string) Where to fetch information from
|
||||
* headers (array) list of additional headers to be used, reserved for authentication tokens
|
||||
* params (array) mapping of additional params to be included at the url, uses $user values
|
||||
* map (array) mapping of the return values to be added to the self::$user
|
||||
* @return array updated user object
|
||||
*/
|
||||
public function getRestUser($options=null, $user=null)
|
||||
{
|
||||
if (is_null($options)) {
|
||||
$options = Configure::read('CertAuth.restApi');
|
||||
}
|
||||
if (!is_null($user)) {
|
||||
self::$user = $user;
|
||||
}
|
||||
/**
|
||||
* Fetches user information from external REST API
|
||||
*
|
||||
* Valid options (should be configured under CertAuth.restApi):
|
||||
*
|
||||
* @param (optional) array $options API configuration
|
||||
* url (string) Where to fetch information from
|
||||
* headers (array) list of additional headers to be used, reserved for authentication tokens
|
||||
* params (array) mapping of additional params to be included at the url, uses $user values
|
||||
* map (array) mapping of the return values to be added to the self::$user
|
||||
* @return array updated user object
|
||||
*/
|
||||
public function getRestUser($options=null, $user=null)
|
||||
{
|
||||
if (is_null($options)) {
|
||||
$options = Configure::read('CertAuth.restApi');
|
||||
}
|
||||
if (!is_null($user)) {
|
||||
self::$user = $user;
|
||||
}
|
||||
|
||||
if (!isset($options['url'])) {
|
||||
return null;
|
||||
}
|
||||
if (!isset($options['url'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a stream
|
||||
$req = array(
|
||||
'http'=>array(
|
||||
'method'=>'GET',
|
||||
'header'=>"Accept: application/json\r\n"
|
||||
),
|
||||
);
|
||||
if (isset($options['headers'])) {
|
||||
foreach ($options['headers'] as $k=>$v) {
|
||||
if (is_int($k)) {
|
||||
$req['header'] .= "{$v}\r\n";
|
||||
} else {
|
||||
$req['header'] .= "{$k}: {$v}\r\n";
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
// Create a stream
|
||||
$req = array(
|
||||
'http'=>array(
|
||||
'method'=>'GET',
|
||||
'header'=>"Accept: application/json\r\n"
|
||||
),
|
||||
);
|
||||
if (isset($options['headers'])) {
|
||||
foreach ($options['headers'] as $k=>$v) {
|
||||
if (is_int($k)) {
|
||||
$req['header'] .= "{$v}\r\n";
|
||||
} else {
|
||||
$req['header'] .= "{$k}: {$v}\r\n";
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
$url = $options['url'];
|
||||
if (isset($options['param'])) {
|
||||
foreach ($options['param'] as $k=>$v) {
|
||||
if (isset(self::$user[$v])) {
|
||||
$url .= ((strpos($url, '?'))?('&'):('?'))
|
||||
. $k . '=' . urlencode(self::$user[$v]);
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
$ctx = stream_context_create($req);
|
||||
$a = file_get_contents($url, false, $ctx);
|
||||
if (!$a) return null;
|
||||
$url = $options['url'];
|
||||
if (isset($options['param'])) {
|
||||
foreach ($options['param'] as $k=>$v) {
|
||||
if (isset(self::$user[$v])) {
|
||||
$url .= ((strpos($url, '?'))?('&'):('?'))
|
||||
. $k . '=' . urlencode(self::$user[$v]);
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
$ctx = stream_context_create($req);
|
||||
$url = mb_ereg_replace("/phar\:\/\//i", '', $url);
|
||||
$a = file_get_contents($url, false, $ctx);
|
||||
if (!$a) return null;
|
||||
|
||||
$A = json_decode($a, true);
|
||||
if (!isset($A['data'][0])) {
|
||||
self::$user = false;
|
||||
} else if (isset($options['map'])) {
|
||||
foreach ($options['map'] as $k=>$v) {
|
||||
if (isset($A['data'][0][$k])) {
|
||||
self::$user[$v] = $A['data'][0][$k];
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
$A = json_decode($a, true);
|
||||
if (!isset($A['data'][0])) {
|
||||
self::$user = false;
|
||||
} else if (isset($options['map'])) {
|
||||
foreach ($options['map'] as $k=>$v) {
|
||||
if (isset($A['data'][0][$k])) {
|
||||
self::$user[$v] = $A['data'][0][$k];
|
||||
}
|
||||
unset($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$user;
|
||||
}
|
||||
return self::$user;
|
||||
}
|
||||
|
||||
protected static $instance;
|
||||
protected static $instance;
|
||||
|
||||
public static function ca()
|
||||
{
|
||||
if (is_null(self::$ca)) new CertificateAuthenticate();
|
||||
return self::$ca;
|
||||
}
|
||||
public static function ca()
|
||||
{
|
||||
if (is_null(self::$ca)) new CertificateAuthenticate();
|
||||
return self::$ca;
|
||||
}
|
||||
|
||||
public static function client()
|
||||
{
|
||||
if (is_null(self::$client)) new CertificateAuthenticate();
|
||||
return self::$client;
|
||||
}
|
||||
public static function client()
|
||||
{
|
||||
if (is_null(self::$client)) new CertificateAuthenticate();
|
||||
return self::$client;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ class SysLog
|
|||
* @param array $options Options for the SysLog, see above.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
public function __construct($options = [])
|
||||
{
|
||||
$options += array('ident' => LOGS, 'facility' => LOG_LOCAL0, 'to_stderr' => true);
|
||||
$options += ['ident' => LOGS, 'facility' => LOG_LOCAL0, 'to_stderr' => true];
|
||||
$option = LOG_PID; // include PID with each message
|
||||
if ($options['to_stderr']) {
|
||||
$option |= LOG_PERROR; // print log message also to standard error
|
||||
|
@ -51,7 +51,7 @@ class SysLog
|
|||
/**
|
||||
* Implements writing to the specified syslog
|
||||
*
|
||||
* @param string $type The type of log you are making.
|
||||
* @param int $type The type of log you are making.
|
||||
* @param string $message The message you want to log.
|
||||
* @return boolean success of write.
|
||||
*/
|
||||
|
@ -60,14 +60,9 @@ class SysLog
|
|||
if (!$this->_log) {
|
||||
return false;
|
||||
}
|
||||
$debugTypes = array('notice', 'info', 'debug');
|
||||
$priority = LOG_INFO;
|
||||
if ($type == 'error' || $type == 'warning') {
|
||||
$priority = LOG_ERR;
|
||||
} else if (in_array($type, $debugTypes)) {
|
||||
$priority = LOG_DEBUG;
|
||||
if (!is_int($type)) {
|
||||
throw new InvalidArgumentException("Invalid log type `$type`, must be one of LOG_* constant.");
|
||||
}
|
||||
$output = date('Y-m-d H:i:s') . ' ' . ucfirst($type) . ': ' . $message;
|
||||
return syslog($priority, $output);
|
||||
return syslog($type, $message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
require_once __DIR__ . '/../Lib/Tools/GpgTool.php';
|
||||
require_once __DIR__ . '/../Lib/Tools/TmpFileTool.php';
|
||||
require_once __DIR__ . '/../Lib/Tools/CryptGpgExtended.php';
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class GpgToolTest extends TestCase
|
||||
{
|
||||
public function testInit(): void
|
||||
{
|
||||
$gpg = $this->init();
|
||||
$this->assertInstanceOf('CryptGpgExtended', $gpg);
|
||||
$this->assertIsString($gpg->getVersion());
|
||||
}
|
||||
|
||||
public function testSignAndVerify()
|
||||
{
|
||||
$gpg = $this->init();
|
||||
include __DIR__ . '/../Config/config.php';
|
||||
$gpg->addSignKey($config['GnuPG']['email'], $config['GnuPG']['password']);
|
||||
|
||||
$testString = 'ahojSvete';
|
||||
|
||||
$signature = $gpg->sign($testString, Crypt_GPG::SIGN_MODE_DETACHED, Crypt_GPG::ARMOR_BINARY);
|
||||
$this->assertIsString($signature);
|
||||
|
||||
$verified = $gpg->verify($testString, $signature);
|
||||
$this->assertIsArray($verified);
|
||||
$this->assertCount(1, $verified);
|
||||
$this->assertTrue($verified[0]->isValid());
|
||||
|
||||
$signature = $gpg->sign($testString, Crypt_GPG::SIGN_MODE_DETACHED, Crypt_GPG::ARMOR_ASCII);
|
||||
$this->assertIsString($signature);
|
||||
|
||||
$verified = $gpg->verify($testString, $signature);
|
||||
$this->assertIsArray($verified);
|
||||
$this->assertCount(1, $verified);
|
||||
$this->assertTrue($verified[0]->isValid());
|
||||
|
||||
// Tmp file
|
||||
$tmpFile = new TmpFileTool();
|
||||
$tmpFile->write($testString);
|
||||
$signature = $gpg->signFile($tmpFile, null, Crypt_GPG::SIGN_MODE_DETACHED, Crypt_GPG::ARMOR_BINARY);
|
||||
$this->assertIsString($signature);
|
||||
|
||||
$verified = $gpg->verify($testString, $signature);
|
||||
$this->assertIsArray($verified);
|
||||
$this->assertCount(1, $verified);
|
||||
$this->assertTrue($verified[0]->isValid());
|
||||
}
|
||||
|
||||
private function init(): CryptGpgExtended
|
||||
{
|
||||
require_once 'Crypt/GPG.php';
|
||||
include __DIR__ . '/../Config/config.php';
|
||||
|
||||
$options = [
|
||||
'homedir' => $config['GnuPG']['homedir'],
|
||||
'gpgconf' => $config['GnuPG']['gpgconf'] ?? null,
|
||||
'binary' => $config['GnuPG']['binary'] ?? '/usr/bin/gpg',
|
||||
];
|
||||
return new CryptGpgExtended($options);
|
||||
}
|
||||
}
|
|
@ -35,12 +35,28 @@ class JSONConverterToolTest extends TestCase
|
|||
$this->check($event);
|
||||
}
|
||||
|
||||
public function testCheckJsonIsValidUnicodeSlashes(): void
|
||||
{
|
||||
$attribute = ['id' => 1, 'event_id' => 2, 'type' => 'ip-src', 'value' => '1.1.1.1'];
|
||||
$event = ['Event' => ['id' => 2, 'info' => 'Test event ěšřžýáí \/'], 'errors' => 'chyba ě+š'];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$event['Attribute'][] = $attribute;
|
||||
}
|
||||
$this->check($event);
|
||||
}
|
||||
|
||||
private function check(array $event): void
|
||||
{
|
||||
$json = '';
|
||||
foreach (JSONConverterTool::streamConvert($event) as $part) {
|
||||
$json .= $part;
|
||||
}
|
||||
|
||||
// Check if result is the same without spaces
|
||||
$jsonStreamWithoutSpaces = preg_replace("/\s+/", "", $json);
|
||||
$jsonNormalWithoutSpaces = preg_replace("/\s+/", "", JSONConverterTool::convert($event));
|
||||
$this->assertEquals($jsonNormalWithoutSpaces, $jsonStreamWithoutSpaces);
|
||||
|
||||
if (defined('JSON_THROW_ON_ERROR')) {
|
||||
json_decode($json, true, 512, JSON_THROW_ON_ERROR);
|
||||
$this->assertTrue(true);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="dashboard_element">
|
||||
<h4 class="blue bold">API info</h4>
|
||||
<?php
|
||||
echo '<h4 class="blue bold">API info</h4>';
|
||||
foreach ($api_info as $key => $value) {
|
||||
if (!empty($value)) {
|
||||
if (is_array($value)) {
|
||||
|
@ -30,11 +30,11 @@
|
|||
}
|
||||
$temp[] = $fieldName . $infoHtml;
|
||||
}
|
||||
$value = implode('<br />', $temp);
|
||||
$value = implode('<br>', $temp);
|
||||
} else {
|
||||
$value = h($value);
|
||||
}
|
||||
echo sprintf('<span class=blue>%s</span>:<br /><div style="padding-left:10px;">%s</div>', ucfirst(h($key)), $value);
|
||||
echo sprintf('<span class=blue>%s</span>:<br><div style="padding-left:10px;">%s</div>', ucfirst(h($key)), $value);
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -4,12 +4,12 @@
|
|||
<span id="showQB" class="btn btn-primary useCursorPointer" style="margin: 5px;"><span class="fa fa-wrench"> Query Builder</span></span>
|
||||
<?php
|
||||
$options = '<option value="">None</option>';
|
||||
foreach($allValidApisFormated as $scope => $actions) {
|
||||
$options .= sprintf('<optgroup label="%s">', $scope);
|
||||
foreach($actions as $action) {
|
||||
$options .= sprintf('<option value="%s">%s</option>', $action['url'], $action['action']);
|
||||
}
|
||||
foreach ($allAccessibleApis as $scope => $actions) {
|
||||
$options .= sprintf('<optgroup label="%s">', $scope);
|
||||
foreach ($actions as $action => $url) {
|
||||
$options .= sprintf('<option value="%s">%s</option>', $url, $action);
|
||||
}
|
||||
}
|
||||
echo sprintf('<select id="TemplateSelect">%s</select>', $options);
|
||||
?>
|
||||
<div id="apiInfo" style="margin-top: 15px;"></div>
|
||||
|
@ -63,7 +63,7 @@
|
|||
'class' => 'input-xxlarge'
|
||||
));
|
||||
?>
|
||||
<div class="input clear" style="width:100%;" />
|
||||
<div class="input clear" style="width:100%;"></div>
|
||||
<?php
|
||||
if (!empty(Configure::read('Security.rest_client_enable_arbitrary_urls'))) {
|
||||
echo $this->Form->input('use_full_path', array(
|
||||
|
@ -77,7 +77,7 @@
|
|||
'onChange' => 'toggleRestClientBookmark();'
|
||||
));
|
||||
?>
|
||||
<div class="input clear" style="width:100%;" />
|
||||
<div class="input clear" style="width:100%;"></div>
|
||||
<div id="bookmark-name" style="display:none;">
|
||||
<?php
|
||||
echo $this->Form->input('name', array(
|
||||
|
@ -86,7 +86,7 @@
|
|||
));
|
||||
?>
|
||||
</div>
|
||||
<div class="input clear" style="width:100%;" />
|
||||
<div class="input clear" style="width:100%;"></div>
|
||||
<?php
|
||||
echo $this->Form->input('show_result', array(
|
||||
'label' => __('Show result'),
|
||||
|
@ -157,7 +157,7 @@
|
|||
}
|
||||
echo '</div>';
|
||||
}
|
||||
if (!empty($data['data'])): ?>
|
||||
if (isset($data['data'])): ?>
|
||||
<h3><?= __('Response') ?></h3>
|
||||
<div><span class="bold"><?= __('Queried URL') ?></span>: <?= h($data['url']) ?></div>
|
||||
<div><span class="bold"><?= __('Response code') ?></span>: <?= h($data['code']) ?></div>
|
||||
|
@ -220,18 +220,6 @@
|
|||
)
|
||||
));
|
||||
?>
|
||||
|
||||
<script type="text/javascript">
|
||||
var allValidApis = <?= json_encode($allValidApis); ?>;
|
||||
var fieldsConstraint = <?= json_encode($allValidApisFieldsContraint); ?>;
|
||||
$(function() {
|
||||
populate_rest_history('history');
|
||||
populate_rest_history('bookmark');
|
||||
toggleRestClientBookmark();
|
||||
setupCodeMirror();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.CodeMirror-wrap {
|
||||
border: 1px solid #cccccc;
|
|
@ -51,4 +51,3 @@
|
|||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,12 +1,14 @@
|
|||
<?php
|
||||
if ($field === 'value') {
|
||||
echo $this->element('Events/View/value_field', ['object' => $object['Attribute']]);
|
||||
} elseif ($field === 'timestamp') {
|
||||
echo $this->Time->date($value);
|
||||
} else {
|
||||
if ($value === 'No') {
|
||||
echo '<input type="checkbox" disabled>';
|
||||
} else if ($value === 'Yes') {
|
||||
echo '<input type="checkbox" checked disabled>';
|
||||
} else {
|
||||
echo nl2br(h($value)) . ' ';
|
||||
echo nl2br(h($value), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,9 +320,6 @@ echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'event
|
|||
$('.screenshot').click(function() {
|
||||
screenshotPopup($(this).attr('src'), $(this).attr('title'));
|
||||
});
|
||||
$('.addGalaxy').click(function() {
|
||||
addGalaxyListener(this);
|
||||
});
|
||||
$('.sightings_advanced_add').click(function() {
|
||||
var selected = [];
|
||||
var object_context = $(this).data('object-context');
|
||||
|
@ -338,16 +335,6 @@ echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'event
|
|||
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
|
||||
genericPopup(url, '#popover_box');
|
||||
});
|
||||
$('.correlation-toggle').click(function() {
|
||||
var attribute_id = $(this).data('attribute-id');
|
||||
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
|
||||
return false;
|
||||
});
|
||||
$('.toids-toggle').click(function() {
|
||||
var attribute_id = $(this).data('attribute-id');
|
||||
getPopup(attribute_id, 'attributes', 'toggleToIDS', '', '#confirmation_box');
|
||||
return false;
|
||||
});
|
||||
popoverStartup();
|
||||
$(document).on('click', function(e) {
|
||||
//did not click a popover toggle or popover
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<button class="btn btn-inverse toggle qet" id="galaxies_toggle" data-toggle-type="galaxies">
|
||||
<span class="fas fa-minus" title="<?php echo __('Toggle galaxies');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle galaxies');?>"></span><?php echo __('Galaxy');?>
|
||||
</button>
|
||||
<button class="btn btn-inverse toggle qet" id="eventgraph_toggle" data-toggle-type="eventgraph" onclick="enable_interactive_graph();">
|
||||
<button class="btn btn-inverse toggle qet" id="eventgraph_toggle" data-toggle-type="eventgraph">
|
||||
<span class="fas fa-plus" title="<?php echo __('Toggle Event graph');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle Event graph');?>"></span><?php echo __('Event graph');?>
|
||||
</button>
|
||||
<button class="btn btn-inverse toggle qet" id="eventtimeline_toggle" data-toggle-type="eventtimeline" onclick="enable_timeline();">
|
||||
<button class="btn btn-inverse toggle qet" id="eventtimeline_toggle" data-toggle-type="eventtimeline">
|
||||
<span class="fas fa-plus" title="<?php echo __('Toggle Event timeline');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle Event timeline');?>"></span><?php echo __('Event timeline');?>
|
||||
</button>
|
||||
<button class="btn btn-inverse toggle qet" id="correlationgraph_toggle" data-toggle-type="correlationgraph" data-load-url="<?= $baseurl ?>/events/viewGraph/<?= h($event['Event']['id']) ?>">
|
||||
|
@ -27,10 +27,10 @@
|
|||
<span class="fas fa-minus" title="<?php echo __('Toggle discussions');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle discussions');?>"></span><?php echo __('Discussion');?>
|
||||
</button>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br>
|
||||
<br>
|
||||
<div id="pivots_div">
|
||||
<?php if (sizeOf($allPivots) > 1) echo $this->element('pivot'); ?>
|
||||
<?php if (count($allPivots) > 1) echo $this->element('pivot'); ?>
|
||||
</div>
|
||||
<div id="galaxies_div">
|
||||
<span class="title-section"><?= __('Galaxies') ?></span>
|
||||
|
@ -60,13 +60,12 @@
|
|||
<div id="clusterrelation_div" class="info_container_eventgraph_network" style="display: none;" data-fullscreen="false">
|
||||
</div>
|
||||
<div id="attributes_div">
|
||||
<?php echo $this->element('eventattribute'); ?>
|
||||
<?= $this->element('eventattribute'); ?>
|
||||
</div>
|
||||
<div id="discussions_div">
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var showContext = false;
|
||||
$(function () {
|
||||
<?php
|
||||
if (!Configure::check('MISP.disable_event_locks') || !Configure::read('MISP.disable_event_locks')) {
|
||||
|
@ -77,8 +76,6 @@ $(function () {
|
|||
);
|
||||
}
|
||||
?>
|
||||
popoverStartup();
|
||||
|
||||
$(document.body).tooltip({
|
||||
selector: 'span[title], td[title], time[title]',
|
||||
placement: 'top',
|
||||
|
|
|
@ -3,7 +3,6 @@ $tr_class = '';
|
|||
if (empty($context)) {
|
||||
$context = 'event';
|
||||
}
|
||||
$linkClass = 'blue';
|
||||
if ($event['Event']['id'] != $object['event_id']) {
|
||||
if (!$isSiteAdmin && $event['extensionEvents'][$object['event_id']]['Orgc']['id'] != $me['org_id']) {
|
||||
$mayModify = false;
|
||||
|
@ -32,48 +31,36 @@ if (!empty($k)) {
|
|||
$tr_class .= ' row_' . h($k);
|
||||
}
|
||||
|
||||
$objectId = h($object['id']);
|
||||
$objectId = (int) $object['id'];
|
||||
|
||||
$quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
||||
$quickEdit = function($fieldName) use ($mayModify, $object) {
|
||||
if (!$mayModify) {
|
||||
return ''; // currently it is not supported to create proposals trough quick edit
|
||||
}
|
||||
if ($object['deleted']) {
|
||||
return ''; // deleted attributes are not editable
|
||||
}
|
||||
if ($editScope === 'ShadowAttribute') {
|
||||
return ''; // currently it is not supported to create proposals trough quick edit
|
||||
}
|
||||
if ($fieldName === 'value' && ($object['type'] === 'attachment' || $object['type'] === 'malware-sample')) {
|
||||
return '';
|
||||
}
|
||||
return " onmouseenter=\"quickEditHover(this, '$editScope', '{$object['id']}', '$fieldName', {$event['Event']['id']});\"";
|
||||
return " data-edit-field=\"$fieldName\"";
|
||||
}
|
||||
|
||||
?>
|
||||
<tr id="Attribute_<?= $objectId ?>_tr" class="<?php echo $tr_class; ?>" tabindex="0">
|
||||
<?php
|
||||
if (($mayModify || !empty($extended)) && empty($disable_multi_select)):
|
||||
?>
|
||||
<td style="width:10px;" data-position="<?php echo 'attribute_' . $objectId ?>">
|
||||
<?php
|
||||
if ($mayModify):
|
||||
?>
|
||||
<input id="select_<?= $objectId ?>" class="select_attribute row_checkbox" type="checkbox" data-id="<?= $objectId ?>" aria-label="<?php echo __('Select attribute');?>" />
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<tr id="Attribute_<?= $objectId ?>_tr" data-primary-id="<?= $objectId ?>" class="<?php echo $tr_class; ?>" tabindex="0">
|
||||
<?php if (($mayModify || !empty($extended)) && empty($disable_multi_select)): ?>
|
||||
<td style="width:10px">
|
||||
<?php if ($mayModify):?>
|
||||
<input class="select_attribute" type="checkbox" data-id="<?= $objectId ?>" aria-label="<?php echo __('Select attribute');?>">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<td class="short context hidden">
|
||||
<?= $objectId ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="short context hidden"><?= $objectId ?></td>
|
||||
<td class="short context hidden uuid quickSelect"><?php echo h($object['uuid']); ?></td>
|
||||
<td class="short context hidden">
|
||||
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php echo date('Y-m-d', $object['timestamp']); ?>
|
||||
</td>
|
||||
<td class="short timestamp"><?= $this->Time->date($object['timestamp']) ?></td>
|
||||
<?php
|
||||
if (!empty($extended)):
|
||||
?>
|
||||
|
@ -100,31 +87,24 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
endif;
|
||||
endif;
|
||||
?>
|
||||
|
||||
</td>
|
||||
<td class="short"<?= $quickEdit('category') ?>>
|
||||
<div id="Attribute_<?= $objectId ?>_category_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_category_solid" class="inline-field-solid">
|
||||
<div class="inline-field-solid">
|
||||
<?php echo h($object['category']); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="short"<?= $quickEdit('type') ?>>
|
||||
<?php
|
||||
if (!empty($object['object_relation'])):
|
||||
?>
|
||||
<?php if (!empty($object['object_relation'])):?>
|
||||
<div class="bold"><?php echo h($object['object_relation']); ?>:</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="Attribute_<?= $objectId ?>_type_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_type_solid" class="inline-field-solid">
|
||||
<?php endif; ?>
|
||||
<div class="inline-field-solid">
|
||||
<?php echo h($object['type']); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td id="Attribute_<?= $objectId ?>_container" class="showspaces limitedWidth shortish"<?= $quickEdit('value') ?>>
|
||||
<div id="Attribute_<?= $objectId ?>_value_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_value_solid" class="inline-field-solid">
|
||||
<div class="inline-field-solid">
|
||||
<?php
|
||||
$value = $this->element('/Events/View/value_field', array('object' => $object));
|
||||
if (Configure::read('Plugin.Enrichment_hover_enable') && isset($modules) && isset($modules['hover_type'][$object['type']])) {
|
||||
$commonDataFields = sprintf('data-object-type="Attribute" data-object-id="%s"', $objectId);
|
||||
$spanExtra = Configure::read('Plugin.Enrichment_hover_popover_only') ? '' : sprintf(' class="eventViewAttributeHover" %s', $commonDataFields);
|
||||
|
@ -132,20 +112,19 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
echo sprintf(
|
||||
'<span%s>%s</span> %s',
|
||||
$spanExtra,
|
||||
$this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass)),
|
||||
$value,
|
||||
$popupButton
|
||||
);
|
||||
} else {
|
||||
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
|
||||
echo $value;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div class="attributeTagContainer">
|
||||
<?php echo $this->element(
|
||||
'ajaxTags',
|
||||
array('attributeId' => $object['id'],
|
||||
<?php echo $this->element('ajaxTags', array(
|
||||
'attributeId' => $objectId,
|
||||
'tags' => $object['AttributeTag'],
|
||||
'tagAccess' => ($isSiteAdmin || $mayModify),
|
||||
'localTagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id'] || (int)$me['org_id'] === Configure::read('MISP.host_org_id')),
|
||||
|
@ -160,7 +139,7 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
if (!empty($includeRelatedTags)) {
|
||||
$element = '';
|
||||
if (!empty($object['RelatedTags'])) {
|
||||
$element = $this->element('ajaxAttributeTags', array('attributeId' => $object['id'], 'attributeTags' => $object['RelatedTags'], 'tagAccess' => false));
|
||||
$element = $this->element('ajaxAttributeTags', array('attributeId' => $objectId, 'attributeTags' => $object['RelatedTags'], 'tagAccess' => false));
|
||||
}
|
||||
echo sprintf(
|
||||
'<td class="shortish"><div %s>%s</div></td>',
|
||||
|
@ -169,23 +148,21 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
);
|
||||
}
|
||||
?>
|
||||
<?php $rowId = sprintf('attribute_%s_galaxy', h($objectId)); ?>
|
||||
<td class="short" id="<?= $rowId ?>">
|
||||
<td class="short" id="attribute_<?= $objectId ?>_galaxy">
|
||||
<?php
|
||||
echo $this->element('galaxyQuickViewNew', array(
|
||||
'mayModify' => $mayModify,
|
||||
'isAclTagger' => $isAclTagger,
|
||||
'data' => (!empty($object['Galaxy']) ? $object['Galaxy'] : array()),
|
||||
'event' => $event,
|
||||
'target_id' => $object['id'],
|
||||
'target_id' => $objectId,
|
||||
'target_type' => 'attribute',
|
||||
));
|
||||
?>
|
||||
</td>
|
||||
<td class="showspaces bitwider"<?= $quickEdit('comment') ?>>
|
||||
<div id="Attribute_<?= $objectId ?>_comment_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_comment_solid" class="inline-field-solid">
|
||||
<?php echo nl2br(h($object['comment'])); ?>
|
||||
<div class="inline-field-solid">
|
||||
<?php echo nl2br(h($object['comment']), false); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="short" style="padding-top:3px;">
|
||||
|
@ -195,7 +172,6 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
aria-label="<?php echo __('Toggle correlation');?>"
|
||||
title="<?php echo __('Toggle correlation');?>"
|
||||
type="checkbox"
|
||||
data-attribute-id="<?= $objectId ?>"
|
||||
<?php
|
||||
echo $object['disable_correlation'] ? '' : ' checked';
|
||||
echo ($mayChangeCorrelation && empty($event['Event']['disable_correlation'])) ? '' : ' disabled';
|
||||
|
@ -204,7 +180,7 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
</td>
|
||||
<td class="shortish">
|
||||
<?php
|
||||
if (!empty($event['RelatedAttribute'][$object['id']])) {
|
||||
if (!empty($event['RelatedAttribute'][$objectId])) {
|
||||
echo '<ul class="inline" style="margin:0">';
|
||||
echo $this->element('Events/View/attribute_correlations', array(
|
||||
'scope' => 'Attribute',
|
||||
|
@ -306,20 +282,10 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
</ul>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div id="Attribute_<?= $objectId ?>_to_ids_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_to_ids_solid" class="inline-field-solid">
|
||||
<input type="checkbox" class="toids-toggle" id="toids_toggle_<?= $objectId ?>" data-attribute-id="<?= $objectId ?>" aria-label="<?= __('Toggle IDS flag') ?>" title="<?= __('Toggle IDS flag') ?>"<?= $object['to_ids'] ? ' checked' : ''; ?><?= $mayModify ? '' : ' disabled' ?>>
|
||||
</div>
|
||||
<input type="checkbox" class="toids-toggle" id="toids_toggle_<?= $objectId ?>" aria-label="<?= __('Toggle IDS flag') ?>" title="<?= __('Toggle IDS flag') ?>"<?= $object['to_ids'] ? ' checked' : ''; ?><?= $mayModify ? '' : ' disabled' ?>>
|
||||
</td>
|
||||
<td class="short"<?= $quickEdit('distribution') ?>>
|
||||
<?php
|
||||
$turnRed = '';
|
||||
if ($object['distribution'] == 0) {
|
||||
$turnRed = 'style="color:red"';
|
||||
}
|
||||
?>
|
||||
<div id="Attribute_<?= $objectId ?>_distribution_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Attribute_<?= $objectId ?>_distribution_solid" <?php echo $turnRed; ?> class="inline-field-solid">
|
||||
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
|
||||
<?php
|
||||
if ($object['distribution'] == 4):
|
||||
?>
|
||||
|
@ -342,7 +308,7 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
}
|
||||
if (!empty($includeDecayScore)): ?>
|
||||
<td class="decayingScoreField">
|
||||
<div id="Attribute_<?= $objectId ?>_score_solid" class="inline-field-solid">
|
||||
<div class="inline-field-solid">
|
||||
<?php echo $this->element('DecayingModels/View/attribute_decay_score', array('scope' => 'object', 'object' => $object, 'uselink' => true)); ?>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -354,25 +320,25 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
if ($object['deleted']):
|
||||
if ($isSiteAdmin || $mayModify):
|
||||
?>
|
||||
<span class="fas fa-redo useCursorPointer" title="<?php echo __('Restore attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Restore attribute');?>" onClick="deleteObject('attributes', 'restore', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="i<?php echo __('Permanently delete attribute');?>" onClick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
|
||||
<span class="fas fa-redo useCursorPointer" title="<?php echo __('Restore attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Restore attribute');?>" onclick="deleteObject('attributes', 'restore', '<?= $objectId ?>')"></span>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>')"></span>
|
||||
<?php
|
||||
endif;
|
||||
else:
|
||||
if ($isAclAdd && ($isSiteAdmin || !$mayModify)):
|
||||
if (isset($modules) && isset($modules['types'][$object['type']])):
|
||||
?>
|
||||
<span class="fas fa-asterisk useCursorPointer" role="button" tabindex="0" aria-label="<?php echo __('Query enrichment');?>" onClick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/ShadowAttribute');" title="<?php echo __('Propose enrichment');?>"> </span>
|
||||
<span class="fas fa-asterisk useCursorPointer" role="button" tabindex="0" aria-label="<?php echo __('Query enrichment');?>" onclick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/ShadowAttribute');" title="<?php echo __('Propose enrichment');?>"> </span>
|
||||
<?php
|
||||
endif;
|
||||
if (isset($cortex_modules) && isset($cortex_modules['types'][$object['type']])):
|
||||
?>
|
||||
<span class="icon-eye-open useCursorPointer" title="<?php echo __('Query Cortex');?>" role="button" tabindex="0" aria-label="<?php echo __('Query Cortex');?>" onClick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/ShadowAttribute/Cortex');" title="<?php echo __('Propose enrichment through Cortex');?>"></span>
|
||||
<span class="icon-eye-open useCursorPointer" role="button" tabindex="0" aria-label="<?php echo __('Query Cortex');?>" onclick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/ShadowAttribute/Cortex');" title="<?php echo __('Propose enrichment through Cortex');?>"></span>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<a href="<?php echo $baseurl;?>/shadow_attributes/edit/<?= $objectId ?>" title="<?php echo __('Propose Edit');?>" aria-label="<?php echo __('Propose Edit');?>" class="fa fa-comment useCursorPointer"></a>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Propose Deletion');?>" role="button" tabindex="0" aria-label="Propose deletion" onClick="deleteObject('shadow_attributes', 'delete', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
|
||||
<a href="<?php echo $baseurl;?>/shadow_attributes/edit/<?= $objectId ?>" title="<?php echo __('Propose Edit');?>" aria-label="<?php echo __('Propose Edit');?>" class="fa fa-comment"></a>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Propose Deletion');?>" role="button" tabindex="0" aria-label="Propose deletion" onclick="deleteObject('shadow_attributes', 'delete', '<?= $objectId ?>')"></span>
|
||||
<?php
|
||||
if ($isSiteAdmin):
|
||||
?>
|
||||
|
@ -382,24 +348,24 @@ $quickEdit = function($fieldName) use ($editScope, $object, $event) {
|
|||
if ($isSiteAdmin || $mayModify):
|
||||
if (isset($modules) && isset($modules['types'][$object['type']])):
|
||||
?>
|
||||
<span class="fas fa-asterisk useCursorPointer" onClick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/Attribute');" title="<?php echo __('Add enrichment');?>" role="button" tabindex="0" aria-label="<?php echo __('Add enrichment');?>"> </span>
|
||||
<span class="fas fa-asterisk useCursorPointer" onclick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/Attribute');" title="<?php echo __('Add enrichment');?>" role="button" tabindex="0" aria-label="<?php echo __('Add enrichment');?>"> </span>
|
||||
<?php
|
||||
endif;
|
||||
if (isset($cortex_modules) && isset($cortex_modules['types'][$object['type']])):
|
||||
?>
|
||||
<span class="icon-eye-open useCursorPointer" onClick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/Attribute/Cortex');" title="<?php echo __('Add enrichment');?>" role="button" tabindex="0" aria-label="<?php echo __('Add enrichment via Cortex');?>"></span>
|
||||
<span class="icon-eye-open useCursorPointer" onclick="simplePopup('<?php echo $baseurl;?>/events/queryEnrichment/<?= $objectId ?>/Attribute/Cortex');" title="<?php echo __('Add enrichment');?>" role="button" tabindex="0" aria-label="<?php echo __('Add enrichment via Cortex');?>"></span>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<a href="<?php echo $baseurl;?>/attributes/edit/<?= $objectId ?>" title="<?php echo __('Edit');?>" aria-label="<?php echo __('Edit');?>" class="fa fa-edit useCursorPointer"></a>
|
||||
<a href="<?php echo $baseurl;?>/attributes/edit/<?= $objectId ?>" title="<?php echo __('Edit');?>" aria-label="<?php echo __('Edit');?>" class="fa fa-edit"></a>
|
||||
<?php
|
||||
if (empty($event['Event']['publish_timestamp'])):
|
||||
?>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="i<?php echo __('Permanently delete attribute');?>" onClick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Permanently delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId . '/true'; ?>')"></span>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Soft-delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft-delete attribute');?>" onClick="deleteObject('attributes', 'delete', '<?= $objectId ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
|
||||
<span class="fa fa-trash useCursorPointer" title="<?php echo __('Soft-delete attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft-delete attribute');?>" onclick="deleteObject('attributes', 'delete', '<?= $objectId ?>')"></span>
|
||||
<?php
|
||||
endif;
|
||||
endif;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php
|
||||
$linkClass = 'white';
|
||||
$currentType = 'Object';
|
||||
$tr_class = 'tableHighlightBorderTop borderBlue';
|
||||
if ($event['Event']['id'] != $object['event_id']) {
|
||||
if (!$isSiteAdmin && $event['extensionEvents'][$object['event_id']]['Orgc']['id'] != $me['org_id']) {
|
||||
|
@ -12,8 +10,15 @@
|
|||
if (!empty($k)) {
|
||||
$tr_class .= ' row_' . h($k);
|
||||
}
|
||||
$quickEdit = function($fieldName) use ($mayModify) {
|
||||
if (!$mayModify) {
|
||||
return ''; // without permission it is not possible to edit object
|
||||
}
|
||||
return " data-edit-field=\"$fieldName\"";
|
||||
};
|
||||
$objectId = intval($object['id']);
|
||||
?>
|
||||
<tr id="Object_<?php echo $object['id']; ?>_tr" class="<?php echo $tr_class; ?>" tabindex="0">
|
||||
<tr id="Object_<?= $objectId ?>_tr" data-primary-id="<?= $objectId ?>" class="<?php echo $tr_class; ?>" tabindex="0">
|
||||
<?php
|
||||
if ($mayModify || $extended):
|
||||
?>
|
||||
|
@ -21,16 +26,12 @@
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
<td class="short context hidden">
|
||||
<?php echo h($object['id']); ?>
|
||||
</td>
|
||||
<td class="short context hidden"><?= $objectId ?></td>
|
||||
<td class="short context hidden uuid quickSelect"><?php echo h($object['uuid']); ?></td>
|
||||
<td class="short context hidden">
|
||||
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php echo date('Y-m-d', $object['timestamp']); ?>
|
||||
</td>
|
||||
<td class="short timestamp"><?= $this->Time->date($object['timestamp']) ?></td>
|
||||
<?php
|
||||
if ($extended):
|
||||
?>
|
||||
|
@ -51,13 +52,12 @@
|
|||
endif;
|
||||
endif;
|
||||
?>
|
||||
|
||||
</td>
|
||||
<td colspan="<?= $includeRelatedTags ? 6 : 5 ?>">
|
||||
<span class="bold"><?php echo __('Object name: ');?></span><?php echo h($object['name']);?>
|
||||
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo h($object['id']); ?>_collapsible"></span>
|
||||
<br />
|
||||
<div id="Object_<?php echo $object['id']; ?>_collapsible" class="collapse">
|
||||
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $objectId ?>_collapsible"></span>
|
||||
<br>
|
||||
<div id="Object_<?= $objectId ?>_collapsible" class="collapse">
|
||||
<span class="bold"><?php echo __('UUID');?>: </span><?php echo h($object['uuid']);?><br />
|
||||
<span class="bold"><?php echo __('Meta-category: ');?></span><?php echo h($object['meta-category']);?><br />
|
||||
<span class="bold"><?php echo __('Description: ');?></span><?php echo h($object['description']);?><br />
|
||||
|
@ -77,21 +77,14 @@
|
|||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="showspaces bitwider" onmouseenter="quickEditHover(this, 'Object', '<?php echo $object['id']; ?>', 'comment', <?php echo $event['Event']['id'];?>);">
|
||||
<div id="Object_<?php echo $object['id']; ?>_comment_placeholder" class="inline-field-placeholder"></div>
|
||||
<div id="Object_<?php echo $object['id']; ?>_comment_solid" class="inline-field-solid">
|
||||
<?php echo nl2br(h($object['comment'])); ?>
|
||||
<td class="showspaces bitwider"<?= $quickEdit('comment') ?>>
|
||||
<div class="inline-field-solid">
|
||||
<?= nl2br(h($object['comment']), false); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
</td>
|
||||
<td class="shortish" onmouseenter="quickEditHover(this, 'Object', '<?php echo $object['id']; ?>', 'distribution', <?php echo $event['Event']['id'];?>);">
|
||||
<?php
|
||||
$turnRed = '';
|
||||
if ($object['distribution'] == 0) $turnRed = 'style="color:red"';
|
||||
?>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_distribution_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_distribution_solid'; ?>" <?php echo $turnRed; ?> class="inline-field-solid">
|
||||
<td colspan="4"></td>
|
||||
<td class="shortish"<?= $quickEdit('distribution') ?>>
|
||||
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
|
||||
<?php
|
||||
if ($object['distribution'] == 4):
|
||||
?>
|
||||
|
@ -100,11 +93,10 @@
|
|||
else:
|
||||
echo h($shortDist[$object['distribution']]);
|
||||
endif;
|
||||
?>
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td colspan="2"></td>
|
||||
<?php
|
||||
$paddedFields = array('includeSightingdb', 'includeDecayScore');
|
||||
foreach ($paddedFields as $paddedField) {
|
||||
|
@ -118,29 +110,27 @@
|
|||
if ($mayModify) {
|
||||
if (empty($object['deleted'])) {
|
||||
echo sprintf(
|
||||
'<a href="%s/objects/edit/%s" title="%s" aria-label="%s" class="fa fa-edit white useCursorPointer"></a> ',
|
||||
'<a href="%s/objects/edit/%s" title="%s" aria-label="%s" class="fa fa-edit white"></a> ',
|
||||
$baseurl,
|
||||
h($object['id']),
|
||||
$objectId,
|
||||
__('Edit'),
|
||||
__('Edit')
|
||||
);
|
||||
echo sprintf(
|
||||
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onClick="%2$s"></span>',
|
||||
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onclick="%2$s"></span>',
|
||||
(empty($event['Event']['publish_timestamp']) ? __('Permanently delete object') : __('Soft delete object')),
|
||||
sprintf(
|
||||
'deleteObject(\'objects\', \'delete\', \'%s\', \'%s\');',
|
||||
empty($event['Event']['publish_timestamp']) ? h($object['id']) . '/true' : h($object['id']),
|
||||
h($event['Event']['id'])
|
||||
'deleteObject(\'objects\', \'delete\', \'%s\');',
|
||||
empty($event['Event']['publish_timestamp']) ? $objectId . '/true' : $objectId
|
||||
)
|
||||
);
|
||||
} else {
|
||||
echo sprintf(
|
||||
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onClick="%2$s"></span>',
|
||||
'<span class="fa fa-trash white useCursorPointer" title="%1$s" role="button" tabindex="0" aria-label="%1$s" onclick="%2$s"></span>',
|
||||
__('Permanently delete object'),
|
||||
sprintf(
|
||||
'deleteObject(\'objects\', \'delete\', \'%s\', \'%s\');',
|
||||
h($object['id']) . '/true',
|
||||
h($event['Event']['id'])
|
||||
'deleteObject(\'objects\', \'delete\', \'%s\');',
|
||||
$objectId . '/true'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -161,5 +151,5 @@
|
|||
'child' => $attrKey == $lastElement ? 'last' : true
|
||||
));
|
||||
}
|
||||
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') .'" onclick="popoverPopup(this, ' . h($object['id']) . ', \'objects\', \'quickFetchTemplateWithValidObjectAttributes\')"></span></td></tr>';
|
||||
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') .'" data-popover-popup="' . $baseurl . '/objects/quickFetchTemplateWithValidObjectAttributes/' . $objectId .'"></span></td></tr>';
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
?>
|
||||
<tr id="proposal_<?= $object['id'] ?>_tr" class="<?php echo $tr_class; ?>">
|
||||
<?php if ($mayModify): ?>
|
||||
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
|
||||
<input id = "select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" aria-label="<?php __('Select proposal');?>" data-id="<?php echo $object['id'];?>" />
|
||||
<td style="width:10px">
|
||||
<input class="select_proposal" type="checkbox" aria-label="<?php __('Select proposal');?>" data-id="<?php echo $object['id'];?>">
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="short context hidden">
|
||||
|
@ -50,12 +50,10 @@
|
|||
<?php echo $this->element('/Events/View/seen_field', array('object' => $object)); ?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_timestamp_solid'; ?>">
|
||||
<?php
|
||||
if (isset($object['timestamp'])) echo date('Y-m-d', $object['timestamp']);
|
||||
if (isset($object['timestamp'])) echo $this->Time->date($object['timestamp']);
|
||||
else echo ' ';
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<?php
|
||||
if ($extended):
|
||||
|
@ -74,32 +72,18 @@
|
|||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_category_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_category_solid'; ?>" class="inline-field-solid">
|
||||
<?php echo h($object['category']); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_type_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_type_solid'; ?>" class="inline-field-solid">
|
||||
<?php echo h($object['type']); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td id="<?php echo h($currentType) . '_' . h($object['id']) . '_container'; ?>" class="showspaces limitedWidth shortish">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_value_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType; ?>_<?php echo $object['id']; ?>_value_solid" class="inline-field-solid">
|
||||
<?php
|
||||
echo $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass));
|
||||
?>
|
||||
</div>
|
||||
<?= $this->element('/Events/View/value_field', array('object' => $object, 'linkClass' => $linkClass)); ?>
|
||||
</td>
|
||||
<td class="shortish"> </td>
|
||||
<td class="shortish"> </td>
|
||||
<td class="showspaces bitwider">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_comment_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_comment_solid'; ?>" class="inline-field-solid">
|
||||
<?php echo nl2br(h($object['comment'])); ?>
|
||||
</div>
|
||||
<?php echo nl2br(h($object['comment']), false); ?>
|
||||
</td>
|
||||
<td class="short" style="padding-top:3px;"> </td>
|
||||
<td class="shortish">
|
||||
|
@ -145,13 +129,7 @@
|
|||
</ul>
|
||||
</td>
|
||||
<td class="short">
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_to_ids_placeholder'; ?>" class="inline-field-placeholder"></div>
|
||||
<div id="<?php echo $currentType . '_' . $object['id'] . '_to_ids_solid'; ?>" class="inline-field-solid">
|
||||
<?php
|
||||
if ($object['to_ids']) echo 'Yes';
|
||||
else echo 'No';
|
||||
?>
|
||||
</div>
|
||||
<?= $object['to_ids'] ? __('Yes') : __('No') ?>
|
||||
</td>
|
||||
<td class="shortish"> </td>
|
||||
<td class="shortish"> </td>
|
||||
|
@ -170,12 +148,12 @@
|
|||
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => $baseurl . '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onclick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>');"></span>
|
||||
<?php
|
||||
}
|
||||
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
|
||||
?>
|
||||
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onclick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>');"></span>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
<?php
|
||||
if ($mayModify):
|
||||
?>
|
||||
<td style="width:10px;" data-position="<?php echo h($object['objectType']) . '_' . h($object['id']); ?>">
|
||||
<input id="select_proposal_<?php echo $object['id']; ?>" class="select_proposal row_checkbox" type="checkbox" data-id="<?php echo $object['id'];?>" />
|
||||
<td style="width:10px;">
|
||||
<input class="select_proposal" type="checkbox" data-id="<?php echo $object['id'];?>">
|
||||
</td>
|
||||
<?php
|
||||
endif;
|
||||
|
@ -73,12 +73,12 @@
|
|||
echo $this->Form->create('Shadow_Attribute', array('id' => 'ShadowAttribute_' . $object['id'] . '_accept', 'url' => $baseurl . '/shadow_attributes/accept/' . $object['id'], 'style' => 'display:none;'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onClick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
<span class="fas fa-check white useCursorPointer" title="<?php echo __('Accept Proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept proposal');?>" onclick="acceptObject('shadow_attributes', '<?php echo $object['id']; ?>');"></span>
|
||||
<?php
|
||||
}
|
||||
if (($event['Orgc']['id'] == $me['org_id'] && $mayModify) || $isSiteAdmin || ($object['org_id'] == $me['org_id'])) {
|
||||
?>
|
||||
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onClick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
<span class="fa fa-trash white useCursorPointer" title="<?php echo __('Discard proposal');?>" role="button" tabindex="0" aria-label="<?php echo __('Discard proposal');?>" onclick="deleteObject('shadow_attributes', 'discard' ,'<?php echo $object['id']; ?>');"></span>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -24,23 +24,19 @@ if (isset($sightingsData['data'][$objectId])) {
|
|||
}
|
||||
?>
|
||||
<td class="shortish">
|
||||
<?php
|
||||
if ($isAclSighting):
|
||||
?>
|
||||
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting');?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting');?>" onmouseover="flexibleAddSighting(this, '0', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>', 'top');" onclick="addSighting('0', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>');"> </i>
|
||||
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive');?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive');?>" onmouseover="flexibleAddSighting(this, '1', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>', 'bottom');" onclick="addSighting('1', '<?= $objectId ?>', '<?php echo h($object['event_id']);?>');"> </i>
|
||||
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings');?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings');?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"> </i>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<span id="sightingCount_<?php echo $objectId; ?>" class="bold" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
|
||||
<?php if ($isAclSighting): ?>
|
||||
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting');?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting');?>" onmouseover="flexibleAddSighting(this, 0, <?= $objectId ?>, 'top');" onclick="addSighting(0, <?= $objectId ?>)"></i>
|
||||
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive');?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive');?>" onmouseover="flexibleAddSighting(this, 1, <?= $objectId ?>, 'bottom');" onclick="addSighting(1, <?= $objectId ?>)"></i>
|
||||
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings');?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings');?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"></i>
|
||||
<?php endif; ?>
|
||||
<b id="sightingCount_<?php echo $objectId; ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
|
||||
(<span class="green"><?= $s ?></span>/<span class="red"><?= $f ?></span>/<span class="orange"><?= $e ?></span>)
|
||||
</span>
|
||||
</b>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php
|
||||
if (!empty($sightingsData['csv'][$objectId])) {
|
||||
echo $this->element('sparkline', array('scope' => 'object', 'id' => $objectId, 'csv' => $sightingsData['csv'][$objectId]));
|
||||
echo $this->element('sparkline_new', array('scope' => 'object', 'id' => $objectId, 'csv' => $sightingsData['csv'][$objectId]));
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<tr>
|
||||
<?php if ($isSiteAdmin): ?>
|
||||
<th>
|
||||
<input class="select_all select" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all events on current page');?>" onClick="toggleAllCheckboxes();" />
|
||||
<input class="select_all select" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all events on current page');?>" onClick="toggleAllCheckboxes();">
|
||||
</th>
|
||||
<?php else: ?>
|
||||
<th style="padding-left:0px;padding-right:0px;"> </th>
|
||||
<th style="padding-left:0;padding-right:0;"> </th>
|
||||
<?php endif;?>
|
||||
<th class="filter">
|
||||
<?php echo $this->Paginator->sort('published');?>
|
||||
|
@ -171,12 +171,12 @@
|
|||
</td>
|
||||
<?php if (in_array('timestamp', $columns, true)): ?>
|
||||
<td class="short dblclickElement">
|
||||
<?= $this->Time->time($event['Event']['timestamp']) ?>
|
||||
<?= $this->Time->time($event['Event']['timestamp']) ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<?php if (in_array('publish_timestamp', $columns, true)): ?>
|
||||
<td class="short dblclickElement">
|
||||
<?= $this->Time->time($event['Event']['publish_timestamp']) ?>
|
||||
<?= $this->Time->time($event['Event']['publish_timestamp']) ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="dblclickElement">
|
||||
|
@ -203,14 +203,14 @@
|
|||
<td class="short action-links">
|
||||
<?php
|
||||
if (0 == $event['Event']['published'] && ($isSiteAdmin || ($isAclPublish && $event['Event']['orgc_id'] == $me['org_id']))) {
|
||||
echo $this->Form->postLink('', array('action' => 'alert', $eventId), array('class' => 'black fa fa-upload', 'title' => __('Publish Event'), 'aria-label' => __('Publish Event')), __('Are you sure this event is complete and everyone should be informed?'));
|
||||
echo sprintf('<a class="useCursorPointer fa fa-upload" title="%s" aria-label="%s" onclick="event.preventDefault();publishPopup(%s)"></a>', __('Publish Event'), __('Publish Event'), $eventId);
|
||||
}
|
||||
|
||||
if ($isSiteAdmin || ($isAclModify && $event['Event']['user_id'] == $me['id']) || ($isAclModifyOrg && $event['Event']['orgc_id'] == $me['org_id'])):
|
||||
?>
|
||||
<a href="<?php echo $baseurl."/events/edit/".$eventId ?>" title="<?php echo __('Edit');?>" aria-label="<?php echo __('Edit');?>"><i class="black fa fa-edit"></i></a>
|
||||
<?php
|
||||
echo sprintf('<a class="useCursorPointer fa fa-trash" title="%s" aria-label="%s" onclick="deleteEvent(%s)"></a>', __('Delete'), __('Delete'), $eventId);
|
||||
echo sprintf('<a class="useCursorPointer fa fa-trash" title="%s" aria-label="%s" onclick="event.preventDefault();deleteEventPopup(%s)"></a>', __('Delete'), __('Delete'), $eventId);
|
||||
endif;
|
||||
?>
|
||||
<a href="<?php echo $baseurl."/events/view/".$eventId ?>" title="<?php echo __('View');?>" aria-label="<?php echo __('View');?>"><i class="fa black fa-eye"></i></a>
|
||||
|
@ -226,11 +226,10 @@
|
|||
}).click(function(e) {
|
||||
if ($(this).is(':checked')) {
|
||||
if (e.shiftKey) {
|
||||
selectAllInbetween(lastSelected, this.id);
|
||||
selectAllInbetween(lastSelected, this);
|
||||
}
|
||||
lastSelected = this.id;
|
||||
lastSelected = this;
|
||||
}
|
||||
attributeListAnyAttributeCheckBoxesChecked();
|
||||
});
|
||||
|
||||
$('.distributionNetworkToggle').each(function() {
|
||||
|
@ -239,15 +238,4 @@
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
function deleteEvent(id) {
|
||||
var message = "<?= __('Are you sure you want to delete #') ?>" + id + "?"
|
||||
var url = '<?= $baseurl ?>/events/delete/' + id
|
||||
if (confirm(message)) {
|
||||
fetchFormDataAjax(url, function(formData) {
|
||||
$('body').append($('<div id="temp" class="hidden"/>').html(formData));
|
||||
$('#temp form').submit()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
<?php
|
||||
$addTagButton = ' ';
|
||||
if ($full) {
|
||||
$url = $baseurl . '/tags/selectTaxonomy/' . h($tagCollection['TagCollection']['id']) . '/tag_collection';
|
||||
$addTagButton = sprintf(
|
||||
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 2px;" onClick="popoverPopup(this, %s);"><i class="fas fa-globe-americas"></i> +</button>',
|
||||
sprintf("'%s/tag_collection', 'tags', 'selectTaxonomy'", h($tagCollection['TagCollection']['id']))
|
||||
'<button id="addTagButton" class="btn addButton btn-inverse noPrint" data-popover-popup="%s"><i class="fas fa-globe-americas"></i> <i class="fas fa-plus"></i></button>',
|
||||
$url
|
||||
);
|
||||
}
|
||||
echo $addTagButton;
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
$span_delete = '';
|
||||
if ($full || ($fullLocal && $tag['Tag']['local'])) {
|
||||
$span_delete = sprintf(
|
||||
'<span class="%s" title="%s" role="%s" tabindex="%s" aria-label="%s" onClick="%s">x</span>',
|
||||
'<span class="%s" title="%s" role="%s" tabindex="%s" aria-label="%s" onclick="%s">x</span>',
|
||||
'black-white tag useCursorPointer noPrint',
|
||||
__('Remove tag'),
|
||||
"button",
|
||||
|
@ -107,43 +107,26 @@
|
|||
$buttonData = array();
|
||||
if ($full) {
|
||||
$buttonData[] = sprintf(
|
||||
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" style="%s" onClick="%s">%s</button>',
|
||||
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" data-popover-popup="%s">%s</button>',
|
||||
__('Add a tag'),
|
||||
__('Add a tag'),
|
||||
'addTagButton btn btn-inverse noPrint',
|
||||
'line-height:10px; padding: 2px;',
|
||||
sprintf(
|
||||
"popoverPopup(this, '%s%s', '%s', '%s');",
|
||||
$id,
|
||||
($scope === 'event') ? '' : ('/' . $scope),
|
||||
'tags',
|
||||
'selectTaxonomy'
|
||||
),
|
||||
'<i class="fas fa-globe-americas"></i> +'
|
||||
'addTagButton addButton btn btn-inverse noPrint',
|
||||
$baseurl . '/tags/selectTaxonomy/' . $id . ($scope === 'event' ? '' : ('/' . $scope)),
|
||||
'<i class="fas fa-globe-americas"></i> <i class="fas fa-plus"></i>'
|
||||
);
|
||||
}
|
||||
if ($full || $fullLocal) {
|
||||
$buttonData[] = sprintf(
|
||||
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" style="%s" onClick="%s">%s</button>',
|
||||
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" data-popover-popup="%s">%s</button>',
|
||||
__('Add a local tag'),
|
||||
__('Add a local tag'),
|
||||
'addLocalTagButton btn btn-inverse noPrint',
|
||||
'line-height:10px; padding: 2px;',
|
||||
sprintf(
|
||||
"popoverPopup(this, '%s%s', '%s', '%s')",
|
||||
$id,
|
||||
($scope === 'event') ? '' : ('/' . $scope),
|
||||
'tags',
|
||||
'selectTaxonomy/local:1'
|
||||
),
|
||||
'<i class="fas fa-user"></i> +'
|
||||
'addLocalTagButton addButton btn btn-inverse noPrint',
|
||||
$baseurl . '/tags/selectTaxonomy/local:1/' . $id . ($scope === 'event' ? '' : ('/' . $scope)),
|
||||
'<i class="fas fa-user"></i> <i class="fas fa-plus"></i>'
|
||||
);
|
||||
}
|
||||
if (!empty($buttonData)) {
|
||||
$tagData .= sprintf(
|
||||
'<span style="white-space:nowrap;">%s</span>',
|
||||
implode(' ', $buttonData)
|
||||
);
|
||||
$tagData .= '<span style="white-space:nowrap">' . implode('', $buttonData) . '</span>';
|
||||
}
|
||||
echo sprintf(
|
||||
'<span class="tag-list-container">%s</span>',
|
||||
|
@ -156,11 +139,11 @@
|
|||
$tagConflictData .= '<div class="text-container">';
|
||||
foreach ($tagConflicts['global'] as $tagConflict) {
|
||||
$tagConflictData .= sprintf(
|
||||
'<strong>%s</strong></br>',
|
||||
'<strong>%s</strong><br>',
|
||||
h($tagConflict['conflict'])
|
||||
);
|
||||
foreach ($tagConflict['tags'] as $tag) {
|
||||
$tagConflictData .= sprintf('<span class="apply_css_arrow nowrap">%s</span></br>', h($tag));
|
||||
$tagConflictData .= sprintf('<span class="apply_css_arrow nowrap">%s</span><br>', h($tag));
|
||||
}
|
||||
}
|
||||
$tagConflictData .= '</div></div></span>';
|
||||
|
@ -171,14 +154,13 @@
|
|||
$tagConflictData .= '<div class="text-container">';
|
||||
foreach ($tagConflicts['local'] as $tagConflict) {
|
||||
$tagConflictData .= sprintf(
|
||||
'<strong>%s</strong></br>',
|
||||
'<strong>%s</strong><br>',
|
||||
h($tagConflict['conflict'])
|
||||
);
|
||||
foreach ($tagConflict['tags'] as $tag) {
|
||||
$tagConflictData .= sprintf('<span class="apply_css_arrow nowrap">%s</span></br>', h($tag));
|
||||
$tagConflictData .= sprintf('<span class="apply_css_arrow nowrap">%s</span><br>', h($tag));
|
||||
}
|
||||
}
|
||||
$tagConflictData .= '</div></div></span>';
|
||||
}
|
||||
echo $tagConflictData;
|
||||
?>
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
}
|
||||
$urlHere = implode('/', $urlHere);
|
||||
$urlHere = $baseurl . $urlHere;
|
||||
$mayModify = ($isSiteAdmin || ($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
|
||||
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
|
||||
$mayChangeCorrelation = !Configure::read('MISP.completely_disable_correlation') && ($isSiteAdmin || ($mayModify && Configure::read('MISP.allow_disabling_correlation')));
|
||||
$possibleAction = $mayModify ? 'attribute' : 'shadow_attribute';
|
||||
$all = false;
|
||||
|
@ -19,7 +17,7 @@
|
|||
}
|
||||
$fieldCount = 11;
|
||||
$filtered = false;
|
||||
if(isset($passedArgsArray)){
|
||||
if (isset($passedArgsArray)){
|
||||
if (count($passedArgsArray) > 0) {
|
||||
$filtered = true;
|
||||
}
|
||||
|
@ -69,8 +67,7 @@
|
|||
'label' => false,
|
||||
));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?php
|
||||
|
||||
echo $this->Form->create('ShadowAttribute', array('id' => 'accept_selected', 'url' => $baseurl . '/shadow_attributes/acceptSelected/' . $event['Event']['id']));
|
||||
echo $this->Form->input('ids_accept', array(
|
||||
'type' => 'text',
|
||||
|
@ -79,8 +76,7 @@
|
|||
'label' => false,
|
||||
));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?php
|
||||
|
||||
echo $this->Form->create('ShadowAttribute', array('id' => 'discard_selected', 'url' => $baseurl . '/shadow_attributes/discardSelected/' . $event['Event']['id']));
|
||||
echo $this->Form->input('ids_discard', array(
|
||||
'type' => 'text',
|
||||
|
@ -111,7 +107,7 @@
|
|||
if ($extended || ($mayModify && !empty($event['objects']))):
|
||||
$fieldCount += 1;
|
||||
?>
|
||||
<th><input class="select_all" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all attributes/proposals on current page');?>" onClick="toggleAllAttributeCheckboxes();" /></th>
|
||||
<th><input class="select_all" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all attributes/proposals on current page');?>" onclick="toggleAllAttributeCheckboxes()"></th>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
@ -227,9 +223,6 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
var deleted = <?php echo (!empty($deleted)) ? '1' : '0';?>;
|
||||
var includeRelatedTags = <?php echo (!empty($includeRelatedTags)) ? '1' : '0';?>;
|
||||
$(function() {
|
||||
$('.addGalaxy').click(function() {
|
||||
addGalaxyListener(this);
|
||||
});
|
||||
<?php
|
||||
if (isset($focus)):
|
||||
?>
|
||||
|
@ -242,18 +235,18 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
$('.select_attribute').prop('checked', false).click(function(e) {
|
||||
if ($(this).is(':checked')) {
|
||||
if (e.shiftKey) {
|
||||
selectAllInbetween(lastSelected, this.id);
|
||||
selectAllInbetween(lastSelected, this);
|
||||
}
|
||||
lastSelected = this.id;
|
||||
lastSelected = this;
|
||||
}
|
||||
attributeListAnyAttributeCheckBoxesChecked();
|
||||
});
|
||||
$('.select_proposal').prop('checked', false).click(function(e){
|
||||
if ($(this).is(':checked')) {
|
||||
if (e.shiftKey) {
|
||||
selectAllInbetween(lastSelected, this.id);
|
||||
selectAllInbetween(lastSelected, this);
|
||||
}
|
||||
lastSelected = this.id;
|
||||
lastSelected = this;
|
||||
}
|
||||
attributeListAnyProposalCheckBoxesChecked();
|
||||
});
|
||||
|
@ -261,16 +254,6 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
attributeListAnyAttributeCheckBoxesChecked();
|
||||
attributeListAnyProposalCheckBoxesChecked();
|
||||
});
|
||||
$('.correlation-toggle').click(function() {
|
||||
var attribute_id = $(this).data('attribute-id');
|
||||
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
|
||||
return false;
|
||||
});
|
||||
$('.toids-toggle').click(function() {
|
||||
var attribute_id = $(this).data('attribute-id');
|
||||
getPopup(attribute_id, 'attributes', 'toggleToIDS', '', '#confirmation_box');
|
||||
return false;
|
||||
});
|
||||
$('.screenshot').click(function() {
|
||||
screenshotPopup($(this).attr('src'), $(this).attr('title'));
|
||||
});
|
||||
|
@ -278,15 +261,13 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
var selected = [];
|
||||
var object_context = $(this).data('object-context');
|
||||
var object_id = $(this).data('object-id');
|
||||
if (object_id == 'selected') {
|
||||
$(".select_attribute").each(function() {
|
||||
if ($(this).is(":checked")) {
|
||||
selected.push($(this).data("id"));
|
||||
}
|
||||
if (object_id === 'selected') {
|
||||
$(".select_attribute:checked").each(function() {
|
||||
selected.push($(this).data("id"));
|
||||
});
|
||||
object_id = selected.join('|');
|
||||
}
|
||||
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
|
||||
var url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
|
||||
genericPopup(url, '#popover_box');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -71,8 +71,9 @@
|
|||
'title' => __('Tag selected Attributes'),
|
||||
'class' => 'mass-select hidden',
|
||||
'fa-icon' => 'tag',
|
||||
'onClick' => 'popoverPopup',
|
||||
'onClickParams' => array('this', 'selected/attribute', 'tags', 'selectTaxonomy')
|
||||
'data' => [
|
||||
'popover-popup' => $baseurl . '/tags/selectTaxonomy/selected/attribute',
|
||||
],
|
||||
),
|
||||
array(
|
||||
'id' => 'multi-galaxy-button',
|
||||
|
@ -80,8 +81,9 @@
|
|||
'class' => 'mass-select hidden',
|
||||
'fa-icon' => 'rebel',
|
||||
'fa-source' => 'fab',
|
||||
'onClick' => 'popoverPopup',
|
||||
'onClickParams' => array('this', 'selected/attribute/eventid:' . $eventId, 'galaxies', 'selectGalaxyNamespace')
|
||||
'data' => [
|
||||
'popover-popup' => $baseurl . '/galaxies/selectGalaxyNamespace/selected/attribute/eventid:' . $eventId,
|
||||
],
|
||||
),
|
||||
array(
|
||||
'id' => 'group-into-object-button',
|
||||
|
|
|
@ -123,21 +123,21 @@ echo $this->Form->end();
|
|||
<?php endif; ?>
|
||||
<?php
|
||||
if ($editButtonsEnabled) {
|
||||
$link = "$baseurl/galaxies/selectGalaxyNamespace/" . h($target_id) . "/" . h($target_type) . "/local:0";
|
||||
echo sprintf(
|
||||
'<button class="%s" data-target-type="%s" data-target-id="%s" data-local="false" role="button" tabindex="0" aria-label="' . __('Add new cluster') . '" title="' . __('Add new cluster') . '">%s</button>',
|
||||
'useCursorPointer btn btn-inverse addGalaxy',
|
||||
h($target_type),
|
||||
h($target_id),
|
||||
'<button class="%s" data-popover-popup="%s" role="button" tabindex="0" aria-label="' . __('Add new cluster') . '" title="' . __('Add new cluster') . '">%s</button>',
|
||||
'useCursorPointer addButton btn btn-inverse',
|
||||
$link,
|
||||
'<i class="fas fa-globe-americas"></i> <i class="fas fa-plus"></i>'
|
||||
);
|
||||
}
|
||||
|
||||
if ($editButtonsLocalEnabled) {
|
||||
$link = "$baseurl/galaxies/selectGalaxyNamespace/" . h($target_id) . "/" . h($target_type) . "/local:1";
|
||||
echo sprintf(
|
||||
'<button class="%s" data-target-type="%s" data-target-id="%s" data-local="true" role="button" tabindex="0" aria-label="' . __('Add new local cluster') . '" title="' . __('Add new local cluster') . '">%s</button>',
|
||||
'useCursorPointer btn btn-inverse addGalaxy',
|
||||
h($target_type),
|
||||
h($target_id),
|
||||
'<button class="%s" data-popover-popup="%s" role="button" tabindex="0" aria-label="' . __('Add new local cluster') . '" title="' . __('Add new local cluster') . '">%s</button>',
|
||||
'useCursorPointer addButton btn btn-inverse',
|
||||
$link,
|
||||
'<i class="fas fa-user"></i> <i class="fas fa-plus"></i>'
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<span id="pull_tags_NOT" style="display:none;"><?php echo __('Events with the following tags blocked'); ?>: <span id="pull_tags_NOT_text" style="color:red;"></span><br /></span>
|
||||
<span id="pull_orgs_OR" style="display:none;"><?php echo __('Events with the following organisations allowed'); ?>: <span id="pull_orgs_OR_text" style="color:green;"></span><br /></span>
|
||||
<span id="pull_orgs_NOT" style="display:none;"><?php echo __('Events with the following organisations blocked'); ?>: <span id="pull_orgs_NOT_text" style="color:red;"></span><br /></span>
|
||||
<span id="pull_url_params" style="display:none;"><?php echo __('Additional parameters: '); ?><span id="pull_url_params_text" style="color:green;"></span><br /></span>
|
||||
<span id="pull_modify" class="btn btn-inverse" style="line-height:10px; padding: 4px 4px;"><?php echo __('Modify'); ?></span><br /><br />
|
||||
|
||||
<div id="hiddenRuleForms">
|
||||
|
@ -23,7 +24,8 @@
|
|||
'context' => $this->Form->defaultModel,
|
||||
'allTags' => $fieldData['tags'],
|
||||
'allOrganisations' => $fieldData['orgs'],
|
||||
'ruleObject' => $pullRules
|
||||
'ruleObject' => $pullRules,
|
||||
'coreMirrorHints' => $supportedUrlparams,
|
||||
])
|
||||
]
|
||||
],
|
||||
|
|
|
@ -23,13 +23,17 @@
|
|||
continue;
|
||||
}
|
||||
if (isset($action['complex_requirement'])) {
|
||||
if (isset($action['complex_requirement']['options']['datapath'])) {
|
||||
foreach ($action['complex_requirement']['options']['datapath'] as $name => $path) {
|
||||
$action['complex_requirement']['options']['datapath'][$name] = empty(Hash::extract($row, $path)[0]) ? null : Hash::extract($row, $path)[0];
|
||||
if ($action['complex_requirement'] instanceof Closure) {
|
||||
$requirementMet = $action['complex_requirement']($row);
|
||||
} else {
|
||||
if (isset($action['complex_requirement']['options']['datapath'])) {
|
||||
foreach ($action['complex_requirement']['options']['datapath'] as $name => $path) {
|
||||
$action['complex_requirement']['options']['datapath'][$name] = empty(Hash::extract($row, $path)[0]) ? null : Hash::extract($row, $path)[0];
|
||||
}
|
||||
}
|
||||
$options = isset($action['complex_requirement']['options']) ? $action['complex_requirement']['options'] : [];
|
||||
$requirementMet = $action['complex_requirement']['function']($row, $options);
|
||||
}
|
||||
$options = isset($action['complex_requirement']['options']) ? $action['complex_requirement']['options'] : array();
|
||||
$requirementMet = $action['complex_requirement']['function']($row, $options);
|
||||
if (!$requirementMet) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -10,15 +10,13 @@ if ($quickedit) {
|
|||
$distributionLevel = (Hash::extract($row, $field['data_path'])[0]);
|
||||
|
||||
echo sprintf('<div %s>', $quickedit ? sprintf(
|
||||
" onmouseenter=\"quickEditHover(this, '%s', %s, 'distribution', %s);\"",
|
||||
" onmouseenter=\"quickEditHover(this, '%s', %s, 'distribution');\"",
|
||||
$scope,
|
||||
$objectId,
|
||||
$event['id']
|
||||
$objectId
|
||||
) : '');
|
||||
|
||||
if ($quickedit) {
|
||||
echo sprintf("<div id='%s_%s_distribution_placeholder' class='inline-field-placeholder'></div>", $scope, $objectId);
|
||||
echo sprintf("<div id='%s_%s_distribution_solid' class='inline-field-solid'>", $scope, $objectId);
|
||||
echo "<div class='inline-field-solid'>";
|
||||
}
|
||||
|
||||
echo sprintf(
|
||||
|
|
|
@ -29,12 +29,12 @@ if (isset($sightings['data'][$objectId])) {
|
|||
|
||||
if ($isAclSighting) :
|
||||
?>
|
||||
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting'); ?>" onmouseover="flexibleAddSighting(this, '0', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>', 'top');" onclick="addSighting('0', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>');"> </i>
|
||||
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive'); ?>" onmouseover="flexibleAddSighting(this, '1', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>', 'bottom');" onclick="addSighting('1', '<?= $objectId ?>', '<?php echo h($object['event_id']); ?>');"> </i>
|
||||
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings'); ?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"> </i>
|
||||
<i class="far fa-thumbs-up useCursorPointer" title="<?php echo __('Add sighting'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Add sighting'); ?>" onmouseover="flexibleAddSighting(this, 0, <?= $objectId ?>, 'top');" onclick="addSighting(0, <?= $objectId ?>);"></i>
|
||||
<i class="far fa-thumbs-down useCursorPointer" title="<?php echo __('Mark as false-positive'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Mark as false-positive'); ?>" onmouseover="flexibleAddSighting(this, 1, <?= $objectId ?>, 'bottom');" onclick="addSighting(1, '<?= $objectId ?>');"></i>
|
||||
<i class="fas fa-wrench useCursorPointer sightings_advanced_add" title="<?php echo __('Advanced sightings'); ?>" role="button" tabindex="0" aria-label="<?php echo __('Advanced sightings'); ?>" data-object-id="<?= $objectId ?>" data-object-context="attribute"></i>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<span id="sightingCount_<?php echo $objectId; ?>" class="bold" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
|
||||
<b id="sightingCount_<?php echo $objectId; ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?= h($html) ?>">
|
||||
(<span class="green"><?= $s ?></span>/<span class="red"><?= $f ?></span>/<span class="orange"><?= $e ?></span>)
|
||||
</span>
|
||||
</b>
|
||||
|
|
|
@ -6,18 +6,30 @@
|
|||
* to fetch it.
|
||||
*
|
||||
*/
|
||||
$data = Hash::extract($row, $field['data_path']);
|
||||
$seed = mt_rand();
|
||||
$checkboxId = 'GenericToggle-' . $seed;
|
||||
$checkboxClass = empty($field['checkbox_class']) ? 'genericCheckbox' : h($field['checkbox_class']);
|
||||
$tempboxId = 'TempBox-' . $seed;
|
||||
echo sprintf(
|
||||
'<input type="checkbox" id="%s" class="%s" %s><span id="%s" class="hidden">',
|
||||
$checkboxId,
|
||||
$checkboxClass,
|
||||
empty($data[0]) ? '' : 'checked',
|
||||
$tempboxId
|
||||
);
|
||||
$data = Hash::extract($row, $field['data_path']);
|
||||
$seed = mt_rand();
|
||||
$checkboxId = 'GenericToggle-' . $seed;
|
||||
$checkboxClass = empty($field['checkbox_class']) ? 'genericCheckbox' : h($field['checkbox_class']);
|
||||
$tempboxId = 'TempBox-' . $seed;
|
||||
|
||||
$params = [];
|
||||
if (!empty($data[0])) {
|
||||
$params[] = 'checked';
|
||||
}
|
||||
if (!empty($field['disabled'])) {
|
||||
$params[] = 'disabled';
|
||||
}
|
||||
$params = empty($params) ? '' : ' ' . implode(' ', $params);
|
||||
|
||||
echo sprintf(
|
||||
'<input type="checkbox" id="%s" class="%s"%s><span id="%s" class="hidden"></span>',
|
||||
$checkboxId,
|
||||
$checkboxClass,
|
||||
$params,
|
||||
$tempboxId
|
||||
);
|
||||
|
||||
if (empty($field['disabled'])):
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
@ -71,3 +83,4 @@ $(function() {
|
|||
});
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -9,7 +9,7 @@ if (!isset($data['requirement']) || $data['requirement']) {
|
|||
}
|
||||
$onClickParams = implode(',', $onClickParams);
|
||||
$onClick = sprintf(
|
||||
'onClick = "%s%s"',
|
||||
'onclick="%s%s"',
|
||||
(empty($data['url'])) ? 'event.preventDefault();' : '',
|
||||
(!empty($data['onClick']) ? sprintf(
|
||||
'%s(%s)',
|
||||
|
@ -28,7 +28,6 @@ if (!isset($data['requirement']) || $data['requirement']) {
|
|||
);
|
||||
}
|
||||
}
|
||||
$dataFields = implode(' ', $dataFields);
|
||||
echo sprintf(
|
||||
'<li><a class="%s %s" id="%s" href="%s" %s %s %s %s>%s%s%s</a></li>',
|
||||
empty($data['class']) ? '' : h($data['class']),
|
||||
|
@ -36,7 +35,7 @@ if (!isset($data['requirement']) || $data['requirement']) {
|
|||
empty($data['id']) ? '' : h($data['id']),
|
||||
empty($data['url']) ? '#' : h($data['url']), // prevent default is passed if the url is not set
|
||||
empty($onClick) ? '' : $onClick, // pass $data['onClick'] for the function name to call and $data['onClickParams'] for the parameter list
|
||||
empty($dataFields) ? '' : $dataFields,
|
||||
empty($dataFields) ? '' : implode(' ', $dataFields),
|
||||
empty($data['title']) ? '' : sprintf('title="%s"', h($data['title'])),
|
||||
!empty($data['text']) ? '' : (!empty($data['title']) ? sprintf('aria-label="%s"', h($data['title'])) : ''),
|
||||
empty($data['fa-icon']) ? '' : sprintf('<i class="fa fa-%s"></i>', $data['fa-icon']), // this has to be sanitised beforehand!
|
||||
|
|
|
@ -32,15 +32,20 @@
|
|||
);
|
||||
}
|
||||
}
|
||||
$dataFields = implode(' ', $dataFields);
|
||||
|
||||
$classes = ['btn', 'btn-small'];
|
||||
$classes[] = empty($data['active']) ? 'btn-inverse' : 'btn-primary';
|
||||
if (!empty($data['class'])) {
|
||||
$classes[] = $data['class'];
|
||||
}
|
||||
|
||||
echo sprintf(
|
||||
'<a class="btn btn-small %s %s" %s href="%s" %s %s %s %s %s>%s%s%s %s</a>',
|
||||
empty($data['class']) ? '' : h($data['class']),
|
||||
empty($data['active']) ? 'btn-inverse' : 'btn-primary', // Change the default class for highlighted/active toggles here
|
||||
'<a class="%s" %s href="%s" %s %s %s %s %s>%s%s%s %s</a>',
|
||||
implode(' ', $classes),
|
||||
empty($data['id']) ? '' : 'id="' . h($data['id']) . '"',
|
||||
empty($data['url']) ? '#' : h($data['url']), // prevent default is passed if the url is not set
|
||||
empty($onClick) ? '' : $onClick, // pass $data['onClick'] for the function name to call and $data['onClickParams'] for the parameter list
|
||||
empty($dataFields) ? '' : $dataFields,
|
||||
empty($dataFields) ? '' : implode(' ', $dataFields),
|
||||
empty($data['title']) ? '' : sprintf('title="%s"', h($data['title'])),
|
||||
empty($data['style']) ? '' : sprintf('style="%s"', h($data['style'])),
|
||||
!empty($data['text']) ? '' : (!empty($data['title']) ? sprintf('aria-label="%s"', h($data['title'])) : ''),
|
||||
|
|
|
@ -98,10 +98,13 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
|
|||
'url' => $baseurl . '/events/edit/' . $eventId,
|
||||
'text' => __('Edit Event')
|
||||
));
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_post_link', array(
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'url' => $baseurl . '/events/delete/' . $eventId,
|
||||
'text' => __('Delete Event'),
|
||||
'message' => __('Are you sure you want to delete event #%s?', $eventId)
|
||||
'onClick' => array(
|
||||
'function' => 'deleteEventPopup',
|
||||
'params' => [$eventId]
|
||||
),
|
||||
));
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'element_id' => 'addAttribute',
|
||||
|
@ -337,10 +340,10 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
|
|||
),
|
||||
'text' => __('Import from…')
|
||||
));
|
||||
if ($canAccess('servers', 'rest')) {
|
||||
if ($canAccess('api', 'rest')) {
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'element_id' => 'rest',
|
||||
'url' => $baseurl . '/servers/rest',
|
||||
'url' => $baseurl . '/api/rest',
|
||||
'text' => __('REST client')
|
||||
));
|
||||
}
|
||||
|
@ -1606,17 +1609,15 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
|
|||
case 'api':
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'element_id' => 'openapi',
|
||||
'url' => $baseurl . '/servers/openapi',
|
||||
'url' => $baseurl . '/api/openapi',
|
||||
'text' => __('OpenAPI')
|
||||
));
|
||||
if ($isAclAdd) {
|
||||
if ($canAccess('servers', 'rest')) {
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'element_id' => 'rest',
|
||||
'url' => $baseurl . '/servers/rest',
|
||||
'text' => __('REST client')
|
||||
));
|
||||
}
|
||||
if ($canAccess('api', 'rest')) {
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'element_id' => 'rest',
|
||||
'url' => $baseurl . '/api/rest',
|
||||
'text' => __('REST client')
|
||||
));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ if (!empty($onClick)) {
|
|||
$params .= "'" . h($param) . "'";
|
||||
}
|
||||
}
|
||||
$a .= sprintf(' onclick="%s(%s)"', $onClick['function'], $params);
|
||||
$a .= sprintf(' onclick="event.preventDefault();%s(%s)"', $onClick['function'], $params);
|
||||
}
|
||||
if (!empty($download)) {
|
||||
$a .= ' download="' . h($download) . '"';
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<?php
|
||||
$links = [];
|
||||
foreach ($event['warnings'] as $id => $name) {
|
||||
$links[] = sprintf(
|
||||
'<a href="%s/warninglists/view/%s">%s</a>',
|
||||
$baseurl,
|
||||
h($id),
|
||||
h($name)
|
||||
);
|
||||
}
|
||||
echo sprintf(
|
||||
'<div class="warning_container">%s%s</div>',
|
||||
sprintf(
|
||||
'<h4 class="red">%s</h4>',
|
||||
sprintf(
|
||||
'%s<a href="#attributeList" title="%s" onclick="toggleBoolFilter(\'%s/events/view/%s\');">%s</a>',
|
||||
__('Warning: Potential false positives'),
|
||||
__('Show just attributes that have warnings'),
|
||||
$baseurl,
|
||||
h($event['Event']['id']),
|
||||
__(' (show)')
|
||||
)
|
||||
),
|
||||
implode('<br />', $links)
|
||||
$links = [];
|
||||
foreach ($event['warnings'] as $id => $name) {
|
||||
$links[] = sprintf(
|
||||
'<a href="%s/warninglists/view/%s">%s</a>',
|
||||
$baseurl,
|
||||
(int)$id,
|
||||
h($name)
|
||||
);
|
||||
}
|
||||
echo sprintf(
|
||||
'<div class="warning_container">%s%s</div>',
|
||||
sprintf(
|
||||
'<h4>%s</h4>',
|
||||
sprintf(
|
||||
'%s <a href="#attributeList" title="%s" onclick="toggleBoolFilter(\'%s/events/view/%s\', \'warning\');">(%s)</a>',
|
||||
__('Warning: Potential false positives'),
|
||||
__('Show just attributes that have warnings'),
|
||||
$baseurl,
|
||||
(int)$event['Event']['id'],
|
||||
__('show')
|
||||
)
|
||||
),
|
||||
implode('<br>', $links)
|
||||
);
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
if ($taxonomy['Taxonomy']['exclusive']) {
|
||||
$conflictHtmlInternal[] = sprintf(
|
||||
'<li>%s</li>',
|
||||
sprintf(
|
||||
('%s is an exclusive taxonomy. Only one Tag of this taxonomy is allowed on an element.'),
|
||||
__(
|
||||
'%s is an exclusive taxonomy. Only one Tag of this taxonomy is allowed on an element.',
|
||||
sprintf('<strong>%s</strong>', h($taxonomy['Taxonomy']['namespace']))
|
||||
)
|
||||
);
|
||||
|
@ -21,8 +21,8 @@
|
|||
foreach ($taxonomy['TaxonomyPredicate'] as $predicate) {
|
||||
$conflictHtmlInternal[] = sprintf(
|
||||
'<li>%s</li>',
|
||||
sprintf(
|
||||
('%s is an exclusive taxonomy predicate. Only one Tag of this predicate is allowed on an element'),
|
||||
__(
|
||||
'%s is an exclusive taxonomy predicate. Only one Tag of this predicate is allowed on an element',
|
||||
sprintf('<strong>%s</strong>', h($predicate['value']))
|
||||
)
|
||||
);
|
||||
|
@ -35,7 +35,7 @@
|
|||
}
|
||||
|
||||
echo sprintf(
|
||||
'<div class="warning_container"><h4 class="red">%s</h4>%s</div>',
|
||||
'<div class="warning_container"><h4>%s</h4>%s</div>',
|
||||
__('Warning: Taxonomy inconsistencies'),
|
||||
$conflictHtml
|
||||
);
|
||||
|
|
|
@ -12,6 +12,11 @@ if (!empty($field['url'])) {
|
|||
}
|
||||
foreach ($field['url_vars'] as $k => $path) {
|
||||
$field['url'] = str_replace('{{' . $k . '}}', Hash::extract($data, $path)[0], $field['url']);
|
||||
$temp = explode(':', $field['url']);
|
||||
if (!in_array(strtolower($temp[0]), ['http', 'https'])) {
|
||||
$field['url'] = '#';
|
||||
$string = 'Malformed URL - invalid protocol (' . h($temp[0]) . ':)';
|
||||
}
|
||||
}
|
||||
}
|
||||
$string = sprintf(
|
||||
|
|
|
@ -488,12 +488,12 @@
|
|||
'children' => array(
|
||||
array(
|
||||
'text' => __('OpenAPI'),
|
||||
'url' => $baseurl . '/servers/openapi'
|
||||
'url' => $baseurl . '/api/openapi'
|
||||
),
|
||||
array(
|
||||
'text' => __('REST client'),
|
||||
'url' => $baseurl . '/servers/rest',
|
||||
'requirement' => $canAccess('servers', 'rest')
|
||||
'url' => $baseurl . '/api/rest',
|
||||
'requirement' => $canAccess('api', 'rest')
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
</div>
|
||||
|
||||
<?php
|
||||
if (!empty(Configure::read('MISP.enable_synchronisation_filtering_on_type'))) {
|
||||
if ($pull_scope == 'server' && !empty(Configure::read('MISP.enable_synchronisation_filtering_on_type'))) {
|
||||
echo $this->element('serverRuleElements/rules_filtering_type', [
|
||||
'technique' => 'pull',
|
||||
'allowEmptyOptions' => true,
|
||||
|
@ -99,6 +99,7 @@ echo $this->element('genericElements/assetLoader', array(
|
|||
'js' => array(
|
||||
'codemirror/codemirror',
|
||||
'codemirror/modes/javascript',
|
||||
'codemirror/addons/show-hint',
|
||||
'codemirror/addons/closebrackets',
|
||||
'codemirror/addons/lint',
|
||||
'codemirror/addons/jsonlint',
|
||||
|
@ -114,6 +115,7 @@ echo $this->element('genericElements/assetLoader', array(
|
|||
|
||||
<script>
|
||||
var pullRemoteRules404Error = '<?= __('Connection error or the remote version is not supporting remote filter lookups (v2.4.142+). Make sure that the remote instance is accessible and that it is up to date.') ?>'
|
||||
var coreMirrorHints = <?= json_encode(!empty($coreMirrorHints) ? $coreMirrorHints : []) ?>;
|
||||
var cm;
|
||||
$(function() {
|
||||
var serverID = "<?= isset($id) ? $id : '' ?>"
|
||||
|
@ -194,6 +196,28 @@ echo $this->element('genericElements/assetLoader', array(
|
|||
});
|
||||
}
|
||||
|
||||
function jsonHints() {
|
||||
var cur = cm.getCursor()
|
||||
var token = cm.getTokenAt(cur)
|
||||
if (token.type != 'string property' && token.type != 'string') {
|
||||
return
|
||||
}
|
||||
if (cm.getMode().helperType !== "json") return;
|
||||
token.state = cm.state;
|
||||
token.line = cur.line
|
||||
|
||||
if (/\"([^\"]*)\"/.test(token.string)) {
|
||||
token.end = cur.ch;
|
||||
token.string = token.string.slice(1, cur.ch - token.start);
|
||||
}
|
||||
|
||||
return {
|
||||
list: token.type == 'string property' ? coreMirrorHints : [],
|
||||
from: CodeMirror.Pos(cur.line, token.start + 1),
|
||||
to: CodeMirror.Pos(cur.line, token.end)
|
||||
}
|
||||
}
|
||||
|
||||
function setupCodeMirror() {
|
||||
var cmOptions = {
|
||||
mode: "application/json",
|
||||
|
@ -205,10 +229,23 @@ echo $this->element('genericElements/assetLoader', array(
|
|||
showCursorWhenSelecting: true,
|
||||
lineWrapping: true,
|
||||
autoCloseBrackets: true,
|
||||
extraKeys: {
|
||||
"Esc": function(cm) {},
|
||||
"Ctrl-Space": "autocomplete",
|
||||
},
|
||||
hintOptions: {
|
||||
completeSingle: false,
|
||||
hint: jsonHints
|
||||
},
|
||||
}
|
||||
cm = CodeMirror.fromTextArea(document.getElementById('urlParams'), cmOptions);
|
||||
cm.on("keyup", function(cm, event) {
|
||||
$('#urlParams').val(cm.getValue())
|
||||
if (!cm.state.completionActive && /*Enables keyboard navigation in autocomplete list*/
|
||||
event.keyCode != 13) {
|
||||
/*Enter - do not open autocomplete list just after item has been selected in it*/
|
||||
cm.showHint()
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -220,4 +257,8 @@ echo $this->element('genericElements/assetLoader', array(
|
|||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.CodeMirror-hints {
|
||||
z-index: 1050;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,6 @@
|
|||
<?php if (!empty($csv)): ?>
|
||||
<div id="spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>"></div>
|
||||
<script>
|
||||
sparkline('#spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>', "<?= $csv ?>");
|
||||
</script>
|
||||
<?php endif; ?>
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
$body = str_replace('$password', $password, $body);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
$body = str_replace('\n', PHP_EOL, $body);
|
||||
$resolveVars = [
|
||||
'$contact' => 'MISP.contact',
|
||||
'$org' => 'MISP.org',
|
||||
'$misp' => 'MISP.baseurl'
|
||||
];
|
||||
foreach ($resolveVars as $k => $v) {
|
||||
$v = Configure::read($v);
|
||||
$body= str_replace($k, $v, $body);
|
||||
}
|
||||
echo $body;
|
|
@ -2,9 +2,9 @@
|
|||
<?php
|
||||
echo $this->Form->create('EventBlocklist', array('style' => 'margin:0px;', 'id' => 'PromptForm'));
|
||||
echo $this->Form->input('ids', array(
|
||||
'type' => 'hidden',
|
||||
'div' => 'hidden',
|
||||
'value' => json_encode($event_ids)
|
||||
'type' => 'hidden',
|
||||
'div' => 'hidden',
|
||||
'value' => json_encode($event_ids),
|
||||
));
|
||||
?>
|
||||
<legend><?php echo __('Delete blocklisted events'); ?></legend>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span role="button" tabindex="0" aria-label="Publish" title="Publish" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish()">Yes</span>
|
||||
<button role="button" tabindex="0" aria-label="Delete" title="Delete" id="PromptYesButton" class="btn btn-primary">Yes</button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
|
@ -23,7 +23,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -13,29 +13,29 @@
|
|||
'type' => 'simple',
|
||||
'children' => array(
|
||||
array(
|
||||
'onClick' => 'openGenericModal',
|
||||
'onClickParams' => [$baseurl . '/eventReports/add/' . h($event_id)],
|
||||
'url' => $baseurl . '/eventReports/add/' . h($event_id),
|
||||
'active' => true,
|
||||
'text' => __('Add Event Report'),
|
||||
'fa-icon' => 'plus',
|
||||
'class' => 'modal-open',
|
||||
'requirement' => $canModify,
|
||||
),
|
||||
array(
|
||||
'onClick' => 'openGenericModal',
|
||||
'onClickParams' => [$baseurl . '/eventReports/importReportFromUrl/' . h($event_id)],
|
||||
'url' => $baseurl . '/eventReports/importReportFromUrl/' . h($event_id),
|
||||
'active' => true,
|
||||
'text' => __('Import from URL'),
|
||||
'title' => __('Content for this URL will be downloaded and converted to Markdown'),
|
||||
'fa-icon' => 'link',
|
||||
'class' => 'modal-open',
|
||||
'requirement' => $canModify && $importModuleEnabled,
|
||||
),
|
||||
array(
|
||||
'onClick' => 'openGenericModal',
|
||||
'onClickParams' => [$baseurl . '/eventReports/reportFromEvent/' . h($event_id)],
|
||||
'url' => $baseurl . '/eventReports/reportFromEvent/' . h($event_id),
|
||||
'active' => true,
|
||||
'text' => __('Generate report from Event'),
|
||||
'title' => __('Based on filters, create a report summarizing the event'),
|
||||
'fa-icon' => 'list-alt',
|
||||
'class' => 'modal-open',
|
||||
'requirement' => $canModify,
|
||||
),
|
||||
)
|
||||
|
@ -114,18 +114,9 @@
|
|||
'icon' => 'trash',
|
||||
'onclick' => 'simplePopup(\'' . $baseurl . '/event_reports/delete/[onclick_params_data_path]\');',
|
||||
'onclick_params_data_path' => 'EventReport.id',
|
||||
'complex_requirement' => array(
|
||||
'function' => function ($row, $options) {
|
||||
return ($options['me']['Role']['perm_site_admin'] || $options['me']['org_id'] == $options['datapath']['orgc']) && !$options['datapath']['deleted'];
|
||||
},
|
||||
'options' => array(
|
||||
'me' => $me,
|
||||
'datapath' => array(
|
||||
'orgc' => 'EventReport.orgc_id',
|
||||
'deleted' => 'EventReport.deleted'
|
||||
)
|
||||
)
|
||||
),
|
||||
'complex_requirement' => function (array $row) use ($me) {
|
||||
return ($me['Role']['perm_site_admin'] || $me['org_id'] == $row['EventReport']['orgc_id']) && !$row['EventReport']['deleted'];
|
||||
},
|
||||
),
|
||||
array(
|
||||
'title' => __('Restore report'),
|
||||
|
@ -134,25 +125,15 @@
|
|||
'icon' => 'trash-restore',
|
||||
'postLink' => true,
|
||||
'postLinkConfirm' => __('Are you sure you want to restore the Report?'),
|
||||
'complex_requirement' => array(
|
||||
'function' => function ($row, $options) {
|
||||
return ($options['me']['Role']['perm_site_admin'] || $options['me']['org_id'] == $options['datapath']['orgc']) && $options['datapath']['deleted'];
|
||||
},
|
||||
'options' => array(
|
||||
'me' => $me,
|
||||
'datapath' => array(
|
||||
'orgc' => 'EventReport.orgc_id',
|
||||
'deleted' => 'EventReport.deleted'
|
||||
)
|
||||
)
|
||||
),
|
||||
'complex_requirement' => function (array $row) use ($me) {
|
||||
return ($me['Role']['perm_site_admin'] || $me['org_id'] == $row['EventReport']['orgc_id']) && $row['EventReport']['deleted'];
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var loadingSpanAnimation = '<span id="loadingSpan" class="fa fa-spin fa-spinner" style="margin-left: 5px;"></span>';
|
||||
$(function() {
|
||||
|
|
|
@ -11,12 +11,3 @@ echo $this->element('galaxyQuickViewNew', [
|
|||
'target_id' => $scope == 'event' ? $object['Event']['id'] : $object['Attribute']['id'],
|
||||
'target_type' => $scope
|
||||
]);
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var showContext = false;
|
||||
$(function () {
|
||||
$('.addGalaxy').click(function() {
|
||||
addGalaxyListener(this);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
<div class="confirmation">
|
||||
<?php
|
||||
echo $this->Form->create('Event', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => $baseurl . '/events/delete'));
|
||||
echo $this->Form->hidden('id');
|
||||
echo $this->Form->hidden('id');
|
||||
?>
|
||||
<legend><?php echo __('Event Deletion');?></legend>
|
||||
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
|
||||
<?php
|
||||
$message = __('Are you sure you want to delete ');
|
||||
if (count($idArray) > 1) {
|
||||
$message .= count($idArray) . ' Events?';
|
||||
$message = __('Are you sure you want to delete %s events?', count($idArray));
|
||||
} else {
|
||||
$message .= __(' Event #') . $idArray[0] . '?';
|
||||
$message = __('Are you sure you want to delete event #%s?', $idArray[0]);
|
||||
}
|
||||
?>
|
||||
<p><?php echo h($message); ?></p>
|
||||
<p><?= h($message); ?></p>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span class="btn btn-primary" title="<?php echo __('Accept');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept');?>" id="PromptYesButton" onClick="submitMassEventDelete();"><?php echo __('Yes');?></span>
|
||||
<button class="btn btn-primary" title="<?php echo __('Accept');?>" role="button" tabindex="0" aria-label="<?php echo __('Accept');?>" id="PromptYesButton"><?php echo __('Yes');?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
|
@ -27,7 +26,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -1,41 +1,40 @@
|
|||
<div class="confirmation">
|
||||
<?php
|
||||
echo $this->Form->create('Event', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => $baseurl . '/events/' . $type . '/' . $id));
|
||||
$extraTitle = "";
|
||||
if ($type == 'publish') $extraTitle = ' (no email)';
|
||||
$message = __('Publish Event%s', $extraTitle);
|
||||
echo $this->Form->create('Event', ['style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => $baseurl . '/events/' . $type . '/' . $id]);
|
||||
if ($type === 'unpublish') {
|
||||
$message = __('Unpublish Event%s', $extraTitle);
|
||||
$message = __('Unpublish Event');
|
||||
$buttonTitle = __('Unpublish');
|
||||
} else {
|
||||
$extraTitle = $type === 'publish' ? ' (no email)' : '';
|
||||
$message = __('Publish Event%s', $extraTitle);
|
||||
$buttonTitle = __('Publish');
|
||||
}
|
||||
?>
|
||||
|
||||
<legend><?php echo $message;?></legend>
|
||||
<legend><?= $message ?></legend>
|
||||
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
|
||||
<?php
|
||||
if ($type == 'alert') {
|
||||
echo '<p>' . __('Are you sure this event is complete and everyone should be informed?') . '</p>';
|
||||
<p><?php
|
||||
if ($type === 'alert') {
|
||||
echo __('Are you sure this event is complete and everyone should be informed?');
|
||||
} else if ($type === 'unpublish') {
|
||||
echo '<p>' . __('Are you sure you wish to unpublish the event?') . '</p>';
|
||||
echo __('Are you sure you wish to unpublish the event?');
|
||||
} else if ($type === 'publishSightings') {
|
||||
echo '<p>' . __('Are you sure you wish publish and synchronise all sightings attached to this event?') . '</p>';
|
||||
echo __('Are you sure you wish publish and synchronise all sightings attached to this event?');
|
||||
} else {
|
||||
echo '<p>' . __('Publish but do NOT send alert email? Only for minor changes!') . '</p>';
|
||||
echo __('Publish but do NOT send alert email? Only for minor changes!');
|
||||
}
|
||||
?>
|
||||
?></p>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span role="button" tabindex="0" aria-label="<?php echo __('Publish');?>" title="<?php echo __('Publish');?>" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish()"><?php echo __('Yes');?></span>
|
||||
<button role="button" tabindex="0" aria-label="<?= $buttonTitle ?>" title="<?= $buttonTitle ?>" id="PromptYesButton" class="btn btn-primary"><?= __('Yes') ?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<span role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();"><?php echo __('No');?></span>
|
||||
<span role="button" tabindex="0" aria-label="<?= __('Cancel');?>" title="<?= __('Cancel');?>" class="btn btn-inverse" id="PromptNoButton" onclick="cancelPrompt()"><?= __('No');?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span role="button" tabindex="0" aria-label="<?php echo __('Toggle correlation');?>" title="<?php echo __('Toggle correlation');?>" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish();"><?php echo __('Yes');?></span>
|
||||
<button role="button" tabindex="0" aria-label="<?php echo __('Toggle correlation');?>" title="<?php echo __('Toggle correlation');?>" id="PromptYesButton" class="btn btn-primary"><?php echo __('Yes');?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
|
@ -27,7 +27,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<p class="bold"><?php echo __('Check out the OpenAPI spec of the MISP Automation API <a href="%s">here</a>.', $baseurl . '/servers/openapi');?></p>
|
||||
<p><?php echo __('Automation functionality is designed to automatically feed other tools and systems with the data in your MISP repository.
|
||||
To to make this functionality available for automated tools an authentication key is used.');?>
|
||||
<br /><?php echo __('You can use the <a href="' . $baseurl . '/servers/rest">REST client</a> to test your API queries against your MISP and export the resulting tuned queries as curl or python scripts.');?>
|
||||
<br /><?php echo __('You can use the <a href="' . $baseurl . '/api/rest">REST client</a> to test your API queries against your MISP and export the resulting tuned queries as curl or python scripts.');?>
|
||||
<strong><?php echo __('Make sure you keep your API key secret as it gives access to the all of the data that you normally have access to in MISP.');?></strong>
|
||||
<?php echo __('To view the old MISP automation page, click <a href="' . $baseurl . '/automation/1">here</a>.');?>
|
||||
</p>
|
||||
|
|
|
@ -153,6 +153,12 @@
|
|||
'style' => 'display:none;width:424px;',
|
||||
'div' => false
|
||||
));
|
||||
echo $this->Form->input('searchall', array(
|
||||
'label' => false,
|
||||
'class' => 'input-large',
|
||||
'style' => 'display:none;width:424px;',
|
||||
'div' => false
|
||||
));
|
||||
?>
|
||||
<span id="addRuleButton" class="btn btn-inverse" style="margin-bottom:10px;display:none;"><?php echo __('Add');?></span>
|
||||
</div>
|
||||
|
@ -167,7 +173,7 @@
|
|||
<th style="width:10px;border:1px solid #cccccc;border-left:0px;text-align: left;"></th>
|
||||
</tr>
|
||||
<?php
|
||||
$fields = array('published', 'org', 'tag', 'date', 'eventinfo', 'eventid', 'threatlevel', 'analysis', 'distribution', 'sharinggroup', 'attribute', 'hasproposal', 'timestamp', 'publishtimestamp');
|
||||
$fields = array('published', 'org', 'tag', 'date', 'eventinfo', 'eventid', 'threatlevel', 'analysis', 'distribution', 'sharinggroup', 'attribute', 'hasproposal', 'timestamp', 'publishtimestamp', 'all');
|
||||
if ($isSiteAdmin) $fields[] = 'email';
|
||||
foreach ($fields as $k => $field):
|
||||
?>
|
||||
|
@ -242,9 +248,9 @@ var filtering = <?php echo $filtering; ?>;
|
|||
|
||||
var operators = ["<?php echo __('OR');?>", "<?php echo __('NOT');?>"];
|
||||
|
||||
var allFields = ["published", "tag", "date", "eventinfo", "eventid", "threatlevel", "distribution", "sharinggroup", "analysis", "attribute", "hasproposal", "timestamp", "publishtimestamp"];
|
||||
var allFields = ["published", "tag", "date", "eventinfo", "eventid", "threatlevel", "distribution", "sharinggroup", "analysis", "attribute", "hasproposal", "timestamp", "publishtimestamp", "all"];
|
||||
|
||||
var simpleFilters = ["tag", "eventinfo", "eventid", "threatlevel", "distribution", "sharinggroup", "analysis", "attribute"];
|
||||
var simpleFilters = ["tag", "eventinfo", "eventid", "threatlevel", "distribution", "sharinggroup", "analysis", "attribute", "all"];
|
||||
|
||||
var differentFilters = ["published", "date", "hasproposal", "timestamp", "publishtimestamp"];
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
<div class="freetext">
|
||||
<?php
|
||||
echo $this->Form->create('Attribute', array('id'));
|
||||
?>
|
||||
<?= $this->Form->create('Attribute', array('id')); ?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Freetext Import Tool'); ?></legend>
|
||||
<div class="add_attribute_fields">
|
||||
|
@ -9,35 +7,32 @@ echo $this->Form->create('Attribute', array('id'));
|
|||
<?php
|
||||
echo $this->Form->hidden('event_id');
|
||||
echo $this->Form->input('value', array(
|
||||
'type' => 'textarea',
|
||||
'error' => array('escape' => false),
|
||||
'div' => 'input clear',
|
||||
'class' => 'input-xxlarge',
|
||||
'label' => false
|
||||
'type' => 'textarea',
|
||||
'error' => array('escape' => false),
|
||||
'div' => 'input clear',
|
||||
'class' => 'input-xxlarge',
|
||||
'label' => false
|
||||
));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<p style="color:red;font-weight:bold;display:none;" id="warning-message"><?php echo __('Warning: You are about to share data that is of a classified nature (Attribution / targeting data). Make sure that you are authorised to share this.');?></p>
|
||||
<div class="overlay_spacing">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<button id="submitButton" class="btn btn-primary"><?php echo __('Submit');?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
<p style="color:red;font-weight:bold;display:none;text-align:center" id="warning-message"></p>
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<span class="btn btn-inverse" id="cancel_attribute_add"><?php echo __('Cancel');?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<div class="overlay_spacing">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<button id="submitButton" class="btn btn-primary"><?php echo __('Submit');?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
<p style="color:red;font-weight:bold;display:none;text-align:center" id="warning-message"></p>
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<span class="btn btn-inverse" id="cancel_attribute_add"><?php echo __('Cancel');?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -48,4 +43,3 @@ $(function() {
|
|||
$('#AttributeValue').focus();
|
||||
});
|
||||
</script>
|
||||
<?php echo $this->Js->writeBuffer(); // Write cached scripts
|
||||
|
|
|
@ -135,6 +135,7 @@
|
|||
'button' => __('Filter'),
|
||||
'placeholder' => __('Enter value to search'),
|
||||
'data' => '',
|
||||
'searchKey' => 'searcheventinfo',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
echo sprintf('<p class="bold red">%s</p>', $missingTldLists);
|
||||
}
|
||||
?>
|
||||
<p></p>
|
||||
<?php
|
||||
$instanceDefault = 5;
|
||||
if (!empty(Configure::read('MISP.default_attribute_distribution'))) {
|
||||
|
@ -22,36 +21,36 @@
|
|||
echo $this->Form->create('Attribute', array('url' => $baseurl . '/events/saveFreeText/' . $event['Event']['id'], 'class' => 'mainForm'));
|
||||
if ($isSiteAdmin) {
|
||||
echo $this->Form->input('force', array(
|
||||
'checked' => false,
|
||||
'label' => __('Proposals instead of attributes'),
|
||||
'checked' => false,
|
||||
'label' => __('Proposals instead of attributes'),
|
||||
));
|
||||
}
|
||||
echo $this->Form->input('JsonObject', array(
|
||||
'label' => false,
|
||||
'type' => 'text',
|
||||
'style' => 'display:none;',
|
||||
'value' => '',
|
||||
'label' => false,
|
||||
'type' => 'text',
|
||||
'style' => 'display:none;',
|
||||
'value' => '',
|
||||
));
|
||||
echo $this->Form->input('default_comment', array(
|
||||
'label' => false,
|
||||
'type' => 'text',
|
||||
'style' => 'display:none;',
|
||||
'value' => $importComment,
|
||||
'label' => false,
|
||||
'type' => 'text',
|
||||
'style' => 'display:none;',
|
||||
'value' => $importComment,
|
||||
));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<tr>
|
||||
<th><?php echo __('Value');?></th>
|
||||
<th><?php echo __('Similar Attributes');?></th>
|
||||
<th><?php echo __('Category');?></th>
|
||||
<th><?php echo __('Type');?></th>
|
||||
<th><?php echo __('IDS');?><input type="checkbox" id="checkAllIDS" style="margin-top:0;margin-left:.3em"></th>
|
||||
<th style="text-align:center;"><?php echo __('Disable Correlation');?><input type="checkbox" id="checkAllDC" style="margin-top:0;margin-left:.3em"></th>
|
||||
<th><?php echo __('Distribution');?></th>
|
||||
<th><?php echo __('Comment');?></th>
|
||||
<th><?php echo __('Tags (separated by comma)');?></th>
|
||||
<th><?php echo __('Actions');?></th>
|
||||
<th><?php echo __('Value');?></th>
|
||||
<th><?php echo __('Similar Attributes');?></th>
|
||||
<th><?php echo __('Category');?></th>
|
||||
<th><?php echo __('Type');?></th>
|
||||
<th><?php echo __('IDS');?><input type="checkbox" id="checkAllIDS" style="margin-top:0;margin-left:.3em"></th>
|
||||
<th style="text-align:center;"><?php echo __('Disable Correlation');?><input type="checkbox" id="checkAllDC" style="margin-top:0;margin-left:.3em"></th>
|
||||
<th><?php echo __('Distribution');?></th>
|
||||
<th><?php echo __('Comment');?></th>
|
||||
<th><?php echo __('Tags (separated by comma)');?></th>
|
||||
<th><?php echo __('Actions');?></th>
|
||||
</tr>
|
||||
<?php
|
||||
$options = array();
|
||||
|
@ -60,31 +59,31 @@
|
|||
<tr id="row_<?php echo $k; ?>" class="freetext_row">
|
||||
<?php
|
||||
echo $this->Form->input('Attribute' . $k . 'Save', array(
|
||||
'label' => false,
|
||||
'style' => 'display:none;',
|
||||
'value' => 1,
|
||||
'label' => false,
|
||||
'style' => 'display:none;',
|
||||
'value' => 1,
|
||||
));
|
||||
echo $this->Form->input('Attribute' . $k . 'Data', array(
|
||||
'label' => false,
|
||||
'type' => 'hidden',
|
||||
'value' => isset($item['data']) ? $item['data'] : false,
|
||||
'label' => false,
|
||||
'type' => 'hidden',
|
||||
'value' => isset($item['data']) ? $item['data'] : false,
|
||||
));
|
||||
echo $this->Form->input('Attribute' . $k . 'DataIsHandled', array(
|
||||
'label' => false,
|
||||
'type' => 'hidden',
|
||||
'value' => isset($item['data_is_handled']) ? h($item['data_is_handled']) : false,
|
||||
'label' => false,
|
||||
'type' => 'hidden',
|
||||
'value' => isset($item['data_is_handled']) ? h($item['data_is_handled']) : false,
|
||||
));
|
||||
?>
|
||||
<td>
|
||||
<?php
|
||||
echo $this->Form->input('Attribute' . $k . 'Value', array(
|
||||
'label' => false,
|
||||
'value' => $item['value'],
|
||||
'style' => 'padding:0px;height:20px;margin-bottom:0px;width:90%;min-width:400px;',
|
||||
'div' => false
|
||||
'label' => false,
|
||||
'value' => $item['value'],
|
||||
'style' => 'padding:0px;height:20px;margin-bottom:0px;width:90%;min-width:400px;',
|
||||
'div' => false
|
||||
));
|
||||
?>
|
||||
<input type="hidden" id="<?php echo 'Attribute' . $k . 'Save'; ?>" value=1 >
|
||||
<input type="hidden" id="<?php echo 'Attribute' . $k . 'Save'; ?>" value="1">
|
||||
</td>
|
||||
<td class="shortish">
|
||||
<?php
|
||||
|
@ -129,8 +128,8 @@
|
|||
if (isset($item['categories']) && !in_array($category, $item['categories'])) {
|
||||
continue;
|
||||
}
|
||||
echo '<option value="' . $category . '" ';
|
||||
if ($category == $default) echo 'selected="selected"';
|
||||
echo '<option';
|
||||
if ($category == $default) echo ' selected="selected"';
|
||||
echo '>' . $category . '</option>';
|
||||
}
|
||||
?>
|
||||
|
@ -140,33 +139,35 @@
|
|||
<?php
|
||||
$divVisibility = '';
|
||||
$selectVisibility = '';
|
||||
if (count($item['types']) == 1) {
|
||||
if (count($item['types']) === 1) {
|
||||
$selectVisibility = 'display:none;';
|
||||
} else {
|
||||
$divVisibility = 'style="display:none;"';
|
||||
if (!in_array(array_keys($item['types']), $options)) $options[] = array_values($item['types']);
|
||||
if (!in_array($item['types'], $options)) {
|
||||
$options[] = $item['types'];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div id = "<?php echo 'Attribute' . $k . 'TypeStatic'; ?>" <?php echo $divVisibility; ?> ><?php echo h($item['default_type']); ?></div>
|
||||
<select id = "<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='padding:0px;height:20px;margin-bottom:0px;<?php echo $selectVisibility; ?>'>
|
||||
<div id="<?php echo 'Attribute' . $k . 'TypeStatic'; ?>" <?php echo $divVisibility; ?> ><?php echo h($item['default_type']); ?></div>
|
||||
<select id="<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='padding:0px;height:20px;margin-bottom:0px;<?php echo $selectVisibility; ?>'>
|
||||
<?php
|
||||
if (!empty($item['types'])) {
|
||||
foreach ($item['types'] as $type) {
|
||||
echo '<option value="' . h($type) . '" ';
|
||||
echo ($type == $item['default_type'] ? 'selected="selected"' : '') . '>' . h($type) . '</option>';
|
||||
echo '<option';
|
||||
echo ($type === $item['default_type'] ? ' selected="selected"' : '') . '>' . h($type) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</td>
|
||||
<td class="short" style="width:40px;text-align:center;">
|
||||
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'To_ids'; ?>" <?php if ($item['to_ids']) echo 'checked'; ?> class="idsCheckbox" />
|
||||
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'To_ids'; ?>" <?php if ($item['to_ids']) echo 'checked'; ?> class="idsCheckbox">
|
||||
</td>
|
||||
<td class="short" style="width:40px;text-align:center;">
|
||||
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'Disable_correlation'; ?>" <?php if (isset($item['disable_correlation']) && $item['disable_correlation']) echo 'checked'; ?> class="dcCheckbox" />
|
||||
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'Disable_correlation'; ?>" <?php if (!empty($item['disable_correlation'])) echo 'checked'; ?> class="dcCheckbox">
|
||||
</td>
|
||||
<td class="short" style="width:40px;text-align:center;">
|
||||
<select id = "<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle' style='padding:0px;height:20px;margin-bottom:0px;'>
|
||||
<select id="<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle' style='padding:0px;height:20px;margin-bottom:0px;'>
|
||||
<?php
|
||||
foreach ($distributions as $distKey => $distValue) {
|
||||
$default = isset($item['distribution']) ? $item['distribution'] : $instanceDefault;
|
||||
|
@ -176,7 +177,7 @@
|
|||
?>
|
||||
</select>
|
||||
<div style="display:none;">
|
||||
<select id = "<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
|
||||
<select id="<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
|
||||
<?php
|
||||
foreach ($sgs as $sgKey => $sgValue) {
|
||||
echo '<option value="' . h($sgKey) . '">' . h($sgValue) . '</option>';
|
||||
|
@ -186,13 +187,13 @@
|
|||
</div>
|
||||
</td>
|
||||
<td class="short">
|
||||
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>/>
|
||||
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>>
|
||||
</td>
|
||||
<td class="short">
|
||||
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>/>
|
||||
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>>
|
||||
</td>
|
||||
<td class="action short">
|
||||
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onClick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onclick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
|
@ -209,7 +210,7 @@
|
|||
?>
|
||||
</table>
|
||||
<span>
|
||||
<button class="btn btn-primary" style="float:left;" onClick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', '<?php echo count($resultArray); ?>');"><?php echo __('Submit %s', $scope);?></button>
|
||||
<button class="btn btn-primary" style="float:left;" onclick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', <?= count($resultArray) ?>);"><?php echo __('Submit %s', $scope);?></button>
|
||||
<span style="float:right">
|
||||
<?php
|
||||
if (!empty($optionsRearranged)):
|
||||
|
@ -229,7 +230,7 @@
|
|||
$keys = array_keys($optionsRearranged);
|
||||
foreach ($optionsRearranged[$keys[0]] as $toElement):
|
||||
?>
|
||||
<option value="<?php echo $toElement; ?>"><?php echo $toElement; ?></option>
|
||||
<option><?php echo $toElement; ?></option>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
|
@ -244,7 +245,7 @@
|
|||
<script>
|
||||
var options = <?php echo json_encode($optionsRearranged);?>;
|
||||
var typeCategoryMapping = <?php echo json_encode($typeCategoryMapping); ?>;
|
||||
$(document).ready(function() {
|
||||
$(function() {
|
||||
popoverStartup();
|
||||
$('.typeToggle').on('change', function() {
|
||||
var currentId = $(this).attr('id');
|
||||
|
@ -266,9 +267,10 @@
|
|||
}
|
||||
}
|
||||
*/
|
||||
$('#' + currentId).empty();
|
||||
var $categorySelect = $('#' + currentId);
|
||||
$categorySelect.empty();
|
||||
for (var category in currentOptions) {
|
||||
$('#' + currentId).append($("<option></option>").attr("value", category).text(category));
|
||||
$categorySelect.append(new Option(category, category));
|
||||
}
|
||||
});
|
||||
<?php
|
||||
|
@ -276,16 +278,15 @@
|
|||
?>
|
||||
$('#changeFrom').change(function(){
|
||||
changeFreetextImportFrom();
|
||||
});
|
||||
$('#changeFrom').trigger('change');
|
||||
}).trigger('change');
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
$('#checkAllIDS').change(function() {
|
||||
$('.idsCheckbox').prop('checked', $('#checkAllIDS').is(':checked'));
|
||||
$('.idsCheckbox').prop('checked', $(this).is(':checked'));
|
||||
});
|
||||
$('#checkAllDC').change(function() {
|
||||
$('.dcCheckbox').prop('checked', $('#checkAllDC').is(':checked'));
|
||||
$('.dcCheckbox').prop('checked', $(this).is(':checked'));
|
||||
});
|
||||
$('.distributionToggle').change(function() {
|
||||
if ($(this).val() == 4) {
|
||||
|
@ -296,6 +297,4 @@
|
|||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'freetextResults'));
|
||||
?>
|
||||
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'freetextResults'));
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
<?php
|
||||
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
|
||||
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
|
||||
$menuData = array_merge($menuData, ['mayPublish' => $mayPublish, 'mayModify' => $mayModify]);
|
||||
$scripts = ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph'];
|
||||
echo $this->element('genericElements/assetLoader', array(
|
||||
echo $this->element('genericElements/assetLoader', [
|
||||
'css' => ['query-builder.default', 'attack_matrix'],
|
||||
'js' => ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph']
|
||||
));
|
||||
'js' => ['doT', 'extendext', 'moment.min', 'query-builder', 'network-distribution-graph', 'd3', 'd3.custom'],
|
||||
]);
|
||||
echo $this->element(
|
||||
'genericElements/SingleViews/single_view',
|
||||
[
|
||||
'title' => ($extended ? '[' . __('Extended view') . '] ' : '') . h(nl2br($event['Event']['info'])),
|
||||
'title' => ($extended ? '[' . __('Extended view') . '] ' : '') . h(nl2br($event['Event']['info'], false)),
|
||||
'data' => $event,
|
||||
'fields' => [
|
||||
[
|
||||
|
@ -182,7 +178,7 @@
|
|||
],
|
||||
[
|
||||
'key' => __('#Attributes'),
|
||||
'raw' => $attribute_count . __n(' (%s Object)', ' (%s Objects)', $object_count, h($object_count))
|
||||
'raw' => __n('%s (%s Object)', '%s (%s Objects)', $object_count, $attribute_count, h($object_count))
|
||||
],
|
||||
[
|
||||
'key' => __('First recorded change'),
|
||||
|
@ -195,7 +191,7 @@
|
|||
[
|
||||
'key' => __('Modification map'),
|
||||
'type' => 'element',
|
||||
'element' => 'sparkline',
|
||||
'element' => 'sparkline_new',
|
||||
'element_params' => [
|
||||
'scope' => 'modification',
|
||||
'id' => $event['Event']['id'],
|
||||
|
@ -231,7 +227,7 @@
|
|||
[
|
||||
'key' => __('Activity'),
|
||||
'type' => 'element',
|
||||
'element' => 'sparkline',
|
||||
'element' => 'sparkline_new',
|
||||
'element_params' => [
|
||||
'scope' => 'event',
|
||||
'id' => $event['Event']['id'],
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span role="button" tabindex="0" aria-label="Publish" title="Publish" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish()">Yes</span>
|
||||
<button role="button" tabindex="0" aria-label="Publish" title="Publish" id="PromptYesButton" class="btn btn-primary">Yes</button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
|
@ -18,7 +18,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span role="button" tabindex="0" aria-label="<?php echo __('Publish');?>" title="<?php echo __('Publish');?>" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish()"><?php echo __('Yes');?></span>
|
||||
<button role="button" tabindex="0" aria-label="<?php echo __('Publish');?>" title="<?php echo __('Publish');?>" id="PromptYesButton" class="btn btn-primary"><?php echo __('Yes');?></button>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
|
@ -32,7 +32,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?= $this->Form->end(); ?>
|
||||
</div>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue