mirror of https://github.com/MISP/MISP
Merge branch '2.4' into issues_1643
commit
f24682f86a
|
@ -1,6 +1,9 @@
|
|||
/vendors
|
||||
/app/Vendor
|
||||
/app/composer*
|
||||
!/app/composer.phar
|
||||
!/app/composer.license
|
||||
/app/composer.json
|
||||
/lib
|
||||
/.project
|
||||
/.settings
|
||||
|
@ -9,7 +12,6 @@
|
|||
.DS_Store
|
||||
/.htaccess
|
||||
/app/Vendor
|
||||
/app/composer*
|
||||
/README
|
||||
/app/tmp/GPG*
|
||||
/app/tmp/sessions/sess_*
|
||||
|
|
4
AUTHORS
4
AUTHORS
|
@ -9,10 +9,11 @@ Contributors
|
|||
|
||||
Aaron Kaplan
|
||||
Airbus Group CERT (AiG CERT)
|
||||
Alexander J
|
||||
Alexander Jaeger
|
||||
Alexandre Dulaunoy
|
||||
Alexandru Ciobanu
|
||||
Andras Iklody
|
||||
Andreas Ziegler
|
||||
Andrzej Dereszowski
|
||||
Bâkır Emre
|
||||
Chris Clark
|
||||
|
@ -34,6 +35,7 @@ Copyright (C) 2012 Belgian Defence
|
|||
Copyright (C) 2012 NATO / NCIRC
|
||||
Copyright (C) 2013-2016 Andras Iklody
|
||||
Copyright (C) 2015-2016 CIRCL - Computer Incident Response Center Luxembourg
|
||||
Copyright (C) 2016 Andreas Ziegler
|
||||
|
||||
MISP is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE version 3.
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
curl -s https://getcomposer.org/installer | php
|
||||
php composer.phar require kamisama/cake-resque:4.1.2
|
||||
php composer.phar config vendor-dir Vendor
|
||||
php composer.phar install
|
||||
|
@ -138,8 +137,14 @@ service apache2 reload
|
|||
# We seriously recommend using only SSL !
|
||||
# Check out the /var/www/MISP/INSTALL/apache.misp.ssl file for an example
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
cd /var/www/MISP/app/Config
|
||||
|
|
|
@ -42,7 +42,7 @@ sudo a2dissite 000-default
|
|||
sudo a2ensite default-ssl
|
||||
|
||||
# Install PHP and dependencies
|
||||
sudo apt-get install libapache2-mod-php5 php5 php5-cli php-crypt-gpg php5-dev php5-json php5-mysql php5-readline php5-redis
|
||||
sudo apt-get install libapache2-mod-php5 php5 php5-cli php-crypt-gpg php5-dev php5-json php5-xml php5-mysql php5-readline php5-redis
|
||||
|
||||
# Apply all changes
|
||||
sudo systemctl restart apache2
|
||||
|
@ -86,7 +86,6 @@ sudo -u www-data git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
sudo -u www-data wget https://getcomposer.org/download/1.2.1/composer.phar -O composer.phar
|
||||
sudo -u www-data php composer.phar require kamisama/cake-resque:4.1.2
|
||||
sudo -u www-data php composer.phar config vendor-dir Vendor
|
||||
sudo -u www-data php composer.phar install
|
||||
|
@ -184,8 +183,14 @@ sudo a2ensite misp-ssl
|
|||
# Restart apache
|
||||
sudo systemctl restart apache2
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php
|
||||
|
|
|
@ -27,7 +27,7 @@ Once the system is installed you can perform the following steps as root:
|
|||
apt-get install vim
|
||||
|
||||
# Install the dependencies:
|
||||
apt-get install gcc zip php-pear git redis-server make python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev php5-dev libapache2-mod-php5 php5-mysql php5-json php5-redis curl gnupg-agent
|
||||
apt-get install gcc zip php-pear git redis-server make python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev php5-dev php5-xml libapache2-mod-php5 php5-mysql php5-json php5-redis curl gnupg-agent
|
||||
pear install Crypt_GPG # we need version >1.3.0
|
||||
|
||||
3/ MISP code
|
||||
|
@ -67,7 +67,6 @@ git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
curl -s https://getcomposer.org/installer | php
|
||||
php composer.phar require kamisama/cake-resque:4.1.2
|
||||
php composer.phar config vendor-dir Vendor
|
||||
php composer.phar install
|
||||
|
@ -129,8 +128,14 @@ service apache2 reload
|
|||
# We seriously recommend using only SSL !
|
||||
# Check out the apache.misp.ssl file for an example
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
cd /var/www/MISP/app/Config
|
||||
|
|
|
@ -43,7 +43,7 @@ sudo a2dissite 000-default
|
|||
sudo a2ensite default-ssl
|
||||
|
||||
# Install PHP and dependencies
|
||||
sudo apt-get install libapache2-mod-php php php-cli php-crypt-gpg php-dev php-json php-mysql php-opcache php-readline php-redis
|
||||
sudo apt-get install libapache2-mod-php php php-cli php-crypt-gpg php-dev php-json php-mysql php-opcache php-readline php-redis php-xml
|
||||
|
||||
# Apply all changes
|
||||
sudo systemctl restart apache2
|
||||
|
@ -87,7 +87,6 @@ sudo -u www-data git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
sudo -u www-data wget https://getcomposer.org/download/1.2.1/composer.phar -O composer.phar
|
||||
sudo -u www-data php composer.phar require kamisama/cake-resque:4.1.2
|
||||
sudo -u www-data php composer.phar config vendor-dir Vendor
|
||||
sudo -u www-data php composer.phar install
|
||||
|
@ -185,8 +184,14 @@ sudo a2ensite misp-ssl
|
|||
# Restart apache
|
||||
sudo systemctl restart apache2
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php
|
||||
|
|
|
@ -39,6 +39,23 @@ CREATE TABLE IF NOT EXISTS `attributes` (
|
|||
UNIQUE INDEX `uuid` (`uuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- -------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `attribute_tags`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `attribute_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`attribute_id` int(11) NOT NULL,
|
||||
`event_id` int(11) NOT NULL,
|
||||
`tag_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `attribute_id` (`attribute_id`),
|
||||
INDEX `event_id` (`event_id`),
|
||||
INDEX `tag_id` (`tag_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
|
|
|
@ -39,6 +39,23 @@ CREATE INDEX idx_attributes_sharing_group_id ON attributes (sharing_group_id);
|
|||
CREATE INDEX idx_attributes_value1 ON attributes (value1);
|
||||
CREATE INDEX idx_attributes_value2 ON attributes (value2);
|
||||
|
||||
-- -------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table attribute_tags
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS attribute_tags (
|
||||
id bigserial NOT NULL,
|
||||
attribute_id bigint NOT NULL,
|
||||
event_id bigint NOT NULL,
|
||||
tag_id bigint NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
CREATE INDEX idx_attribute_tags_attribute_id ON attribute_tags (attribute_id);
|
||||
CREATE INDEX idx_attribute_tags_event_id ON attribute_tags (event_id);
|
||||
CREATE INDEX idx_attribute_tags_tag_id ON attribute_tags (tag_id);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/var/www/MISP/app/tmp/logs/resque-*-error.log {
|
||||
rotate 30
|
||||
dateext
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
weekly
|
||||
copytruncate
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
module misplogrotate 1.0;
|
||||
require {
|
||||
type logrotate_t;
|
||||
type httpd_sys_content_t;
|
||||
class dir { ioctl read getattr lock search open };
|
||||
}
|
||||
#============= logrotate_t ==============
|
||||
allow logrotate_t httpd_sys_content_t:dir { ioctl read getattr lock search open };
|
|
@ -33,7 +33,7 @@ yum install vim
|
|||
yum install gcc git httpd zip redis mysql-server python-devel python-pip libxslt-devel zlib-devel
|
||||
|
||||
# Install PHP 5.6 from SCL, see https://www.softwarecollections.org/en/scls/rhscl/rh-php56/
|
||||
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-bcmath
|
||||
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-php-xml rh-php56-bcmath
|
||||
|
||||
# rh-php56-php only provided mod_php for httpd24-httpd from SCL
|
||||
# if we want to use httpd from CentOS base we can use rh-php56-php-fpm instead
|
||||
|
@ -99,7 +99,6 @@ git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
curl -s https://getcomposer.org/installer | php
|
||||
php composer.phar require kamisama/cake-resque:4.1.2
|
||||
php composer.phar config vendor-dir Vendor
|
||||
php composer.phar install
|
||||
|
@ -177,8 +176,14 @@ service iptables save
|
|||
# We seriously recommend using only SSL !
|
||||
# Check out the apache.misp.ssl file for an example
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
cd /var/www/MISP/app/Config
|
||||
|
|
|
@ -31,7 +31,7 @@ yum install centos-release-scl
|
|||
yum install gcc git httpd zip redis mariadb mariadb-server python-devel python-pip libxslt-devel zlib-devel
|
||||
|
||||
# Install PHP 5.6 from SCL, see https://www.softwarecollections.org/en/scls/rhscl/rh-php56/
|
||||
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-bcmath
|
||||
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-php-xml rh-php56-php-bcmath
|
||||
|
||||
# rh-php56-php only provided mod_php for httpd24-httpd from SCL
|
||||
# if we want to use httpd from CentOS base we can use rh-php56-php-fpm instead
|
||||
|
@ -102,7 +102,6 @@ git submodule update
|
|||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
curl -s https://getcomposer.org/installer | php
|
||||
php composer.phar require kamisama/cake-resque:4.1.2
|
||||
php composer.phar config vendor-dir Vendor
|
||||
php composer.phar install
|
||||
|
@ -194,8 +193,24 @@ firewall-cmd --reload
|
|||
# Add SSL support by running: yum install mod_ssl
|
||||
# Check out the apache.misp.ssl file for an example
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of it's workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
8/ MISP configuration
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
# Now make logrotate work under SELinux as well
|
||||
# Allow logrotate to modify the log files
|
||||
semanage fcontext -a -t httpd_log_t "/var/www/MISP/app/tmp/logs(/.*)?"
|
||||
chcon -R -t httpd_log_t /var/www/MISP/app/tmp/logs
|
||||
|
||||
# Allow logrotate to read /var/www
|
||||
checkmodule -M -m -o /tmp/misplogrotate.mod INSTALL/misplogrotate.te
|
||||
semodule_package -o /tmp/misplogrotate.pp -m /tmp/misplogrotate.mod
|
||||
semodule -i /tmp/misplogrotate.pp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
cd /var/www/MISP/app/Config
|
||||
|
@ -206,7 +221,7 @@ cp -a config.default.php config.php
|
|||
|
||||
# Configure the fields in the newly created files:
|
||||
# config.php : baseurl (example: 'baseurl' => 'http://misp',) - don't use "localhost" it causes issues when browsing externally
|
||||
# config.php : Uncomment and set the timezone: `// date_default_timezone_set('UTC');`
|
||||
# core.php : Uncomment and set the timezone: `// date_default_timezone_set('UTC');`
|
||||
# database.php : login, port, password, database
|
||||
|
||||
# Important! Change the salt key in /var/www/MISP/app/Config/config.php
|
||||
|
|
2
PyMISP
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit 0511bd44867f5f7f74cb54d61b0df7d99b719118
|
||||
Subproject commit 26a8f4c66230c0df10b2f9637e53ee1542a26f40
|
39
README.md
39
README.md
|
@ -1,12 +1,36 @@
|
|||
[![Build Status](https://travis-ci.org/MISP/MISP.svg?branch=2.4)](https://travis-ci.org/MISP/MISP)
|
||||
|
||||
MISP - Malware Information Sharing Platform and Threat Sharing
|
||||
--------------------------------------------------------------
|
||||
|
||||
[![Join the chat at https://gitter.im/MISP/MISP](https://badges.gitter.im/MISP/MISP.svg)](https://gitter.im/MISP/MISP?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
![logo](./INSTALL/logos/misp-logo.png?raw=true "MISP")
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Latest Release</td>
|
||||
<td><a href="https://badge.fury.io/gh/MISP%2FMISP"><img src="https://badge.fury.io/gh/MISP%2FMISP.svg" alt="GitHub version" height="18"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Travis</td>
|
||||
<td><a href="https://travis-ci.org/MISP/MISP.svg?branch=2.4"><img src="https://img.shields.io/travis/MISP/MISP/2.4.svg" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gitter</td>
|
||||
<td><a href="https://gitter.im/MISP/MISP?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img src="https://badges.gitter.im/MISP/MISP.svg" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Twitter</td>
|
||||
<td><a href="https://twitter.com/MISPProject"><img src="https://img.shields.io/twitter/follow/MISPProject.svg?style=social&label=Follow" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Contributors</td>
|
||||
<td><img src="https://img.shields.io/github/contributors/MISP/MISP.svg" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>License</td>
|
||||
<td><img src="https://img.shields.io/github/license/MISP/MISP.svg" /></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
MISP, Malware Information Sharing Platform and Threat Sharing, is an open source software solution for collecting, storing, distributing and sharing cyber security indicators and threat about cyber security incidents analysis and malware analysis. MISP is designed by and for incident analysts, security and ICT professionals or malware reverser to support their day-to-day operations to share structured informations efficiently.
|
||||
|
||||
The objective of MISP is to foster the sharing of structured information within the security community and abroad. MISP provides functionalities to support the exchange of information but also the consumption of the information by Network Detection Intrusion System (NIDS), LIDS but also log analysis tools, SIEMs.
|
||||
|
@ -56,6 +80,8 @@ For installation guide see [INSTALL](https://github.com/MISP/MISP/tree/2.4/INSTA
|
|||
Contributing
|
||||
------------
|
||||
|
||||
Please see our [Code of conduct](code_of_conduct.md).
|
||||
|
||||
Feel free to fork the code, play with it, make some patches and send us the pull requests via the [issues](https://github.com/MISP/MISP/issues).
|
||||
|
||||
Feel free to contact us, create [issues](https://github.com/MISP/MISP/issues), if you have questions, remarks or bug reports.
|
||||
|
@ -84,7 +110,8 @@ This software is licensed under [GNU Affero General Public License version 3](ht
|
|||
* Copyright (C) 2012 Christophe Vandeplas
|
||||
* Copyright (C) 2012 Belgian Defence
|
||||
* Copyright (C) 2012 NATO / NCIRC
|
||||
* Copyright (C) 2013-2016 Andras Iklody
|
||||
* Copyright (C) 2015-2016 CIRCL - Computer Incident Response Center Luxembourg
|
||||
* Copyright (C) 2013-2017 Andras Iklody
|
||||
* Copyright (C) 2015-2017 CIRCL - Computer Incident Response Center Luxembourg
|
||||
* Copyright (C) 2016 Andreas Ziegler
|
||||
|
||||
For more information, [the list of authors and contributors](AUTHORS) is available.
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":59}
|
||||
{"major":2, "minor":4, "hotfix":65}
|
||||
|
|
|
@ -30,6 +30,8 @@ $config = array(
|
|||
'default_attribute_distribution' => 'event',
|
||||
'tagging' => true,
|
||||
'full_tags_on_event_index' => true,
|
||||
'attribute_tagging' => true,
|
||||
'full_tags_on_attribute_index' => true,
|
||||
'footer_logo' => '',
|
||||
'take_ownership_xml_import' => false,
|
||||
'unpublishedprivate' => false,
|
||||
|
|
|
@ -177,7 +177,7 @@ define('LOG_ERROR', LOG_ERR);
|
|||
*/
|
||||
Configure::write('Session', array(
|
||||
'timeout' => 60, // Session timeout, default is 1 hour
|
||||
'defaults' => 'database',
|
||||
'defaults' => 'php',
|
||||
'autoRegenerate' => true
|
||||
));
|
||||
|
||||
|
|
|
@ -70,6 +70,6 @@ class DATABASE_CONFIG {
|
|||
'password' => 'db password',
|
||||
'database' => 'misp',
|
||||
'prefix' => '',
|
||||
//'encoding' => 'utf8',
|
||||
'encoding' => 'utf8',
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
App::uses('AppShell', 'Console/Command');
|
||||
class AdminShell extends AppShell
|
||||
{
|
||||
public $uses = array('Event');
|
||||
public $uses = array('Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Whitelist', 'Server', 'Organisation');
|
||||
|
||||
public function jobGenerateCorrelation() {
|
||||
$jobId = $this->args[0];
|
||||
|
@ -45,4 +45,17 @@ class AdminShell extends AppShell
|
|||
$this->Job->saveField('message', 'Job done.');
|
||||
$this->Job->saveField('status', 4);
|
||||
}
|
||||
|
||||
public function prune_update_logs() {
|
||||
$jobId = $this->args[0];
|
||||
$user_id = $this->args[1];
|
||||
$user = $this->User->getAuthUser($user_id);
|
||||
$this->loadModel('Job');
|
||||
$this->Job->id = $jobId;
|
||||
$this->loadModel('Log');
|
||||
$this->Log->pruneUpdateLogs($jobId, $user);
|
||||
$this->Job->saveField('progress', 100);
|
||||
$this->Job->saveField('message', 'Job done.');
|
||||
$this->Job->saveField('status', 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -347,6 +347,7 @@ class EventShell extends AppShell
|
|||
$file = new File($dir->pwd() . DS . 'misp.bro.' . $user['Organisation']['name'] . '.intel');
|
||||
}
|
||||
|
||||
$file->write('');
|
||||
foreach ($types as $k => $type) {
|
||||
$final = $this->Attribute->bro($user, $type);
|
||||
foreach ($final as $attribute) {
|
||||
|
|
|
@ -39,11 +39,13 @@ class UserInitShell extends AppShell {
|
|||
}
|
||||
|
||||
if ($this->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$org = array('Organisation' => array(
|
||||
'id' => 1,
|
||||
'name' => !empty(Configure::read('MISP.org')) ? Configure::read('MISP.org') : 'ADMIN',
|
||||
'description' => 'Automatically generated admin organisation',
|
||||
'type' => 'ADMIN',
|
||||
'date_created' => $date,
|
||||
'uuid' => CakeText::uuid(),
|
||||
'local' => 1
|
||||
));
|
||||
|
|
|
@ -46,9 +46,10 @@ class AppController extends Controller {
|
|||
|
||||
public $helpers = array('Utility');
|
||||
|
||||
private $__jsVersion = '2.4.58';
|
||||
private $__jsVersion = '2.4.62';
|
||||
public $pyMispVersion = '2.4.65';
|
||||
public $phpmin = '5.5.9';
|
||||
public $phprec = '5.6.0';
|
||||
public $phprec = '7.0.0';
|
||||
|
||||
// Used for _isAutomation(), a check that returns true if the controller & action combo matches an action that is a non-xml and non-json automation method
|
||||
// This is used to allow authentication via headers for methods not covered by _isRest() - as that only checks for JSON and XML formats
|
||||
|
@ -81,6 +82,11 @@ class AppController extends Controller {
|
|||
public function beforeFilter() {
|
||||
// check for a supported datasource configuration
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
if (!isset($dataSourceConfig['encoding'])) {
|
||||
$db = ConnectionManager::getDataSource('default');
|
||||
$db->setConfig(array('encoding' => 'utf8'));
|
||||
ConnectionManager::create('default', $db->config);
|
||||
}
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
if ($dataSource != 'Database/Mysql' && $dataSource != 'Database/Postgres') {
|
||||
throw new Exception('datasource not supported: ' . $dataSource);
|
||||
|
|
|
@ -63,6 +63,9 @@ class AttributesController extends AppController {
|
|||
'Orgc' => array('fields' => array('id', 'name'))
|
||||
)
|
||||
);
|
||||
if (!$this->_isRest()) {
|
||||
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
|
||||
}
|
||||
$this->set('isSearch', 0);
|
||||
$this->set('attributes', $this->paginate());
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
|
@ -235,7 +238,7 @@ class AttributesController extends AppController {
|
|||
$message .= '[' . $k . ']: ' . $v[0] . PHP_EOL;
|
||||
}
|
||||
throw new NotFoundException('Could not save the attribute. ' . $message);
|
||||
} else if ($this->request->is('ajax')) {
|
||||
} else if ($this->request->is('ajax')) {
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $this->Attribute->validationErrors)),'status'=>200));
|
||||
} else {
|
||||
|
@ -252,6 +255,11 @@ class AttributesController extends AppController {
|
|||
|
||||
// combobox for types
|
||||
$types = array_keys($this->Attribute->typeDefinitions);
|
||||
foreach ($types as $key => $value) {
|
||||
if (in_array($value, array('malware-sample', 'attachment'))) {
|
||||
unset($types[$key]);
|
||||
}
|
||||
}
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
|
@ -714,7 +722,7 @@ class AttributesController extends AppController {
|
|||
$saved_attribute = $this->Attribute->find('first', array(
|
||||
'conditions' => array('id' => $this->Attribute->id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'type', 'to_ids', 'category', 'uuid', 'event_id', 'distribution', 'timestamp', 'comment', 'value'),
|
||||
'fields' => array('id', 'type', 'to_ids', 'category', 'uuid', 'event_id', 'distribution', 'timestamp', 'comment', 'value', 'disable_correlation'),
|
||||
));
|
||||
$response = array('response' => array('Attribute' => $saved_attribute['Attribute']));
|
||||
$this->set('response', $response);
|
||||
|
@ -744,6 +752,11 @@ class AttributesController extends AppController {
|
|||
// needed for RBAC
|
||||
// combobox for types
|
||||
$types = array_keys($this->Attribute->typeDefinitions);
|
||||
foreach ($types as $key => $value) {
|
||||
if (in_array($value, array('malware-sample', 'attachment'))) {
|
||||
unset($types[$key]);
|
||||
}
|
||||
}
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
|
@ -851,9 +864,16 @@ class AttributesController extends AppController {
|
|||
throw new NotFoundException('Invalid attribute');
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true));
|
||||
$conditions = array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true);
|
||||
$conditions['includeAllTags'] = false;
|
||||
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), $conditions);
|
||||
if (empty($attribute)) throw new MethodNotAllowedException('Invalid attribute');
|
||||
$attribute = $attribute[0];
|
||||
if (isset($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $k => $tag) {
|
||||
$attribute['Attribute']['Tag'][$k] = $tag['Tag'];
|
||||
}
|
||||
}
|
||||
$this->set('Attribute', $attribute['Attribute']);
|
||||
$this->set('_serialize', array('Attribute'));
|
||||
} else {
|
||||
|
@ -972,7 +992,14 @@ class AttributesController extends AppController {
|
|||
if ($hard) {
|
||||
$save = $this->Attribute->delete($id);
|
||||
} else {
|
||||
$result['Attribute']['deleted'] = true;
|
||||
if (Configure::read('Security.sanitise_attribute_on_delete')) {
|
||||
$result['Attribute']['category'] = 'Other';
|
||||
$result['Attribute']['type'] = 'comment';
|
||||
$result['Attribute']['value'] = 'deleted';
|
||||
$result['Attribute']['comment'] = '';
|
||||
$result['Attribute']['to_ids'] = 0;
|
||||
}
|
||||
$result['Attribute']['deleted'] = 1;
|
||||
$result['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$save = $this->Attribute->save($result);
|
||||
}
|
||||
|
@ -1130,214 +1157,362 @@ class AttributesController extends AppController {
|
|||
}
|
||||
|
||||
public function search() {
|
||||
$fullAddress = '/attributes/search';
|
||||
if ($this->request->here == $fullAddress) {
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
// reset the paginate_conditions
|
||||
$this->Session->write('paginate_conditions',array());
|
||||
if ($this->request->is('post')) {
|
||||
$keyword = $this->request->data['Attribute']['keyword'];
|
||||
$keyword2 = $this->request->data['Attribute']['keyword2'];
|
||||
$tags = $this->request->data['Attribute']['tags'];
|
||||
$org = $this->request->data['Attribute']['org'];
|
||||
$type = $this->request->data['Attribute']['type'];
|
||||
$ioc = $this->request->data['Attribute']['ioc'];
|
||||
$this->set('ioc', $ioc);
|
||||
$category = $this->request->data['Attribute']['category'];
|
||||
$this->set('keywordSearch', $keyword);
|
||||
$this->set('tags', $tags);
|
||||
$keyWordText = null;
|
||||
$keyWordText2 = null;
|
||||
$keyWordText3 = null;
|
||||
$this->set('typeSearch', $type);
|
||||
$this->set('isSearch', 1);
|
||||
$this->set('categorySearch', $category);
|
||||
// search the db
|
||||
$conditions = array();
|
||||
if ($ioc) {
|
||||
$conditions['AND'][] = array('Attribute.to_ids =' => 1);
|
||||
$conditions['AND'][] = array('Event.published =' => 1);
|
||||
}
|
||||
// search on the value field
|
||||
if (isset($keyword)) {
|
||||
$keywordArray = explode("\n", $keyword);
|
||||
$this->set('keywordArray', $keywordArray);
|
||||
$i = 1;
|
||||
$temp = array();
|
||||
$temp2 = array();
|
||||
foreach ($keywordArray as $keywordArrayElement) {
|
||||
$saveWord = trim(strtolower($keywordArrayElement));
|
||||
if ($saveWord != '') {
|
||||
$toInclude = true;
|
||||
if ($saveWord[0] == '!') {
|
||||
$toInclude = false;
|
||||
$saveWord = substr($saveWord, 1);
|
||||
}
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
|
||||
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
|
||||
if ($this->Cidr->checkCIDR($saveWord, 4)) {
|
||||
$cidrresults = $this->Cidr->CIDR($saveWord);
|
||||
foreach ($cidrresults as $result) {
|
||||
$result = strtolower($result);
|
||||
if (strpos($result, '|')) {
|
||||
$resultParts = explode('|', $result);
|
||||
$fullAddress = '/attributes/search';
|
||||
// if no search is given, show the search form
|
||||
if ($this->request->here == $fullAddress && !$this->request->is('post')) {
|
||||
// adding filtering by category and type
|
||||
// combobox for types
|
||||
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
|
||||
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
|
||||
ksort($types['types']);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
|
||||
$this->set('categories', $categories);
|
||||
} else {
|
||||
$this->set('isSearch', 1);
|
||||
|
||||
$attributeTagQuery = '/attributetag';
|
||||
// check if the request is a GET request for attributes with a specific tag (usually after clicking on an attributetag)
|
||||
if (substr($this->request->here, strlen($fullAddress), strlen($attributeTagQuery)) == $attributeTagQuery) {
|
||||
$attributeTagId = substr($this->request->here, (strlen($fullAddress) + strlen($attributeTagQuery) + 1));
|
||||
if (!is_numeric($attributeTagId)) {
|
||||
// either pagination active or no correct id
|
||||
unset($attributeTagId);
|
||||
}
|
||||
}
|
||||
|
||||
// if this is no new search, get parameters from session
|
||||
if ($this->request->here != $fullAddress && !isset($attributeTagId)) {
|
||||
$keyword = $this->Session->read('paginate_conditions_keyword');
|
||||
$keyword2 = $this->Session->read('paginate_conditions_keyword2');
|
||||
$attributeTags = $this->Session->read('paginate_conditions_attributetags');
|
||||
$org = $this->Session->read('paginate_conditions_org');
|
||||
$type = $this->Session->read('paginate_conditions_type');
|
||||
$category = $this->Session->read('paginate_conditions_category');
|
||||
$tags = $this->Session->read('paginate_conditions_tags');
|
||||
$this->set('keywordSearch', $keyword);
|
||||
$this->set('keywordSearch2', $keyword2);
|
||||
if (isset($attributeTags)) {
|
||||
$this->set('attributeTags', $attributeTags);
|
||||
}
|
||||
$this->set('orgSearch', $org);
|
||||
$this->set('typeSearch', $type);
|
||||
$this->set('tags', $tags);
|
||||
$this->set('categorySearch', $category);
|
||||
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
|
||||
|
||||
// re-get pagination
|
||||
$this->Attribute->recursive = 0;
|
||||
$this->paginate = $this->Session->read('paginate_conditions');
|
||||
$this->set('attributes', $this->paginate());
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
} else {
|
||||
// reset the paginate_conditions
|
||||
$this->Session->write('paginate_conditions', array());
|
||||
$conditions = array();
|
||||
$alternateSearch = false;
|
||||
|
||||
if (isset($attributeTagId)) {
|
||||
$this->loadModel('Tag');
|
||||
$this->Tag->id = $attributeTagId;
|
||||
if (!$this->Tag->exists()) {
|
||||
throw new NotFoundException(__('Invalid tag'));
|
||||
}
|
||||
|
||||
$attributeTags = $this->Tag->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array(
|
||||
'id' => $attributeTagId
|
||||
)
|
||||
));
|
||||
$attributeTags = $attributeTags['Tag']['name'];
|
||||
$conditions['AND'][] = array('OR' => array('Attribute.id' => $this->Tag->findAttributeIdsByAttributeTagNames(array($attributeTags))));
|
||||
|
||||
$keyword = null;
|
||||
$keyword2 = null;
|
||||
$org = null;
|
||||
$type = 'ALL';
|
||||
$tags = null;
|
||||
$category = 'ALL';
|
||||
$ioc = false;
|
||||
|
||||
$this->set('keywordSearch', $keyword);
|
||||
$this->set('keywordSearch2', $keyword2);
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$keyword = $this->request->data['Attribute']['keyword'];
|
||||
$keyword2 = $this->request->data['Attribute']['keyword2'];
|
||||
$attributeTags = $this->request->data['Attribute']['attributetags'];
|
||||
$tags = $this->request->data['Attribute']['tags'];
|
||||
$org = $this->request->data['Attribute']['org'];
|
||||
$type = $this->request->data['Attribute']['type'];
|
||||
$ioc = $this->request->data['Attribute']['ioc'];
|
||||
$this->set('ioc', $ioc);
|
||||
$category = $this->request->data['Attribute']['category'];
|
||||
|
||||
$keyWordText = null;
|
||||
$keyWordText2 = null;
|
||||
$keyWordText3 = null;
|
||||
|
||||
// search the db
|
||||
if ($ioc) {
|
||||
$conditions['AND'][] = array('Attribute.to_ids =' => 1);
|
||||
$conditions['AND'][] = array('Event.published =' => 1);
|
||||
}
|
||||
// search on the value field
|
||||
if (isset($keyword)) {
|
||||
$keywordArray = explode("\n", $keyword);
|
||||
$this->set('keywordArray', $keywordArray);
|
||||
$i = 1;
|
||||
$temp = array();
|
||||
$temp2 = array();
|
||||
foreach ($keywordArray as $keywordArrayElement) {
|
||||
$saveWord = trim(strtolower($keywordArrayElement));
|
||||
if ($saveWord != '') {
|
||||
$toInclude = true;
|
||||
if ($saveWord[0] == '!') {
|
||||
$toInclude = false;
|
||||
$saveWord = substr($saveWord, 1);
|
||||
}
|
||||
|
||||
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
|
||||
if ($this->Cidr->checkCIDR($saveWord, 4)) {
|
||||
$cidrresults = $this->Cidr->CIDR($saveWord);
|
||||
foreach ($cidrresults as $result) {
|
||||
$result = strtolower($result);
|
||||
if (strpos($result, '|')) {
|
||||
$resultParts = explode('|', $result);
|
||||
if (!$toInclude) {
|
||||
$temp2[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1) NOT LIKE' => $resultParts[0],
|
||||
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1],
|
||||
));
|
||||
} else {
|
||||
$temp[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1)' => $resultParts[0],
|
||||
'LOWER(Attribute.value2)' => $resultParts[1],
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (!$toInclude) {
|
||||
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => $result));
|
||||
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => $result));
|
||||
} else {
|
||||
array_push($temp, array('LOWER(Attribute.value1) LIKE' => $result));
|
||||
array_push($temp, array('LOWER(Attribute.value2) LIKE' => $result));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (strpos($saveWord, '|')) {
|
||||
$resultParts = explode('|', $saveWord);
|
||||
if (!$toInclude) {
|
||||
$temp2[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1) NOT LIKE' => $resultParts[0],
|
||||
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1],
|
||||
));
|
||||
'LOWER(Attribute.value1) NOT LIKE' => '%' . $resultParts[0],
|
||||
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1] . '%',
|
||||
));
|
||||
} else {
|
||||
$temp[] = array(
|
||||
$temp2[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1)' => $resultParts[0],
|
||||
'LOWER(Attribute.value2)' => $resultParts[1],
|
||||
));
|
||||
'LOWER(Attribute.value1)' => '%' . $resultParts[0],
|
||||
'LOWER(Attribute.value2)' => $resultParts[1] . '%',
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (!$toInclude) {
|
||||
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => $result));
|
||||
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => $result));
|
||||
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
} else {
|
||||
array_push($temp, array('LOWER(Attribute.value1) LIKE' => $result));
|
||||
array_push($temp, array('LOWER(Attribute.value2) LIKE' => $result));
|
||||
array_push($temp, array('LOWER(Attribute.value1) LIKE' => '%' . $saveWord . '%'));
|
||||
array_push($temp, array('LOWER(Attribute.value2) LIKE' => '%' . $saveWord . '%'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (strpos($saveWord, '|')) {
|
||||
$resultParts = explode('|', $saveWord);
|
||||
if (!$toInclude) {
|
||||
$temp2[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1) NOT LIKE' => '%' . $resultParts[0],
|
||||
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1] . '%',
|
||||
));
|
||||
} else {
|
||||
$temp2[] = array(
|
||||
'AND' => array(
|
||||
'LOWER(Attribute.value1)' => '%' . $resultParts[0],
|
||||
'LOWER(Attribute.value2)' => $resultParts[1] . '%',
|
||||
));
|
||||
}
|
||||
if ($toInclude) {
|
||||
array_push($temp, array('LOWER(Attribute.comment) LIKE' => '%' . $saveWord . '%'));
|
||||
} else {
|
||||
if (!$toInclude) {
|
||||
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
} else {
|
||||
array_push($temp, array('LOWER(Attribute.value1) LIKE' => '%' . $saveWord . '%'));
|
||||
array_push($temp, array('LOWER(Attribute.value2) LIKE' => '%' . $saveWord . '%'));
|
||||
}
|
||||
array_push($temp2, array('LOWER(Attribute.comment) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
}
|
||||
}
|
||||
if ($toInclude) {
|
||||
array_push($temp, array('LOWER(Attribute.comment) LIKE' => '%' . $saveWord . '%'));
|
||||
} else {
|
||||
array_push($temp2, array('LOWER(Attribute.comment) NOT LIKE' => '%' . $saveWord . '%'));
|
||||
if ($i == 1 && $saveWord != '') {
|
||||
$keyWordText = $saveWord;
|
||||
} else if (($i > 1 && $i < 10) && $saveWord != '') {
|
||||
$keyWordText = $keyWordText . ', ' . $saveWord;
|
||||
} else if ($i == 10 && $saveWord != '') {
|
||||
$keyWordText = $keyWordText . ' and several other keywords';
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if ($i == 1 && $saveWord != '') $keyWordText = $saveWord;
|
||||
else if (($i > 1 && $i < 10) && $saveWord != '') $keyWordText = $keyWordText . ', ' . $saveWord;
|
||||
else if ($i == 10 && $saveWord != '') $keyWordText = $keyWordText . ' and several other keywords';
|
||||
$i++;
|
||||
}
|
||||
$this->set('keywordSearch', $keyWordText);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND']['OR'] = $temp;
|
||||
}
|
||||
if (!empty($temp2)) {
|
||||
$conditions['AND'][] = $temp2;
|
||||
$this->set('keywordSearch', $keyWordText);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND']['OR'] = $temp;
|
||||
}
|
||||
if (!empty($temp2)) {
|
||||
$conditions['AND'][] = $temp2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// event IDs to be excluded
|
||||
if (isset($keyword2)) {
|
||||
$keywordArray2 = explode("\n", $keyword2);
|
||||
$i = 1;
|
||||
$temp = array();
|
||||
foreach ($keywordArray2 as $keywordArrayElement) {
|
||||
$saveWord = trim($keywordArrayElement);
|
||||
if (empty($saveWord)) continue;
|
||||
if ($saveWord[0] == '!') {
|
||||
if (strlen(substr($saveWord, 1)) == 36) {
|
||||
$temp[] = array('Event.uuid !=' => substr($saveWord, 1));
|
||||
$temp[] = array('Attribute.uuid !=' => substr($saveWord, 1));
|
||||
} else {
|
||||
$temp[] = array('Attribute.event_id !=' => substr($saveWord, 1));
|
||||
// event IDs to be excluded
|
||||
if (isset($keyword2)) {
|
||||
$keywordArray2 = explode("\n", $keyword2);
|
||||
$i = 1;
|
||||
$temp = array();
|
||||
foreach ($keywordArray2 as $keywordArrayElement) {
|
||||
$saveWord = trim($keywordArrayElement);
|
||||
if (empty($saveWord)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (strlen($saveWord) == 36) {
|
||||
$temp['OR'][] = array('Event.uuid =' => $saveWord);
|
||||
$temp['OR'][] = array('Attribute.uuid' => $saveWord);
|
||||
if ($saveWord[0] == '!') {
|
||||
if (strlen(substr($saveWord, 1)) == 36) {
|
||||
$temp[] = array('Event.uuid !=' => substr($saveWord, 1));
|
||||
$temp[] = array('Attribute.uuid !=' => substr($saveWord, 1));
|
||||
} else {
|
||||
$temp[] = array('Attribute.event_id !=' => substr($saveWord, 1));
|
||||
}
|
||||
} else {
|
||||
$temp['OR'][] = array('Attribute.event_id =' => $saveWord);
|
||||
if (strlen($saveWord) == 36) {
|
||||
$temp['OR'][] = array('Event.uuid =' => $saveWord);
|
||||
$temp['OR'][] = array('Attribute.uuid' => $saveWord);
|
||||
} else {
|
||||
$temp['OR'][] = array('Attribute.event_id =' => $saveWord);
|
||||
}
|
||||
}
|
||||
if ($i == 1 && $saveWord != '') {
|
||||
$keyWordText2 = $saveWord;
|
||||
} else if (($i > 1 && $i < 10) && $saveWord != '') {
|
||||
$keyWordText2 = $keyWordText2 . ', ' . $saveWord;
|
||||
} else if ($i == 10 && $saveWord != '') {
|
||||
$keyWordText2 = $keyWordText2 . ' and several other events';
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
$this->set('keywordSearch2', $keyWordText2);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND'][] = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($attributeTags) || !empty($tags)) {
|
||||
$this->loadModel('Tag');
|
||||
}
|
||||
|
||||
if (!empty($attributeTags)) {
|
||||
$includeAttributeTags = array();
|
||||
$excludeAttributeTags = array();
|
||||
$attributeTagsKeywordArray = explode("\n", $attributeTags);
|
||||
foreach ($attributeTagsKeywordArray as $tagName) {
|
||||
$tagName = trim($tagName);
|
||||
if (empty($tagName)) {
|
||||
continue;
|
||||
}
|
||||
if (substr($tagName, 0, 1) === '!') {
|
||||
$excludeAttributeTags[] = substr($tagName, 1);
|
||||
} else {
|
||||
$includeAttributeTags[] = $tagName;
|
||||
}
|
||||
}
|
||||
if ($i == 1 && $saveWord != '') $keyWordText2 = $saveWord;
|
||||
else if (($i > 1 && $i < 10) && $saveWord != '') $keyWordText2 = $keyWordText2 . ', ' . $saveWord;
|
||||
else if ($i == 10 && $saveWord != '') $keyWordText2 = $keyWordText2 . ' and several other events';
|
||||
$i++;
|
||||
if (!empty($includeAttributeTags)) {
|
||||
$conditions['AND'][] = array('OR' => array('Attribute.id' => $this->Tag->findAttributeIdsByAttributeTagNames($includeAttributeTags)));
|
||||
}
|
||||
if (!empty($excludeAttributeTags)) {
|
||||
$conditions['AND'][] = array('Attribute.id !=' => $this->Tag->findAttributeIdsByAttributeTagNames($excludeAttributeTags));
|
||||
}
|
||||
}
|
||||
$this->set('keywordSearch2', $keyWordText2);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND'][] = $temp;
|
||||
if (!empty($tags)) {
|
||||
$include = array();
|
||||
$exclude = array();
|
||||
$keywordArray = explode("\n", $tags);
|
||||
foreach ($keywordArray as $tagname) {
|
||||
$tagname = trim($tagname);
|
||||
if (empty($tagname)) {
|
||||
continue;
|
||||
}
|
||||
if (substr($tagname, 0, 1) === '!') {
|
||||
$exclude[] = substr($tagname, 1);
|
||||
} else {
|
||||
$include[] = $tagname;
|
||||
}
|
||||
}
|
||||
if (!empty($include)) {
|
||||
$conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findEventIdsByTagNames($include)));
|
||||
}
|
||||
if (!empty($exclude)) {
|
||||
$conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findEventIdsByTagNames($exclude));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($tags)) {
|
||||
$include = array();
|
||||
$exclude = array();
|
||||
$keywordArray = explode("\n", $tags);
|
||||
foreach ($keywordArray as $tagname) {
|
||||
$tagname = trim($tagname);
|
||||
if (empty($tagname)) continue;
|
||||
if (substr($tagname, 0, 1) === '!') $exclude[] = substr($tagname, 1);
|
||||
else $include[] = $tagname;
|
||||
if ($type != 'ALL') {
|
||||
$conditions['Attribute.type ='] = $type;
|
||||
}
|
||||
$this->loadModel('Tag');
|
||||
if (!empty($include)) $conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findEventIdsByTagNames($include)));
|
||||
if (!empty($exclude)) $conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findEventIdsByTagNames($exclude));
|
||||
}
|
||||
if ($type != 'ALL') {
|
||||
$conditions['Attribute.type ='] = $type;
|
||||
}
|
||||
if ($category != 'ALL') {
|
||||
$conditions['Attribute.category ='] = $category;
|
||||
}
|
||||
// organisation search field
|
||||
$temp = array();
|
||||
if (isset($org)) {
|
||||
$this->loadModel('Organisation');
|
||||
$orgArray = explode("\n", $org);
|
||||
foreach ($orgArray as $i => $orgArrayElement) {
|
||||
$saveWord = trim($orgArrayElement);
|
||||
if (empty($saveWord)) continue;
|
||||
if ($saveWord[0] == '!') {
|
||||
$org_names = $this->Organisation->find('all', array(
|
||||
'fields' => array('id', 'name'),
|
||||
if ($category != 'ALL') {
|
||||
$conditions['Attribute.category ='] = $category;
|
||||
}
|
||||
// organisation search field
|
||||
if (isset($org)) {
|
||||
$temp = array();
|
||||
$this->loadModel('Organisation');
|
||||
$orgArray = explode("\n", $org);
|
||||
foreach ($orgArray as $i => $orgArrayElement) {
|
||||
$saveWord = trim($orgArrayElement);
|
||||
if (empty($saveWord)) {
|
||||
continue;
|
||||
}
|
||||
if ($saveWord[0] == '!') {
|
||||
$org_names = $this->Organisation->find('all', array(
|
||||
'fields' => array('id', 'name'),
|
||||
'conditions' => array('lower(name) LIKE' => '%' . strtolower(substr($saveWord, 1)) . '%'),
|
||||
));
|
||||
foreach ($org_names as $org_name) $temp['AND'][] = array('Event.orgc_id !=' => $org_name['Organisation']['id']);
|
||||
} else {
|
||||
$org_names = $this->Organisation->find('all', array(
|
||||
'fields' => array('id', 'name'),
|
||||
));
|
||||
foreach ($org_names as $org_name) {
|
||||
$temp['AND'][] = array('Event.orgc_id !=' => $org_name['Organisation']['id']);
|
||||
}
|
||||
} else {
|
||||
$org_names = $this->Organisation->find('all', array(
|
||||
'fields' => array('id', 'name'),
|
||||
'conditions' => array('lower(name) LIKE' => '%' . strtolower($saveWord) . '%'),
|
||||
));
|
||||
foreach ($org_names as $org_name) $temp['OR'][] = array('Event.orgc_id' => $org_name['Organisation']['id']);
|
||||
));
|
||||
foreach ($org_names as $org_name) {
|
||||
$temp['OR'][] = array('Event.orgc_id' => $org_name['Organisation']['id']);
|
||||
}
|
||||
}
|
||||
if ($i == 0 && $saveWord != '') {
|
||||
$keyWordText3 = $saveWord;
|
||||
} else if (($i > 0 && $i < 9) && $saveWord != '') {
|
||||
$keyWordText3 = $keyWordText3 . ', ' . $saveWord;
|
||||
} else if ($i == 9 && $saveWord != '') {
|
||||
$keyWordText3 = $keyWordText3 . ' and several other organisations';
|
||||
}
|
||||
}
|
||||
$this->set('orgSearch', $keyWordText3);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND'][] = $temp;
|
||||
}
|
||||
if ($i == 0 && $saveWord != '') $keyWordText3 = $saveWord;
|
||||
else if (($i > 0 && $i < 9) && $saveWord != '') $keyWordText3 = $keyWordText3 . ', ' . $saveWord;
|
||||
else if ($i == 9 && $saveWord != '') $keyWordText3 = $keyWordText3 . ' and several other organisations';
|
||||
}
|
||||
$this->set('orgSearch', $keyWordText3);
|
||||
if (!empty($temp)) {
|
||||
$conditions['AND'][] = $temp;
|
||||
|
||||
if ($this->request->data['Attribute']['alternate']) {
|
||||
$alternateSearch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($attributeTags)) {
|
||||
$this->set('attributeTags', $attributeTags);
|
||||
}
|
||||
$this->set('tags', $tags);
|
||||
$this->set('typeSearch', $type);
|
||||
$this->set('categorySearch', $category);
|
||||
|
||||
$conditions['AND'][] = array('Attribute.deleted' => 0);
|
||||
if ($this->request->data['Attribute']['alternate']) {
|
||||
if ($alternateSearch) {
|
||||
$events = $this->searchAlternate($conditions);
|
||||
$this->set('events', $events);
|
||||
$this->render('alternate_search_result');
|
||||
|
@ -1361,6 +1536,7 @@ class AttributesController extends AppController {
|
|||
),
|
||||
)
|
||||
);
|
||||
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
// merge in private conditions
|
||||
$this->paginate = Set::merge($this->paginate, array(
|
||||
|
@ -1396,10 +1572,13 @@ class AttributesController extends AppController {
|
|||
}
|
||||
}
|
||||
$this->set('attributes', $attributes);
|
||||
|
||||
// and store into session
|
||||
$this->Session->write('paginate_conditions', $this->paginate);
|
||||
$this->Session->write('paginate_conditions_keyword', $keyword);
|
||||
$this->Session->write('paginate_conditions_keyword2', $keyword2);
|
||||
if (isset($attributeTags))
|
||||
$this->Session->write('paginate_conditions_attributetags', $attributeTags);
|
||||
$this->Session->write('paginate_conditions_org', $org);
|
||||
$this->Session->write('paginate_conditions_type', $type);
|
||||
$this->Session->write('paginate_conditions_ioc', $ioc);
|
||||
|
@ -1411,46 +1590,7 @@ class AttributesController extends AppController {
|
|||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
}
|
||||
} else {
|
||||
// no search keyword is given, show the search form
|
||||
|
||||
// adding filtering by category and type
|
||||
// combobox for types
|
||||
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
|
||||
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
|
||||
ksort($types['types']);
|
||||
$this->set('types', $types);
|
||||
|
||||
// combobox for categories
|
||||
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
|
||||
$this->set('categories', $categories);
|
||||
}
|
||||
} else {
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
// get from Session
|
||||
$keyword = $this->Session->read('paginate_conditions_keyword');
|
||||
$keyword2 = $this->Session->read('paginate_conditions_keyword2');
|
||||
$org = $this->Session->read('paginate_conditions_org');
|
||||
$type = $this->Session->read('paginate_conditions_type');
|
||||
$category = $this->Session->read('paginate_conditions_category');
|
||||
$tags = $this->Session->read('paginate_conditions_tags');
|
||||
$this->set('keywordSearch', $keyword);
|
||||
$this->set('keywordSearch2', $keyword2);
|
||||
$this->set('orgSearch', $org);
|
||||
$this->set('typeSearch', $type);
|
||||
$this->set('tags', $tags);
|
||||
$this->set('isSearch', 1);
|
||||
$this->set('categorySearch', $category);
|
||||
|
||||
// re-get pagination
|
||||
$this->Attribute->recursive = 0;
|
||||
$this->paginate = $this->Session->read('paginate_conditions');
|
||||
$this->set('attributes', $this->paginate());
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1520,9 +1660,9 @@ class AttributesController extends AppController {
|
|||
// the last 4 fields accept the following operators:
|
||||
// && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two.
|
||||
// ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't.
|
||||
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false) {
|
||||
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false) {
|
||||
if ($tags) $tags = str_replace(';', ':', $tags);
|
||||
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
|
||||
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
|
||||
foreach ($simpleFalse as $sF) {
|
||||
if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false;
|
||||
}
|
||||
|
@ -1551,13 +1691,13 @@ class AttributesController extends AppController {
|
|||
if (!isset($data['request'])) {
|
||||
$data['request'] = $data;
|
||||
}
|
||||
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
|
||||
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
|
||||
foreach ($paramArray as $p) {
|
||||
if (isset($data['request'][$p])) ${$p} = $data['request'][$p];
|
||||
else ${$p} = null;
|
||||
}
|
||||
}
|
||||
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
|
||||
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
|
||||
foreach ($simpleFalse as $sF) {
|
||||
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) ${$sF} = false;
|
||||
}
|
||||
|
@ -1668,7 +1808,13 @@ class AttributesController extends AppController {
|
|||
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
|
||||
if ($published) $conditions['AND'][] = array('Event.published' => $published);
|
||||
if ($timestamp) $conditions['AND'][] = array('Attribute.timestamp >=' => $timestamp);
|
||||
|
||||
if ($to_ids) {
|
||||
if ($to_ids === 'exclude') {
|
||||
$conditions['AND'][] = array('Attribute.to_ids' => 0);
|
||||
} else {
|
||||
$conditions['AND'][] = array('Attribute.to_ids' => 1);
|
||||
}
|
||||
}
|
||||
// change the fields here for the attribute export!!!! Don't forget to check for the permissions, since you are not going through fetchevent. Maybe create fetchattribute?
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
|
@ -1676,6 +1822,12 @@ class AttributesController extends AppController {
|
|||
'withAttachments' => $withAttachments,
|
||||
'enforceWarninglist' => $enforceWarninglist
|
||||
);
|
||||
if ($deleted) {
|
||||
$params['deleted'] = 1;
|
||||
if ($deleted === 'only') {
|
||||
$params['conditions']['AND'][] = array('Attribute.deleted' => 1);
|
||||
}
|
||||
}
|
||||
$results = $this->Attribute->fetchAttributes($this->Auth->user(), $params);
|
||||
$this->loadModel('Whitelist');
|
||||
$results = $this->Whitelist->removeWhitelistedFromArray($results, true);
|
||||
|
@ -1814,8 +1966,8 @@ class AttributesController extends AppController {
|
|||
$this->__downloadAttachment($this->Attribute->data['Attribute']);
|
||||
}
|
||||
|
||||
public function text($key='download', $type = 'all', $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false) {
|
||||
$simpleFalse = array('eventId', 'allowNonIDS', 'tags', 'from', 'to', 'last', 'enforceWarninglist');
|
||||
public function text($key='download', $type = 'all', $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false, $allowNotPublished = false) {
|
||||
$simpleFalse = array('eventId', 'allowNonIDS', 'tags', 'from', 'to', 'last', 'enforceWarninglist', 'allowNotPublished');
|
||||
foreach ($simpleFalse as $sF) {
|
||||
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) ${$sF} = false;
|
||||
}
|
||||
|
@ -1837,7 +1989,7 @@ class AttributesController extends AppController {
|
|||
$this->response->type('txt'); // set the content type
|
||||
$this->header('Content-Disposition: download; filename="misp.' . $type . '.txt"');
|
||||
$this->layout = 'text/default';
|
||||
$attributes = $this->Attribute->text($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last, $enforceWarninglist);
|
||||
$attributes = $this->Attribute->text($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last, $enforceWarninglist, $allowNotPublished);
|
||||
$this->loadModel('Whitelist');
|
||||
$attributes = $this->Whitelist->removeWhitelistedFromArray($attributes, true);
|
||||
$this->set('attributes', $attributes);
|
||||
|
@ -2487,6 +2639,178 @@ class AttributesController extends AppController {
|
|||
$this->render('/Servers/json/simple');
|
||||
}
|
||||
|
||||
public function addTag($id = false, $tag_id = false) {
|
||||
if (!$this->request->is('post')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that. Only POST requests are accepted.')), 'status' => 200));
|
||||
}
|
||||
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'Attribute' => false,
|
||||
'tag_id' => 'tag',
|
||||
'attribute_id' => 'attribute',
|
||||
'id' => 'attribute'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) {
|
||||
$id = $this->request->data['attribute'];
|
||||
}
|
||||
if ($id === 'selected') {
|
||||
$idList = json_decode($this->request->data['attribute_ids'], true);
|
||||
}
|
||||
if ($tag_id === false) $tag_id = $this->request->data['tag'];
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
|
||||
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
if (!isset($idList)) {
|
||||
$idList = array($id);
|
||||
}
|
||||
$success = 0;
|
||||
$fails = 0;
|
||||
foreach ($idList as $id) {
|
||||
$this->Attribute->id = $id;
|
||||
if (!$this->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
|
||||
$this->Attribute->read();
|
||||
if ($this->Attribute->data['Attribute']['deleted']) throw new NotFoundException(__('Invalid attribute'));
|
||||
$eventId = $this->Attribute->data['Attribute']['event_id'];
|
||||
|
||||
$this->Attribute->Event->recursive = -1;
|
||||
$event = $this->Attribute->Event->read(array(), $eventId);
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
|
||||
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status' => 200));
|
||||
}
|
||||
}
|
||||
|
||||
$this->Attribute->recursive = -1;
|
||||
$this->Attribute->AttributeTag->Tag->id = $tag_id;
|
||||
if (!$this->Attribute->AttributeTag->Tag->exists()) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
|
||||
}
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
$found = $this->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'attribute_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (!empty($found)) {
|
||||
$fails++;
|
||||
continue;
|
||||
}
|
||||
$this->Attribute->AttributeTag->create();
|
||||
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->Event->save($event);
|
||||
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->save($this->Attribute->data);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
|
||||
$success++;
|
||||
} else {
|
||||
$fails++;
|
||||
}
|
||||
}
|
||||
if ($fails == 0) {
|
||||
if ($success == 1) {
|
||||
$message = 'Tag added.';
|
||||
} else {
|
||||
$message = $success . ' tags added.';
|
||||
}
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $message, 'check_publish' => true)), 'status' => 200));
|
||||
} else {
|
||||
if ($fails == 1) {
|
||||
$message = 'Tag could not be added.';
|
||||
} else {
|
||||
$message = $fails . ' tags could not be added.';
|
||||
}
|
||||
if ($success > 0) {
|
||||
$message .= ' However, ' . $success . ' tag(s) were added.';
|
||||
}
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $message)), 'status' => 200));
|
||||
}
|
||||
}
|
||||
|
||||
public function removeTag($id = false, $tag_id = false) {
|
||||
if (!$this->request->is('post')) {
|
||||
$this->set('id', $id);
|
||||
$this->set('tag_id', $tag_id);
|
||||
$this->set('model', 'Attribute');
|
||||
$this->render('ajax/tagRemoveConfirmation');
|
||||
} else {
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'Attribute' => false,
|
||||
'tag_id' => 'tag',
|
||||
'attribute_id' => 'attribute',
|
||||
'id' => 'attribute'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) $id = $this->request->data['attribute'];
|
||||
if ($tag_id === false) $tag_id = $this->request->data['tag'];
|
||||
$this->Attribute->id = $id;
|
||||
if (!$this->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
|
||||
$this->Attribute->read();
|
||||
if ($this->Attribute->data['Attribute']['deleted']) throw new NotFoundException(__('Invalid attribute'));
|
||||
$eventId = $this->Attribute->data['Attribute']['event_id'];
|
||||
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
|
||||
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
if (!is_numeric($id)) $id = $this->request->data['Attribute']['id'];
|
||||
|
||||
$this->Attribute->Event->recursive = -1;
|
||||
$event = $this->Attribute->Event->read(array(), $eventId);
|
||||
// org should allow to (un)tag too, so that an event that gets pushed can be (un)tagged locally by the owning org
|
||||
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'] && $event['Event']['distribution'] == 0) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status' => 200));
|
||||
}
|
||||
|
||||
$this->Attribute->recursive = -1;
|
||||
$attributeTag = $this->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'attribute_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (empty($attributeTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid attribute - tag combination.')), 'status' => 200));
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
if ($this->Attribute->AttributeTag->delete($attributeTag['AttributeTag']['id'])) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->Event->save($event);
|
||||
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->save($this->Attribute->data);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from attribute (' . $id . ')', 'Attribute (' . $id . ') untagged of Tag (' . $tag_id . ')');
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.', 'check_publish' => true)), 'status' => 200));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be removed.')), 'status' => 200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleCorrelation($id) {
|
||||
if (!$this->_isSiteAdmin() && Configure.read('MISP.allow_disabling_correlation')) {
|
||||
throw new MethodNotAllowedException('Disabling the correlation is not permitted on this instance.');
|
||||
|
|
|
@ -31,6 +31,7 @@ class ACLComponent extends Component {
|
|||
'add' => array('perm_add'),
|
||||
'add_attachment' => array('perm_add'),
|
||||
'add_threatconnect' => array('perm_add'),
|
||||
'addTag' => array('perm_tagger'),
|
||||
'attributeReplace' => array('perm_add'),
|
||||
'attributeStatistics' => array('*'),
|
||||
'bro' => array('*'),
|
||||
|
@ -51,6 +52,7 @@ class ACLComponent extends Component {
|
|||
'hoverEnrichment' => array('perm_add'),
|
||||
'index' => array('*'),
|
||||
'pruneOrphanedAttributes' => array(),
|
||||
'removeTag' => array('perm_tagger'),
|
||||
'reportValidationIssuesAttributes' => array(),
|
||||
'restore' => array('perm_add'),
|
||||
'restSearch' => array('*'),
|
||||
|
@ -165,10 +167,10 @@ class ACLComponent extends Component {
|
|||
),
|
||||
'jobs' => array(
|
||||
'cache' => array('*'),
|
||||
'getError' => array(),
|
||||
'getGenerateCorrelationProgress' => array('*'),
|
||||
'getProgress' => array('*'),
|
||||
'index' => array(),
|
||||
'getError' => array()
|
||||
'index' => array()
|
||||
),
|
||||
'logs' => array(
|
||||
'admin_index' => array('perm_audit'),
|
||||
|
@ -176,6 +178,7 @@ class ACLComponent extends Component {
|
|||
'event_index' => array('*'),
|
||||
'maxDateActivity' => array('*'),
|
||||
'returnDates' => array('*'),
|
||||
'pruneUpdateLogs' => array()
|
||||
),
|
||||
'news' => array(
|
||||
'add' => array(),
|
||||
|
@ -235,6 +238,7 @@ class ACLComponent extends Component {
|
|||
'edit' => array(),
|
||||
'fetchServersForSG' => array('*'),
|
||||
'filterEventIndex' => array(),
|
||||
'getPyMISPVersion' => array('*'),
|
||||
'getVersion' => array('*'),
|
||||
'index' => array('OR' => array('perm_sync', 'perm_admin')),
|
||||
'previewEvent' => array(),
|
||||
|
@ -283,16 +287,20 @@ class ACLComponent extends Component {
|
|||
'sightings' => array(
|
||||
'add' => array('perm_add'),
|
||||
'delete' => array('perm_add'),
|
||||
'index' => array('*')
|
||||
),
|
||||
'tags' => array(
|
||||
'add' => array('perm_tag_editor'),
|
||||
'attachTagToObject' => array('perm_tagger'),
|
||||
'delete' => array('perm_tag_editor'),
|
||||
'edit' => array('perm_tag_editor'),
|
||||
'index' => array('*'),
|
||||
'quickAdd' => array('perm_tag_editor'),
|
||||
'removeTagFromObject' => array('perm_tagger'),
|
||||
'selectTag' => array('perm_tagger'),
|
||||
'selectTaxonomy' => array('perm_tagger'),
|
||||
'showEventTag' => array('*'),
|
||||
'showAttributeTag' => array('*'),
|
||||
'tagStatistics' => array('*'),
|
||||
'view' => array('*'),
|
||||
'viewTag' => array('*'),
|
||||
|
|
|
@ -13,6 +13,18 @@ class RestResponseComponent extends Component {
|
|||
'description' => "POST a User object in JSON format to this API to edit a user.",
|
||||
'optional' => array('email', 'org_id', 'role_id', 'password', 'external_auth_required', 'external_auth_key', 'enable_password', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'change_pw', 'termsaccepted', 'newsread')
|
||||
)
|
||||
),
|
||||
'Organisation' => array(
|
||||
'admin_add' => array(
|
||||
'description' => "POST an Organisation object in JSON format to this API to create a new organsiation.",
|
||||
'mandatory' => array('name'),
|
||||
'optional' => array('anonymise', 'description', 'type', 'nationality', 'sector', 'uuid', 'contacts', 'local')
|
||||
),
|
||||
'admin_edit' => array(
|
||||
'description' => "POST an Organisation object in JSON format to this API to create a new organsiation.",
|
||||
'mandatory' => array('name'),
|
||||
'optional' => array('anonymise', 'description', 'type', 'nationality', 'sector', 'uuid', 'contacts', 'local')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -30,7 +42,7 @@ class RestResponseComponent extends Component {
|
|||
public function saveSuccessResponse($controller, $action, $id = false, $format = false, $message = false) {
|
||||
$action = $this->__dissectAdminRouting($action);
|
||||
if (!$message) {
|
||||
$message = Inflector::singularize($controller) . ' ' . $action['action'] . 'ed';
|
||||
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) == 'e') ? 'd' : 'ed');
|
||||
}
|
||||
$response['name'] = $message;
|
||||
$response['message'] = $response['name'];
|
||||
|
|
|
@ -571,6 +571,7 @@ class EventsController extends AppController {
|
|||
if (Configure::read('MISP.showCorrelationsOnIndex')) $events = $this->Event->attachCorrelationCountToEvents($this->Auth->user(), $events);
|
||||
if (Configure::read('MISP.showSightingsCountOnIndex') && Configure::read('MISP.Plugin.Sightings_enable') !== false) $events = $this->Event->attachSightingsCountToEvents($this->Auth->user(), $events);
|
||||
if (Configure::read('MISP.showProposalsCountOnIndex')) $events = $this->Event->attachProposalsCountToEvents($this->Auth->user(), $events);
|
||||
if (Configure::read('MISP.showDiscussionsCountOnIndex')) $events = $this->Event->attachDiscussionsCountToEvents($this->Auth->user(), $events);
|
||||
$events = $this->GalaxyCluster->attachClustersToEventIndex($events, true);
|
||||
$this->set('events', $events);
|
||||
}
|
||||
|
@ -792,11 +793,11 @@ class EventsController extends AppController {
|
|||
|
||||
// workaround to get the event dates in to the attribute relations
|
||||
$relatedDates = array();
|
||||
if (isset($event['RelatedEvent'])) {
|
||||
if (!empty($event['RelatedEvent'])) {
|
||||
foreach ($event['RelatedEvent'] as $relation) {
|
||||
$relatedDates[$relation['Event']['id']] = $relation['Event']['date'];
|
||||
}
|
||||
if (isset($event['RelatedAttribute'])) {
|
||||
if (!empty($event['RelatedAttribute'])) {
|
||||
foreach ($event['RelatedAttribute'] as $key => $relatedAttribute) {
|
||||
foreach ($relatedAttribute as $key2 => $relation) {
|
||||
$event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
|
||||
|
@ -1008,7 +1009,9 @@ class EventsController extends AppController {
|
|||
$sgs = $this->Event->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->_isRest()) {
|
||||
|
||||
if (empty($this->data)) {
|
||||
throw new MethodNotAllowedException('No valid event data received.');
|
||||
}
|
||||
// rearrange the response if the event came from an export
|
||||
if (isset($this->request->data['response'])) $this->request->data = $this->request->data['response'];
|
||||
|
||||
|
@ -1194,9 +1197,9 @@ class EventsController extends AppController {
|
|||
if (isset($this->data['Event']['submittedfile'])) {
|
||||
if (Configure::read('MISP.take_ownership_xml_import')
|
||||
&& (isset($this->data['Event']['takeownership']) && $this->data['Event']['takeownership'] == 1)) {
|
||||
$results = $this->_addMISPExportFile($ext, true);
|
||||
$results = $this->_addMISPExportFile($ext, true, $this->data['Event']['publish']);
|
||||
} else {
|
||||
$results = $this->_addMISPExportFile($ext);
|
||||
$results = $this->_addMISPExportFile($ext, false, $this->data['Event']['publish']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1278,6 +1281,13 @@ class EventsController extends AppController {
|
|||
}
|
||||
|
||||
public function edit($id = null) {
|
||||
if (Validation::uuid($id)) {
|
||||
$temp = $this->Event->find('first', array('recursive' => -1, 'fields' => array('Event.id'), 'conditions' => array('Event.uuid' => $id)));
|
||||
if (empty($temp)) throw new NotFoundException('Invalid event');
|
||||
$id = $temp['Event']['id'];
|
||||
} else if (!is_numeric($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->Event->id = $id;
|
||||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
|
@ -2172,7 +2182,7 @@ class EventsController extends AppController {
|
|||
}
|
||||
}
|
||||
|
||||
public function _addMISPExportFile($ext, $take_ownership = false) {
|
||||
public function _addMISPExportFile($ext, $take_ownership = false, $publish = false) {
|
||||
App::uses('FileAccessTool', 'Tools');
|
||||
$data = (new FileAccessTool())->readFromFile($this->data['Event']['submittedfile']['tmp_name'], $this->data['Event']['submittedfile']['size']);
|
||||
|
||||
|
@ -2210,6 +2220,7 @@ class EventsController extends AppController {
|
|||
$event = array('Event' => $event);
|
||||
$created_id = 0;
|
||||
$event['Event']['locked'] = 1;
|
||||
$event['Event']['published'] = $publish;
|
||||
$result['result'] = $this->Event->_add($event, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues);
|
||||
$result['id'] = $created_id;
|
||||
$result['validationIssues'] = $validationIssues;
|
||||
|
@ -2223,6 +2234,7 @@ class EventsController extends AppController {
|
|||
}
|
||||
$created_id = 0;
|
||||
$temp['Event']['locked'] = 1;
|
||||
$temp['Event']['published'] = $publish;
|
||||
$result = $this->Event->_add($temp, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues);
|
||||
$results = array(0 => array('info' => $temp['Event']['info'], 'result' => $result, 'id' => $created_id, 'validationIssues' => $validationIssues));
|
||||
}
|
||||
|
@ -2941,56 +2953,60 @@ class EventsController extends AppController {
|
|||
|
||||
public function removeTag($id = false, $tag_id = false, $galaxy = false) {
|
||||
if (!$this->request->is('post')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that. Only POST requests are accepted.')), 'status'=>200));
|
||||
}
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'Event' => false,
|
||||
'tag_id' => 'tag',
|
||||
'event_id' => 'event',
|
||||
'id' => 'event'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) $id = $this->request->data['event'];
|
||||
if ($tag_id === false) $tag_id = $this->request->data['tag'];
|
||||
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')),'status'=>200));
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
|
||||
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')), 'status'=>200));
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
|
||||
$this->Event->recursive = -1;
|
||||
$event = $this->Event->read(array(), $id);
|
||||
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
|
||||
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id']) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')),'status'=>200));
|
||||
}
|
||||
$eventTag = $this->Event->EventTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'event_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - ' . ($galaxy ? 'galaxy' : 'tag') . ' combination.')),'status'=>200));
|
||||
$tag = $this->Event->EventTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Event->save($event);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.', 'check_publish' => true)), 'status'=>200));
|
||||
$this->set('id', $id);
|
||||
$this->set('tag_id', $tag_id);
|
||||
$this->set('model', 'Event');
|
||||
$this->render('/Attributes/ajax/tagRemoveConfirmation');
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'Event' => false,
|
||||
'tag_id' => 'tag',
|
||||
'event_id' => 'event',
|
||||
'id' => 'event'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) $id = $this->request->data['event'];
|
||||
if ($tag_id === false) $tag_id = $this->request->data['tag'];
|
||||
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')),'status'=>200));
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
|
||||
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')), 'status'=>200));
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
|
||||
$this->Event->recursive = -1;
|
||||
$event = $this->Event->read(array(), $id);
|
||||
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
|
||||
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id']) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')),'status'=>200));
|
||||
}
|
||||
$eventTag = $this->Event->EventTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'event_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - ' . ($galaxy ? 'galaxy' : 'tag') . ' combination.')),'status'=>200));
|
||||
$tag = $this->Event->EventTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Event->save($event);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.', 'check_publish' => true)), 'status'=>200));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3077,6 +3093,8 @@ class EventsController extends AppController {
|
|||
foreach (${$source} as $k => $attribute) {
|
||||
if ($attribute['type'] == 'ip-src/ip-dst') {
|
||||
$types = array('ip-src', 'ip-dst');
|
||||
} else if ($attribute['type'] == 'ip-src|port/ip-dst|port') {
|
||||
$types = array('ip-src|port', 'ip-dst|port');
|
||||
} else if ($attribute['type'] == 'malware-sample') {
|
||||
if (!isset($attribute['data_is_handled']) || !$attribute['data_is_handled']) {
|
||||
App::uses('FileAccessTool', 'Tools');
|
||||
|
@ -3480,10 +3498,10 @@ class EventsController extends AppController {
|
|||
$this->loadModel('Log');
|
||||
$hashes = array('md5' => 'malware-sample', 'sha1' => 'filename|sha1', 'sha256' => 'filename|sha256');
|
||||
$categoryDefinitions = $this->Event->Attribute->categoryDefinitions;
|
||||
$types = array();
|
||||
$categories = array();
|
||||
foreach ($categoryDefinitions as $k => $v) {
|
||||
if (in_array('malware-sample', $v['types']) && !in_array($k, $types)) {
|
||||
$types[] = $k;
|
||||
if (in_array('malware-sample', $v['types']) && !in_array($k, $categories)) {
|
||||
$categories[] = $k;
|
||||
}
|
||||
}
|
||||
$parameter_options = array(
|
||||
|
@ -3492,7 +3510,7 @@ class EventsController extends AppController {
|
|||
'analysis' => array('valid_options' => array(0, 1, 2), 'default' => 0),
|
||||
'info' => array('default' => 'Malware samples uploaded on ' . date('Y-m-d')),
|
||||
'to_ids' => array('valid_options' => array(0, 1), 'default' => 1),
|
||||
'category' => array('valid_options' => $types, 'default' => 'Payload installation'),
|
||||
'category' => array('valid_options' => $categories, 'default' => 'Payload installation'),
|
||||
'comment' => array('default' => '')
|
||||
);
|
||||
|
||||
|
@ -3554,6 +3572,8 @@ class EventsController extends AppController {
|
|||
));
|
||||
if (empty($event)) throw new NotFoundException('Event not found.');
|
||||
$this->Event->id = $data['event_id'];
|
||||
$date = new DateTime();
|
||||
$this->Event->saveField('timestamp', $date->getTimestamp());
|
||||
$this->Event->saveField('published', 0);
|
||||
} else {
|
||||
$this->Event->create();
|
||||
|
@ -3590,69 +3610,44 @@ class EventsController extends AppController {
|
|||
$successCount = 0;
|
||||
$errors = array();
|
||||
foreach ($data['files'] as $file) {
|
||||
if ($data['to_ids']) {
|
||||
$temp = $this->Event->Attribute->handleMaliciousBase64($data['event_id'], $file['filename'], $file['data'], array_keys($hashes));
|
||||
if ($temp['success']) {
|
||||
foreach ($hashes as $hash => $typeName) {
|
||||
if ($temp[$hash] == false) continue;
|
||||
$file[$hash] = $temp[$hash];
|
||||
$file['data'] = $temp['data'];
|
||||
$this->Event->Attribute->create();
|
||||
$attribute = array(
|
||||
'value' => $file['filename'] . '|' . $file[$hash],
|
||||
'distribution' => $data['distribution'],
|
||||
'category' => $data['category'],
|
||||
'type' => $typeName,
|
||||
'event_id' => $data['event_id'],
|
||||
'to_ids' => $data['to_ids'],
|
||||
'comment' => $data['comment']
|
||||
);
|
||||
if ($hash == 'md5') $attribute['data'] = $file['data'];
|
||||
$result = $this->Event->Attribute->save($attribute);
|
||||
if (!$result) {
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Event',
|
||||
'model_id' => $data['event_id'],
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'upload_sample',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Error: Failed to create attribute using the upload sample functionality',
|
||||
'change' => 'There was an issue creating an attribute (' . $typeName . ': ' . $file['filename'] . '|' . $file[$hash] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
|
||||
));
|
||||
if ($typeName == 'malware-sample') {
|
||||
$errors[] = array('filename' => $file['filename'], 'hash' => $file[$hash], 'error' => $this->Event->Attribute->validationErrors);
|
||||
}
|
||||
} else if ($typeName == 'malware-sample') {
|
||||
$successCount++;
|
||||
$temp = $this->Event->Attribute->handleMaliciousBase64($data['event_id'], $file['filename'], $file['data'], array_keys($hashes));
|
||||
if ($temp['success']) {
|
||||
foreach ($hashes as $hash => $typeName) {
|
||||
if ($temp[$hash] == false) continue;
|
||||
$file[$hash] = $temp[$hash];
|
||||
$file['data'] = $temp['data'];
|
||||
$this->Event->Attribute->create();
|
||||
$attribute = array(
|
||||
'value' => $file['filename'] . '|' . $file[$hash],
|
||||
'distribution' => $data['distribution'],
|
||||
'category' => $data['category'],
|
||||
'type' => $typeName,
|
||||
'event_id' => $data['event_id'],
|
||||
'to_ids' => $data['to_ids'],
|
||||
'comment' => $data['comment']
|
||||
);
|
||||
if ($hash == 'md5') $attribute['data'] = $file['data'];
|
||||
$result = $this->Event->Attribute->save($attribute);
|
||||
if (!$result) {
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Event',
|
||||
'model_id' => $data['event_id'],
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'upload_sample',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Error: Failed to create attribute using the upload sample functionality',
|
||||
'change' => 'There was an issue creating an attribute (' . $typeName . ': ' . $file['filename'] . '|' . $file[$hash] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
|
||||
));
|
||||
if ($typeName == 'malware-sample') {
|
||||
$errors[] = array('filename' => $file['filename'], 'hash' => $file[$hash], 'error' => $this->Event->Attribute->validationErrors);
|
||||
}
|
||||
} else if ($typeName == 'malware-sample') {
|
||||
$successCount++;
|
||||
}
|
||||
} else {
|
||||
$errors[] = array('filename' => $file['filename'], 'hash' => $file['hash'], 'error' => 'Failed to encrypt and compress the file.');
|
||||
}
|
||||
} else {
|
||||
$this->Event->Attribute->create();
|
||||
$attribute = array(
|
||||
'value' => $file['filename'],
|
||||
'distribution' => $data['distribution'],
|
||||
'category' => $data['category'],
|
||||
'type' => 'attachment',
|
||||
'event_id' => $data['event_id'],
|
||||
'to_ids' => $data['to_ids'],
|
||||
'data' => $file['data'],
|
||||
'comment' => $data['comment']
|
||||
);
|
||||
$result = $this->Event->Attribute->save($attribute);
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Event',
|
||||
'model_id' => $data['event_id'],
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'upload_sample',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Error: Failed to create attribute using the upload sample functionality',
|
||||
'change' => 'There was an issue creating an attribute (attachment: ' . $file['filename'] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
|
||||
));
|
||||
$errors[] = array('filename' => $file['filename'], 'hash' => $file['hash'], 'error' => 'Failed to encrypt and compress the file.');
|
||||
}
|
||||
}
|
||||
if (!empty($errors)) {
|
||||
|
@ -3692,8 +3687,12 @@ class EventsController extends AppController {
|
|||
} else {
|
||||
$json = $this->__buildGraphJson($id);
|
||||
}
|
||||
$this->set('json', $json);
|
||||
$this->set('_serialize', 'json');
|
||||
array_walk_recursive($json, function(&$item, $key){
|
||||
if(!mb_detect_encoding($item, 'utf-8', true)){
|
||||
$item = utf8_encode($item);
|
||||
}
|
||||
});
|
||||
return new CakeResponse(array('body' => json_encode($json), 'status' => 200));
|
||||
}
|
||||
|
||||
private function __buildGraphJson($id, $json = array()) {
|
||||
|
@ -3794,6 +3793,13 @@ class EventsController extends AppController {
|
|||
$links[] = $temp;
|
||||
}
|
||||
$json['links'] = $links;
|
||||
} else {
|
||||
if (!isset($json['links'])) {
|
||||
$json['links'] = array();
|
||||
}
|
||||
if (!isset($json['nodes'])) {
|
||||
$json['nodes'] = array();
|
||||
}
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
|
|
@ -150,6 +150,12 @@ class FeedsController extends AppController {
|
|||
if (empty($this->request->data['Feed']['target_event'])) {
|
||||
$this->request->data['Feed']['target_event'] = 0;
|
||||
}
|
||||
if (empty($this->request->data['Feed']['input_source'])) {
|
||||
$this->request->data['Feed']['input_source'] = 'network';
|
||||
}
|
||||
if (!isset($this->request->data['Feed']['delete_local_file'])) {
|
||||
$this->request->data['Feed']['delete_local_file'] = 0;
|
||||
}
|
||||
$this->request->data['Feed']['settings'] = json_encode($this->request->data['Feed']['settings']);
|
||||
$this->request->data['Feed']['event_id'] = !empty($this->request->data['Feed']['fixed_event']) ? $this->request->data['Feed']['target_event'] : 0;
|
||||
if (!$error) {
|
||||
|
@ -212,7 +218,7 @@ class FeedsController extends AppController {
|
|||
$this->request->data['Feed']['settings']['delimiter'] = ',';
|
||||
}
|
||||
$this->request->data['Feed']['settings'] = json_encode($this->request->data['Feed']['settings']);
|
||||
$fields = array('id', 'name', 'provider', 'enabled', 'rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'override_ids', 'settings');
|
||||
$fields = array('id', 'name', 'provider', 'enabled', 'rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'source_format', 'override_ids', 'settings', 'input_source', 'delete_local_file');
|
||||
$feed = array();
|
||||
foreach ($fields as $field) {
|
||||
if (isset($this->request->data['Feed'][$field])) {
|
||||
|
|
|
@ -287,4 +287,17 @@ class LogsController extends AppController {
|
|||
$this->set('data', $data);
|
||||
$this->set('_serialize', 'data');
|
||||
}
|
||||
|
||||
public function pruneUpdateLogs() {
|
||||
if (!$this->request->is('post')) {
|
||||
//throw new MethodNotAllowedException('This functionality is only accessible via POST requests');
|
||||
}
|
||||
$this->Log->pruneUpdateLogsRouter($this->Auth->user());
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
$this->Session->setFlash('The pruning job is queued.');
|
||||
} else {
|
||||
$this->Session->setFlash('The pruning is complete.');
|
||||
}
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,17 +38,27 @@ class OrganisationsController extends AppController {
|
|||
}
|
||||
}
|
||||
$this->set('passedArgs', json_encode($passedArgs));
|
||||
$this->paginate = array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
);
|
||||
$this->paginate['conditions'] = $conditions;
|
||||
$usersPerOrg = $this->User->getMembersCount();
|
||||
$orgs = $this->paginate();
|
||||
if ($this->_isSiteAdmin()) {
|
||||
$this->loadModel('User');
|
||||
$org_creator_ids = array();
|
||||
foreach ($orgs as $org) {
|
||||
if (!in_array($org['Organisation']['created_by'], $org_creator_ids)) {
|
||||
if ($this->_isRest()) {
|
||||
unset($this->paginate['limit']);
|
||||
$orgs = $this->Organisation->find('all', $this->paginate);
|
||||
} else {
|
||||
if (isset($this->params['named']['viewall']) && $this->params['named']['viewall']) {
|
||||
$orgCount = $this->Organisation->find('count');
|
||||
$this->paginate['limit'] = $orgCount;
|
||||
}
|
||||
$this->set('viewall', isset($this->params['named']['viewall']) ? $this->params['named']['viewall'] : false);
|
||||
$orgs = $this->paginate();
|
||||
}
|
||||
$this->loadModel('User');
|
||||
$org_creator_ids = array();
|
||||
foreach ($orgs as $k => $org) {
|
||||
if (isset($usersPerOrg[$org['Organisation']['id']])) {
|
||||
$orgs[$k]['Organisation']['user_count'] = $usersPerOrg[$org['Organisation']['id']];
|
||||
}
|
||||
if ($this->_isSiteAdmin()) {
|
||||
if (!in_array($org['Organisation']['created_by'], array_keys($org_creator_ids))) {
|
||||
$email = $this->User->find('first', array('recursive' => -1, 'fields' => array('id', 'email'), 'conditions' => array('id' => $org['Organisation']['created_by'])));
|
||||
if (!empty($email)) {
|
||||
$org_creator_ids[$org['Organisation']['created_by']] = $email['User']['email'];
|
||||
|
@ -56,23 +66,59 @@ class OrganisationsController extends AppController {
|
|||
$org_creator_ids[$org['Organisation']['created_by']] = 'Unknown';
|
||||
}
|
||||
}
|
||||
$orgs[$k]['Organisation']['created_by_email'] = $org_creator_ids[$org['Organisation']['created_by']];
|
||||
}
|
||||
$this->set('org_creator_ids', $org_creator_ids);
|
||||
}
|
||||
$this->set('scope', $scope);
|
||||
$this->set('orgs', $orgs);
|
||||
$this->set('members', $usersPerOrg);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($orgs, $this->response->type());
|
||||
} else {
|
||||
$this->set('named', $this->params['named']);
|
||||
$this->set('scope', $scope);
|
||||
$this->set('orgs', $orgs);
|
||||
}
|
||||
}
|
||||
|
||||
public function admin_add() {
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->_isRest()) {
|
||||
if (isset($this->request->data['request'])) {
|
||||
$this->request->data = $this->request->data['request'];
|
||||
}
|
||||
if (!isset($this->request->data['Organisation'])) {
|
||||
$this->request->data['Organisation'] = $this->request->data;
|
||||
}
|
||||
if (isset($this->request->data['Organisation']['id'])){
|
||||
unset($this->request->data['Organisation']['id']);
|
||||
}
|
||||
}
|
||||
$this->Organisation->create();
|
||||
$this->request->data['Organisation']['created_by'] = $this->Auth->user('id');
|
||||
if ($this->_isRest()) {
|
||||
if (!isset($this->request->data['Organisation']['local'])) {
|
||||
$this->request->data['Organisation']['local'] = true;
|
||||
}
|
||||
}
|
||||
if ($this->Organisation->save($this->request->data)) {
|
||||
$this->Session->setFlash('The organisation has been successfully added.');
|
||||
$this->redirect(array('admin' => false, 'action' => 'index'));
|
||||
if ($this->_isRest()) {
|
||||
$org = $this->Organisation->find('first', array(
|
||||
'conditions' => array('Organisation.id' => $this->Organisation->id),
|
||||
'recursive' => -1
|
||||
));
|
||||
return $this->RestResponse->viewData($org, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash('The organisation has been successfully added.');
|
||||
$this->redirect(array('admin' => false, 'action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
$this->Session->setFlash('The organisation could not be added.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Organisations', 'admin_add', false, $this->Organisation->validationErrors, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash('The organisation could not be added.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->describe('Organisations', 'admin_add', false, $this->response->type());
|
||||
}
|
||||
}
|
||||
$this->set('countries', $this->_arrayToValuesIndexArray($this->Organisation->countries));
|
||||
|
@ -82,12 +128,46 @@ class OrganisationsController extends AppController {
|
|||
$this->Organisation->id = $id;
|
||||
if (!$this->Organisation->exists()) throw new NotFoundException('Invalid organisation');
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if ($this->_isRest()) {
|
||||
if (isset($this->request->data['request'])) {
|
||||
$this->request->data = $this->request->data['request'];
|
||||
}
|
||||
if (!isset($this->request->data['Organisation'])) {
|
||||
$this->request->data['Organisation'] = $this->request->data;
|
||||
}
|
||||
$existingOrg = $this->Organisation->find('first', array('conditions' => array('Organisation.id' => $id)));
|
||||
$changeFields = array('name', 'type', 'nationality', 'sector', 'contacts', 'description', 'local', 'uuid');
|
||||
$temp = array('Organisation' => array());
|
||||
foreach ($changeFields as $field) {
|
||||
if (isset($this->request->data['Organisation'][$field])) {
|
||||
$temp['Organisation'][$field] = $this->request->data['Organisation'][$field];
|
||||
} else {
|
||||
$temp['Organisation'][$field] = $existingOrg['Organisation'][$field];
|
||||
}
|
||||
$this->request->data = $temp;
|
||||
}
|
||||
}
|
||||
$this->request->data['Organisation']['id'] = $id;
|
||||
if ($this->Organisation->save($this->request->data)) {
|
||||
$this->Session->setFlash('Organisation updated.');
|
||||
$this->redirect(array('admin' => false, 'action' => 'view', $this->Organisation->id));
|
||||
if ($this->_isRest()) {
|
||||
$org = $this->Organisation->find('first', array(
|
||||
'conditions' => array('Organisation.id' => $this->Organisation->id),
|
||||
'recursive' => -1
|
||||
));
|
||||
return $this->RestResponse->viewData($org, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash('Organisation updated.');
|
||||
$this->redirect(array('admin' => false, 'action' => 'view', $this->Organisation->id));
|
||||
}
|
||||
} else {
|
||||
$this->Session->setFlash('The organisation could not be updated.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Organisations', 'admin_edit', false, $this->Organisation->validationErrors, $this->response->type());
|
||||
$this->Session->setFlash('The organisation could not be updated.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->describe('Organisations', 'admin_edit', false, $this->response->type());
|
||||
}
|
||||
}
|
||||
$this->set('countries', $this->_arrayToValuesIndexArray($this->Organisation->countries));
|
||||
|
@ -110,11 +190,19 @@ class OrganisationsController extends AppController {
|
|||
if ($org['Organisation']['local']) $url = '/organisations/index';
|
||||
else $url = '/organisations/index/remote';
|
||||
if ($this->Organisation->delete()) {
|
||||
$this->Session->setFlash(__('Organisation deleted'));
|
||||
$this->redirect($url);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Organisations', 'admin_delete', $id, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash(__('Organisation deleted'));
|
||||
$this->redirect($url);
|
||||
}
|
||||
} else {
|
||||
$this->Session->setFlash(__('Organisation could not be deleted. Generally organisations should never be deleted, instead consider moving them to the known remote organisations list. Alternatively, if you are certain that you would like to remove an organisation and are aware of the impact, make sure that there are no users or events still tied to this organisation before deleting it.'));
|
||||
$this->redirect($url);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Organisations', 'admin_delete', $id, $this->Organisation->validationErrors, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash(__('Organisation could not be deleted. Generally organisations should never be deleted, instead consider moving them to the known remote organisations list. Alternatively, if you are certain that you would like to remove an organisation and are aware of the impact, make sure that there are no users or events still tied to this organisation before deleting it.'));
|
||||
$this->redirect($url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,28 +212,47 @@ class OrganisationsController extends AppController {
|
|||
}
|
||||
|
||||
public function view($id) {
|
||||
if (Validation::uuid($id)) {
|
||||
$temp = $this->Organisation->find('first', array('recursive' => -1, 'fields' => array('Organisation.id'), 'conditions' => array('Organisation.uuid' => $id)));
|
||||
if (empty($temp)) throw new NotFoundException('Invalid organisation.');
|
||||
$id = $temp['Organisation']['id'];
|
||||
} else if (!is_numeric($id)) {
|
||||
throw new NotFoundException('Invalid organisation.');
|
||||
}
|
||||
$this->Organisation->id = $id;
|
||||
if (!$this->Organisation->exists()) throw new NotFoundException('Invalid organisation');
|
||||
$fullAccess = false;
|
||||
$fields = array('id', 'name', 'date_created', 'date_modified', 'type', 'nationality', 'sector', 'contacts', 'description', 'local', 'uuid');
|
||||
if ($this->_isSiteAdmin() || $this->Auth->user('Organisation')['id'] == $id) {
|
||||
if ($this->_isSiteAdmin() || ($this->_isAdmin() && $this->Auth->user('Organisation')['id'] == $id)) {
|
||||
$fullAccess = true;
|
||||
$fields = array_merge($fields, array('created_by'));
|
||||
}
|
||||
$org = $this->Organisation->find('first', array(
|
||||
'conditions' => array('id' => $id),
|
||||
'fields' => $fields
|
||||
'fields' => $fields,
|
||||
'recursive' => -1
|
||||
));
|
||||
|
||||
$this->set('local', $org['Organisation']['local']);
|
||||
|
||||
if ($fullAccess) {
|
||||
$creator = $this->Organisation->User->find('first', array('conditions' => array('User.id' => $org['Organisation']['created_by'])));
|
||||
$this->set('creator', $creator);
|
||||
$creator = $this->Organisation->User->find('first', array(
|
||||
'conditions' => array('User.id' => $org['Organisation']['created_by']),
|
||||
'fields' => array('email'),
|
||||
'recursive' => -1
|
||||
)
|
||||
);
|
||||
if (!empty($creator)) {
|
||||
$org['Organisation']['created_by_email'] = $creator['User']['email'];
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$org['Organisation']['user_count'] = $this->Organisation->User->getMembersCount($org['Organisation']['id']);
|
||||
return $this->RestResponse->viewData($org, $this->response->type());
|
||||
} else {
|
||||
$this->set('fullAccess', $fullAccess);
|
||||
$this->set('org', $org);
|
||||
$this->set('id', $id);
|
||||
}
|
||||
$this->set('fullAccess', $fullAccess);
|
||||
$this->set('org', $org);
|
||||
$this->set('id', $id);
|
||||
}
|
||||
|
||||
public function landingpage($id) {
|
||||
|
|
|
@ -720,7 +720,7 @@ class ServersController extends AppController {
|
|||
|
||||
// if Proxy is set up in the settings, try to connect to a test URL
|
||||
$proxyStatus = $this->Server->proxyDiagnostics($diagnostic_errors);
|
||||
|
||||
|
||||
$moduleTypes = array('Enrichment', 'Import', 'Export');
|
||||
foreach ($moduleTypes as $type) {
|
||||
$moduleStatus[$type] = $this->Server->moduleDiagnostics($diagnostic_errors, $type);
|
||||
|
@ -738,9 +738,12 @@ class ServersController extends AppController {
|
|||
$writeableFiles = $this->Server->writeableFilesDiagnostics($diagnostic_errors);
|
||||
$readableFiles = $this->Server->readableFilesDiagnostics($diagnostic_errors);
|
||||
$extensions = $this->Server->extensionDiagnostics();
|
||||
|
||||
// check if the encoding is not set to utf8
|
||||
$dbEncodingStatus = $this->Server->databaseEncodingDiagnostics($diagnostic_errors);
|
||||
|
||||
$viewVars = array(
|
||||
'diagnostic_errors', 'tabs', 'tab', 'issues', 'finalSettings', 'writeableErrors', 'readableErrors', 'writeableDirs', 'writeableFiles', 'readableFiles', 'extensions'
|
||||
'diagnostic_errors', 'tabs', 'tab', 'issues', 'finalSettings', 'writeableErrors', 'readableErrors', 'writeableDirs', 'writeableFiles', 'readableFiles', 'extensions', 'dbEncodingStatus'
|
||||
);
|
||||
$viewVars = array_merge($viewVars, $additionalViewVars);
|
||||
foreach ($viewVars as $viewVar) $this->set($viewVar, ${$viewVar});
|
||||
|
@ -1155,4 +1158,9 @@ class ServersController extends AppController {
|
|||
$this->set('response', array('version' => $versionArray['major'] . '.' . $versionArray['minor'] . '.' . $versionArray['hotfix'], 'perm_sync' => $this->userRole['perm_sync']));
|
||||
$this->set('_serialize', 'response');
|
||||
}
|
||||
|
||||
public function getPyMISPVersion() {
|
||||
$this->set('response', array('version' => $this->pyMispVersion));
|
||||
$this->set('_serialize', 'response');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ class ShadowAttributesController extends AppController {
|
|||
$response = $this->__accept($id);
|
||||
if ($this->_isRest()) {
|
||||
if (isset($response['success'])) {
|
||||
$response['check_publish'] = true;
|
||||
$this->set('name', $response['success']);
|
||||
$this->set('message', $response['success']);
|
||||
$this->set('url', '/shadow_attributes/accept/' . $id);
|
||||
|
@ -436,6 +437,11 @@ class ShadowAttributesController extends AppController {
|
|||
$this->set('event_id', $eventId);
|
||||
// combobox for types
|
||||
$types = array_keys($this->ShadowAttribute->typeDefinitions);
|
||||
foreach ($types as $key => $value) {
|
||||
if (in_array($value, array('malware-sample', 'attachment'))) {
|
||||
unset($types[$key]);
|
||||
}
|
||||
}
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
|
@ -705,6 +711,11 @@ class ShadowAttributesController extends AppController {
|
|||
|
||||
// combobox for types
|
||||
$types = array_keys($this->ShadowAttribute->typeDefinitions);
|
||||
foreach ($types as $key => $value) {
|
||||
if (in_array($value, array('malware-sample', 'attachment'))) {
|
||||
unset($types[$key]);
|
||||
}
|
||||
}
|
||||
$types = $this->_arrayToValuesIndexArray($types);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
|
|
|
@ -51,16 +51,9 @@ class SightingsController extends AppController {
|
|||
}
|
||||
} else {
|
||||
if ($error) {
|
||||
$this->set('errors', $error);
|
||||
$this->set('name', 'Could not add the Sighting.');
|
||||
$this->set('message', 'Could not add the Sighting.');
|
||||
$this->set('_serialize', array('name', 'message', 'errors'));
|
||||
return $this->RestResponse->saveFailResponse('Sighting', 'add', $id, $error);
|
||||
} else {
|
||||
$this->set('name', 'Sighting added.');
|
||||
$this->set('message', $result . ' sighting' . (($result == 1) ? '' : 's') . ' successfuly added.');
|
||||
$this->set('url', '/sightings/add/' . $id);
|
||||
$this->set('id', $this->Sighting->id);
|
||||
$this->set('_serialize', array('name', 'message', 'url', 'id'));
|
||||
return $this->RestResponse->saveSuccessResponse('Sighting', 'add', $id, false, $result . ' sighting' . (($result == 1) ? '' : 's') . ' successfuly added.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,15 +69,37 @@ class SightingsController extends AppController {
|
|||
}
|
||||
$result = $this->Sighting->delete($sighting['Sighting']['id']);
|
||||
if (!$result) {
|
||||
$this->set('errors', '');
|
||||
$this->set('name', 'Failed');
|
||||
$this->set('message', 'Could not delete the Sighting.');
|
||||
$this->set('_serialize', array('name', 'message', 'errors'));
|
||||
return $this->RestResponse->saveFailResponse('Sighting', 'delete', $id, 'Could not delete the Sighting.');
|
||||
} else {
|
||||
$this->set('name', 'Success');
|
||||
$this->set('message', 'Sighting successfuly deleted.');
|
||||
$this->set('url', '/sightings/delete/' . $id);
|
||||
$this->set('_serialize', array('name', 'message', 'url'));
|
||||
return $this->RestResponse->saveSuccessResponse('Sighting', 'delete', $id, false, 'Sighting successfuly deleted.');
|
||||
}
|
||||
}
|
||||
|
||||
public function index($eventid = false) {
|
||||
$this->loadModel('Event');
|
||||
$sightingConditions = array();
|
||||
if ($eventid) {
|
||||
$sightingConditions = array('Sighting.event_id' => $eventid);
|
||||
}
|
||||
$sightedEvents = $this->Sighting->find('list', array(
|
||||
'group' => 'Sighting.event_id',
|
||||
'fields' => array('Sighting.event_id'),
|
||||
'conditions' => $sightingConditions
|
||||
));
|
||||
if (empty($sightedEvents)) {
|
||||
$this->RestResponse->viewData(array());
|
||||
}
|
||||
$conditions = array('metadata' => true, 'contain' => false);
|
||||
if ($eventid) {
|
||||
$conditions['eventid'] = $sightedEvents;
|
||||
}
|
||||
$events = $this->Event->fetchEventIds($this->Auth->user(), false, false, false, false, false, false, $sightedEvents);
|
||||
$sightings = array();
|
||||
if (!empty($events)) {
|
||||
foreach ($events as $k => $event) {
|
||||
$sightings = array_merge($sightings, $this->Sighting->attachToEvent($event, $this->Auth->user()));
|
||||
}
|
||||
}
|
||||
return $this->RestResponse->viewData($sightings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ class TagsController extends AppController {
|
|||
'Tag.name' => 'asc'
|
||||
),
|
||||
'contain' => array(
|
||||
'AttributeTag' => array(
|
||||
'fields' => array('attribute_id')
|
||||
),
|
||||
'EventTag' => array(
|
||||
'fields' => array('event_id')
|
||||
),
|
||||
|
@ -24,6 +27,7 @@ class TagsController extends AppController {
|
|||
public $helpers = array('TextColour');
|
||||
|
||||
public function index($favouritesOnly = false) {
|
||||
$this->loadModel('Attribute');
|
||||
$this->loadModel('Event');
|
||||
$this->loadModel('Taxonomy');
|
||||
$taxonomies = $this->Taxonomy->listTaxonomies(array('full' => false, 'enabled' => true));
|
||||
|
@ -69,6 +73,35 @@ class TagsController extends AppController {
|
|||
$paginated[$k]['Tag']['count'] = count($events);
|
||||
}
|
||||
unset($paginated[$k]['EventTag']);
|
||||
if (empty($tag['AttributeTag'])) {
|
||||
$paginated[$k]['Tag']['attribute_count'] = 0;
|
||||
} else {
|
||||
$attributeIDs = array();
|
||||
foreach ($tag['AttributeTag'] as $attributeTag) {
|
||||
$attributeIDs[] = $attributeTag['attribute_id'];
|
||||
}
|
||||
$conditions = array('Attribute.id' => $attributeIDs);
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array_merge(
|
||||
$conditions,
|
||||
array('OR' => array(
|
||||
array('AND' => array(
|
||||
array('Attribute.deleted =' => 0),
|
||||
array('Attribute.distribution >' => 0),
|
||||
array('Event.distribution >' => 0),
|
||||
array('Event.published =' => 1)
|
||||
)),
|
||||
array('Event.orgc_id' => $this->Auth->user('org_id'))
|
||||
)));
|
||||
}
|
||||
$attributes = $this->Attribute->find('all', array(
|
||||
'fields' => array('Attribute.id', 'Attribute.deleted', 'Attribute.distribution', 'Event.id', 'Event.distribution', 'Event.orgc_id'),
|
||||
'contain' => array('Event' => array('fields' => array('id', 'distribution', 'orgc_id'))),
|
||||
'conditions' => $conditions
|
||||
));
|
||||
$paginated[$k]['Tag']['attribute_count'] = count($attributes);
|
||||
}
|
||||
unset($paginated[$k]['AttributeTag']);
|
||||
if (!empty($tag['FavouriteTag'])) {
|
||||
foreach ($tag['FavouriteTag'] as $ft) if ($ft['user_id'] == $this->Auth->user('id')) $paginated[$k]['Tag']['favourite'] = true;
|
||||
if (!isset($tag['Tag']['favourite'])) $paginated[$k]['Tag']['favourite'] = false;
|
||||
|
@ -213,10 +246,12 @@ class TagsController extends AppController {
|
|||
|
||||
public function view($id) {
|
||||
if ($this->_isRest()) {
|
||||
$contain = array('EventTag' => array('fields' => 'event_id'));
|
||||
$contain['AttributeTag'] = array('fields' => 'attribute_id');
|
||||
$tag = $this->Tag->find('first', array(
|
||||
'conditions' => array('id' => $id),
|
||||
'recursive' => -1,
|
||||
'contain' => array('EventTag' => array('fields' => 'event_id'))
|
||||
'contain' => $contain
|
||||
));
|
||||
if (empty($tag)) throw new MethodNotAllowedException('Invalid Tag');
|
||||
if (empty($tag['EventTag'])) $tag['Tag']['count'] = 0;
|
||||
|
@ -242,6 +277,35 @@ class TagsController extends AppController {
|
|||
$tag['Tag']['count'] = count($events);
|
||||
}
|
||||
unset($tag['EventTag']);
|
||||
if (empty($tag['AttributeTag'])) {
|
||||
$tag['Tag']['attribute_count'] = 0;
|
||||
} else {
|
||||
$attributeIDs = array();
|
||||
foreach ($tag['AttributeTag'] as $attributeTag) {
|
||||
$attributeIDs[] = $attributeTag['attribute_id'];
|
||||
}
|
||||
$conditions = array('Attribute.id' => $attributeIDs);
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array_merge(
|
||||
$conditions,
|
||||
array('OR' => array(
|
||||
array('AND' => array(
|
||||
array('Attribute.deleted =' => 0),
|
||||
array('Attribute.distribution >' => 0),
|
||||
array('Event.distribution >' => 0),
|
||||
array('Event.published =' => 1)
|
||||
)),
|
||||
array('Event.orgc_id' => $this->Auth->user('org_id'))
|
||||
)));
|
||||
}
|
||||
$attributes = $this->Tag->AttributeTag->Attribute->find('all', array(
|
||||
'fields' => array('Attribute.id', 'Attribute.deleted', 'Attribute.distribution', 'Event.id', 'Event.distribution', 'Event.orgc_id'),
|
||||
'contain' => array('Event' => array('fields' => array('id', 'distribution', 'orgc_id'))),
|
||||
'conditions' => $conditions
|
||||
));
|
||||
$tag['Tag']['attribute_count'] = count($attributes);
|
||||
}
|
||||
unset($tag['AttributeTag']);
|
||||
$this->set('Tag', $tag['Tag']);
|
||||
$this->set('_serialize', 'Tag');
|
||||
} else throw new MethodNotAllowedException('This action is only for REST users.');
|
||||
|
@ -275,6 +339,34 @@ class TagsController extends AppController {
|
|||
$this->render('/Events/ajax/ajaxTags');
|
||||
}
|
||||
|
||||
public function showAttributeTag($id) {
|
||||
$this->helpers[] = 'TextColour';
|
||||
$this->loadModel('AttributeTag');
|
||||
|
||||
$this->Tag->AttributeTag->Attribute->id = $id;
|
||||
if (!$this->Tag->AttributeTag->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
|
||||
$this->Tag->AttributeTag->Attribute->read();
|
||||
$eventId = $this->Tag->AttributeTag->Attribute->data['Attribute']['event_id'];
|
||||
|
||||
$attributeTags = $this->AttributeTag->find('all', array(
|
||||
'conditions' => array(
|
||||
'attribute_id' => $id
|
||||
),
|
||||
'contain' => array('Tag'),
|
||||
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
|
||||
));
|
||||
$event = $this->Tag->AttributeTag->Attribute->Event->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),
|
||||
'conditions' => array('Event.id' => $eventId)
|
||||
));
|
||||
$this->set('event', $event);
|
||||
$this->set('attributeTags', $attributeTags);
|
||||
$this->set('attributeId', $id);
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/Attributes/ajax/ajaxAttributeTags');
|
||||
}
|
||||
|
||||
public function viewTag($id) {
|
||||
$tag = $this->Tag->find('first', array(
|
||||
'conditions' => array(
|
||||
|
@ -289,7 +381,7 @@ class TagsController extends AppController {
|
|||
}
|
||||
|
||||
|
||||
public function selectTaxonomy($event_id) {
|
||||
public function selectTaxonomy($id, $attributeTag = false) {
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) throw new NotFoundException('You don\'t have permission to do that.');
|
||||
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
|
||||
$this->loadModel('Taxonomy');
|
||||
|
@ -298,13 +390,16 @@ class TagsController extends AppController {
|
|||
$tags = $this->Taxonomy->getTaxonomyTags($k, false, true);
|
||||
if (empty($tags)) unset($options[$k]);
|
||||
}
|
||||
$this->set('event_id', $event_id);
|
||||
if ($attributeTag !== false) {
|
||||
$this->set('attributeTag', true);
|
||||
}
|
||||
$this->set('object_id', $id);
|
||||
$this->set('options', $options);
|
||||
$this->set('favourites', $favourites);
|
||||
$this->render('ajax/taxonomy_choice');
|
||||
}
|
||||
|
||||
public function selectTag($event_id, $taxonomy_id) {
|
||||
public function selectTag($id, $taxonomy_id, $attributeTag = false) {
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) throw new NotFoundException('You don\'t have permission to do that.');
|
||||
$this->loadModel('Taxonomy');
|
||||
$expanded = array();
|
||||
|
@ -357,12 +452,15 @@ class TagsController extends AppController {
|
|||
unset($expanded[$banned_tag]);
|
||||
}
|
||||
}
|
||||
if ($attributeTag !== false) {
|
||||
$this->set('attributeTag', true);
|
||||
}
|
||||
$this->set('object_id', $id);
|
||||
foreach ($options as $k => $v) {
|
||||
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
|
||||
unset($options[$k]);
|
||||
}
|
||||
}
|
||||
$this->set('event_id', $event_id);
|
||||
$this->set('options', $options);
|
||||
$this->set('expanded', $expanded);
|
||||
$this->set('custom', $taxonomy_id == 0 ? true : false);
|
||||
|
@ -415,4 +513,130 @@ class TagsController extends AppController {
|
|||
$this->response->type('json');
|
||||
$this->render('/Servers/json/simple');
|
||||
}
|
||||
|
||||
private function __findObjectByUuid($object_uuid, &$type) {
|
||||
$this->loadModel('Event');
|
||||
$object = $this->Event->find('first', array(
|
||||
'conditions' => array(
|
||||
'Event.uuid' => $object_uuid,
|
||||
),
|
||||
'fields' => array('Event.orgc_id', 'Event.id'),
|
||||
'recursive' => -1
|
||||
));
|
||||
$type = 'Event';
|
||||
if (!empty($object)) {
|
||||
if (!$this->_isSiteAdmin() && $object['Event']['orgc_id'] != $this->Auth->user('org_id')) {
|
||||
throw new MethodNotAllowedException('Invalid Target.');
|
||||
}
|
||||
} else {
|
||||
$type = 'Attribute';
|
||||
$object = $this->Event->Attribute->find('first', array(
|
||||
'conditions' => array(
|
||||
'Attribute.uuid' => $object_uuid,
|
||||
),
|
||||
'fields' => array('Attribute.id'),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Event.orgc_id')
|
||||
));
|
||||
if (!empty($object)) {
|
||||
if (!$this->_isSiteAdmin() && $object['Event']['orgc_id'] != $this->Auth->user('org_id')) {
|
||||
throw new MethodNotAllowedException('Invalid Target.');
|
||||
}
|
||||
} else {
|
||||
throw new MethodNotAllowedException('Invalid Target.');
|
||||
}
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function attachTagToObject($object_uuid, $tag) {
|
||||
if (!Validation::uuid($object_uuid)) {
|
||||
throw new InvalidArgumentException('Invalid UUID');
|
||||
}
|
||||
if (is_numeric($tag)) {
|
||||
$conditions = array('Tag.id' => $tag);
|
||||
} else {
|
||||
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag)));
|
||||
}
|
||||
$objectType = '';
|
||||
$object = $this->__findObjectByUuid($object_uuid, $objectType);
|
||||
$existingTag = $this->Tag->find('first', array('conditions' => $conditions, 'recursive' => -1));
|
||||
if (empty($existingTag)) {
|
||||
if (!is_numeric($tag)) {
|
||||
if (!$this->userRole['perm_tag_editor']) {
|
||||
throw new InvalidArgumentException('Tag not found and insufficient privileges to create it.');
|
||||
}
|
||||
$this->Tag->create();
|
||||
$this->Tag->save(array('Tag' => array('name' => $tag, 'colour' => $this->Tag->random_color())));
|
||||
$existingTag = $this->Tag->find('first', array('recursive' => -1, 'conditions' => array('Tag.id' => $this->Tag->id)));
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid Tag.');
|
||||
}
|
||||
}
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if (!in_array($existingTag['Tag']['org_id'], array(0, $this->Auth->user('org_id')))) {
|
||||
throw new MethodNotAllowedException('Invalid Tag.');
|
||||
}
|
||||
}
|
||||
$this->loadModel($objectType);
|
||||
$connectorObject = $objectType . 'Tag';
|
||||
$existingAssociation = $this->$objectType->$connectorObject->find('first', array(
|
||||
'conditions' => array(
|
||||
strtolower($objectType) . '_id' => $object[$objectType]['id'],
|
||||
'tag_id' => $existingTag['Tag']['id']
|
||||
)
|
||||
));
|
||||
if (!empty($existingAssociation)) {
|
||||
throw new MethodNotAllowedException('Cannot attach tag, ' . $objectType . ' already has the tag attached.');
|
||||
}
|
||||
$this->$objectType->$connectorObject->create();
|
||||
$result = $this->$objectType->$connectorObject->save(array($connectorObject => array(
|
||||
strtolower($objectType) . '_id' => $object[$objectType]['id'],
|
||||
'tag_id' => $existingTag['Tag']['id']
|
||||
)));
|
||||
if ($result) {
|
||||
$message = 'Tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully attached to ' . $objectType . '(' . $object[$objectType]['id'] . ').';
|
||||
return $this->RestResponse->saveSuccessResponse('Tags', 'attachTagToObject', false, $this->response->type(), $message);
|
||||
} else {
|
||||
return $this->RestResponse->saveFailResponse('Tags', 'attachTagToObject', false, 'Failed to attach tag to object.', $this->response->type());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeTagFromObject($object_uuid, $tag) {
|
||||
if (!Validation::uuid($object_uuid)) {
|
||||
throw new InvalidArgumentException('Invalid UUID');
|
||||
}
|
||||
if (is_numeric($tag)) {
|
||||
$conditions = array('Tag.id' => $tag);
|
||||
} else {
|
||||
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag)));
|
||||
}
|
||||
$existingTag = $this->Tag->find('first', array('conditions' => $conditions, 'recursive' => -1));
|
||||
if (empty($existingTag)) {
|
||||
throw new MethodNotAllowedException('Invalid Tag.');
|
||||
}
|
||||
$objectType = '';
|
||||
$object = $this->__findObjectByUuid($object_uuid, $objectType);
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid Target.');
|
||||
}
|
||||
$connectorObject = $objectType . 'Tag';
|
||||
$this->loadModel($objectType);
|
||||
$existingAssociation = $this->$objectType->$connectorObject->find('first', array(
|
||||
'conditions' => array(
|
||||
strtolower($objectType) . '_id' => $object[$objectType]['id'],
|
||||
'tag_id' => $existingTag['Tag']['id']
|
||||
)
|
||||
));
|
||||
if (empty($existingAssociation)) {
|
||||
throw new MethodNotAllowedException('Could not remove tag as it is not attached to the target ' . $objectType);
|
||||
}
|
||||
$result = $this->$objectType->$connectorObject->delete($existingAssociation[$connectorObject]['id']);
|
||||
if ($result) {
|
||||
$message = 'Tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully removed from ' . $objectType . '(' . $object[$objectType]['id'] . ').';
|
||||
return $this->RestResponse->saveSuccessResponse('Tags', 'removeTagFromObject', false, $this->response->type(), $message);
|
||||
} else {
|
||||
return $this->RestResponse->saveFailResponse('Tags', 'removeTagFromObject', false, 'Failed to remove tag from object.', $this->response->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,68 +19,37 @@ class ThreadsController extends AppController {
|
|||
public function viewEvent($id) {
|
||||
$this->loadModel('Event');
|
||||
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));
|
||||
if (empty($result)) throw new MethodNotAllowedException('You are not authorised to see that.');
|
||||
$result = $result[0];
|
||||
// Show the discussion
|
||||
|
||||
$this->Thread->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
$params = array('conditions' => array('event_id' => $id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'event_id', 'distribution', 'title', 'sharing_group_id')
|
||||
);
|
||||
$thread = $this->Thread->find('first', $params);
|
||||
if (empty($thread)) {
|
||||
$newThread = array(
|
||||
'date_created' => date('Y/m/d H:i:s'),
|
||||
'date_modified' => date('Y/m/d H:i:s'),
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'event_id' => $id,
|
||||
'title' => 'Discussion about Event #' . $result['Event']['id'] . ' (' . $result['Event']['info'] . ')',
|
||||
'distribution' => $result['Event']['distribution'],
|
||||
'sharing_group_id' => $result['Event']['sharing_group_id'],
|
||||
'post_count' => 0,
|
||||
'org_id' => $result['Event']['orgc_id']
|
||||
);
|
||||
$this->Thread->save($newThread);
|
||||
$thread = ($this->Thread->read());
|
||||
} else {
|
||||
if ($thread['Thread']['distribution'] != $result['Event']['distribution']) {
|
||||
$thread['Thread']['distribution'] = $result['Event']['distribution'];
|
||||
$this->Thread->save($thread);
|
||||
}
|
||||
if ($thread['Thread']['sharing_group_id'] != $result['Event']['sharing_group_id']) {
|
||||
$thread['Thread']['sharing_group_id'] = $result['Event']['sharing_group_id'];
|
||||
$this->Thread->save($thread);
|
||||
}
|
||||
}
|
||||
$this->loadModel('Post');
|
||||
$this->paginate['Post'] = array(
|
||||
'limit' => 5,
|
||||
'conditions' => array('Post.thread_id' => $thread['Thread']['id']),
|
||||
'contain' => array('User' => array('Organisation' => array('fields' => array('id', 'name')))),
|
||||
);
|
||||
$posts = $this->paginate('Post');
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
foreach ($posts as $key => $post) {
|
||||
if ($post['User']['org_id'] != $this->Auth->user('org_id')) {
|
||||
$posts[$key]['User']['email'] = 'User ' . $post['User']['id'] . ' (' . $post['User']['org_id'] . ')';
|
||||
$thread_id = false;
|
||||
if ($result) {
|
||||
$thread_id = $this->Thread->find('first', array('recursive' => -1, 'conditions' => array('Thread.event_id' => $id), 'fields' => array('Thread.id')));
|
||||
if ($thread_id) {
|
||||
if (!$this->_isRest()) {
|
||||
$this->redirect(array('action' => 'view', $thread_id['Thread']['id'], true));
|
||||
} else {
|
||||
return $this->__view($thread_id['Thread']['id'], false, false);
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData(array(), $this->response->type());
|
||||
} else {
|
||||
throw new NotFoundException('Invalid Thread.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new NotFoundException('Invalid Event.');
|
||||
}
|
||||
// Show the discussion
|
||||
$this->set('posts', $posts);
|
||||
$this->set('thread_id', $thread['Thread']['id']);
|
||||
$this->set('myuserid', $this->Auth->user('id'));
|
||||
$this->set('thread_title', $thread['Thread']['title']);
|
||||
$this->disableCache();
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/Elements/eventdiscussion');
|
||||
}
|
||||
|
||||
|
||||
public function view($thread_id, $eventView = false) {
|
||||
$post_id = false;
|
||||
if (isset($this->passedArgs['post_id'])) $post_id = $this->passedArgs['post_id'];
|
||||
$response = $this->__view($thread_id, $eventView, $post_id);
|
||||
if ($this->_isRest()) {
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
private function __view($thread_id, $eventView, $post_id) {
|
||||
if ($eventView) {
|
||||
$id = $thread_id;
|
||||
// Show the discussion
|
||||
|
@ -111,7 +80,6 @@ class ThreadsController extends AppController {
|
|||
throw new NotFoundException('Invalid thread.');
|
||||
}
|
||||
$thread = $this->Thread->read();
|
||||
|
||||
// If the thread belongs to an event, we have to make sure that the event's distribution level hasn't changed.
|
||||
// This is also a good time to update the thread's distribution level if that did happen.
|
||||
if (!empty($thread['Thread']['event_id'])) {
|
||||
|
@ -144,24 +112,41 @@ class ThreadsController extends AppController {
|
|||
'conditions' => array('Post.thread_id' => $thread_id),
|
||||
'contain' => array(
|
||||
'User' => array(
|
||||
'fields' => array('User.email', 'User.id'),
|
||||
'Organisation' => array(
|
||||
'fields' => array('id', 'name')
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
$posts = $this->paginate('Post');
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
foreach ($posts as $key => $post) {
|
||||
if ($post['User']['org_id'] != $this->Auth->user('org_id')) {
|
||||
$posts[$key]['User']['email'] = 'User ' . $post['User']['id'] . ' (' . $post['User']['org_id'] . ')';
|
||||
if ($this->_isRest()) {
|
||||
$posts = $this->Thread->Post->find('all', array(
|
||||
'contain' => $this->paginate['contain'],
|
||||
'conditions' => $this->paginate['conditions']
|
||||
));
|
||||
} else {
|
||||
$posts = $this->paginate('Post');
|
||||
}
|
||||
foreach ($posts as $k => $post) {
|
||||
if (!empty($post['User'])) {
|
||||
$posts[$k]['Post']['org_name'] = $post['User']['Organisation']['name'];
|
||||
if ($this->_isSiteAdmin() || $this->Auth->user('org_id') == $post['User']['org_id']) {
|
||||
$posts[$k]['Post']['user_email'] = $post['User']['email'];
|
||||
}
|
||||
$posts[$k]['Post']['user_id'] = $post['User']['id'];
|
||||
$posts[$k] = $posts[$k]['Post'];
|
||||
}
|
||||
}
|
||||
$this->set('posts', $posts);
|
||||
$this->set('post_id', $post_id);
|
||||
$this->set('thread_id', $thread_id);
|
||||
$this->set('thread_title', $thread['Thread']['title']);
|
||||
if ($this->_isRest()) {
|
||||
if (!empty($posts)) {
|
||||
$thread['Thread']['Post'] = $posts;
|
||||
}
|
||||
return $this->RestResponse->viewData($thread, $this->response->type());
|
||||
} else {
|
||||
$this->set('posts', $posts);
|
||||
$this->set('post_id', $post_id);
|
||||
$this->set('thread', $thread);
|
||||
}
|
||||
}
|
||||
if ($eventView) {
|
||||
$this->set('context', 'event');
|
||||
|
|
|
@ -382,6 +382,15 @@ class UsersController extends AppController {
|
|||
}
|
||||
$fieldList = array('password', 'email', 'external_auth_required', 'external_auth_key', 'enable_password', 'confirm_password', 'org_id', 'role_id', 'authkey', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'invited_by', 'change_pw', 'termsaccepted', 'newsread');
|
||||
if ($this->User->save($this->request->data, true, $fieldList)) {
|
||||
$notification_message = '';
|
||||
if ($this->request->data['User']['notify']) {
|
||||
$user = $this->User->find('first', array('conditions' => array('User.id' => $this->User->id), 'recursive' => -1));
|
||||
$password = isset($this->request->data['User']['password']) ? $this->request->data['User']['password'] : false;
|
||||
$result = $this->User->initiatePasswordReset($user, true, true, $password);
|
||||
if ($result) {
|
||||
$notification_message .= ' User notified of new credentials.';
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$user = $this->User->find('first', array(
|
||||
'conditions' => array('User.id' => $this->User->id),
|
||||
|
@ -390,7 +399,7 @@ class UsersController extends AppController {
|
|||
$user['User']['password'] = '******';
|
||||
return $this->RestResponse->viewData($user, $this->response->type());
|
||||
} else {
|
||||
$this->Session->setFlash(__('The user has been saved'));
|
||||
$this->Session->setFlash(__('The user has been saved.' . $notification_message));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
|
@ -711,6 +720,7 @@ class UsersController extends AppController {
|
|||
}
|
||||
}
|
||||
if ($this->User->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$org = array('Organisation' => array(
|
||||
'id' => 1,
|
||||
'name' => !empty(Configure::read('MISP.org')) ? Configure::read('MISP.org') : 'ADMIN',
|
||||
|
@ -718,6 +728,7 @@ class UsersController extends AppController {
|
|||
'type' => 'ADMIN',
|
||||
'uuid' => CakeText::uuid(),
|
||||
'local' => 1,
|
||||
'date_created' => $date,
|
||||
'sector' => '',
|
||||
'nationality' => ''
|
||||
));
|
||||
|
@ -817,7 +828,7 @@ class UsersController extends AppController {
|
|||
}
|
||||
|
||||
public function histogram($selected = null) {
|
||||
if (!$this->request->is('ajax')) throw new MethodNotAllowedException('This function can only be accessed via AJAX.');
|
||||
if (!$this->request->is('ajax') && !$this->_isRest()) throw new MethodNotAllowedException('This function can only be accessed via AJAX or the API.');
|
||||
if ($selected == '[]') $selected = null;
|
||||
$selectedTypes = array();
|
||||
if ($selected) $selectedTypes = json_decode($selected);
|
||||
|
@ -877,9 +888,13 @@ class UsersController extends AppController {
|
|||
foreach ($sigTypes as $k => $type) {
|
||||
$typeDb[$type] = $colours[$k];
|
||||
}
|
||||
$this->set('typeDb', $typeDb);
|
||||
$this->set('sigTypes', $sigTypes);
|
||||
$this->layout = 'ajax';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->set('typeDb', $typeDb);
|
||||
$this->set('sigTypes', $sigTypes);
|
||||
$this->layout = 'ajax';
|
||||
}
|
||||
}
|
||||
|
||||
public function terms() {
|
||||
|
@ -1022,26 +1037,7 @@ class UsersController extends AppController {
|
|||
}
|
||||
if ($this->request->is('post')) {
|
||||
if (isset($this->request->data['User']['firstTime'])) $firstTime = $this->request->data['User']['firstTime'];
|
||||
$org = Configure::read('MISP.org');
|
||||
$options = array('passwordResetText', 'newUserText');
|
||||
$subjects = array('[' . $org . ' MISP] New user registration', '[' . $org . ' MISP] Password reset');
|
||||
$textToFetch = $options[($firstTime ? 0 : 1)];
|
||||
$subject = $subjects[($firstTime ? 0 : 1)];
|
||||
$this->loadModel('Server');
|
||||
$body = Configure::read('MISP.' . $textToFetch);
|
||||
if (!$body) $body = $this->Server->serverSettings['MISP'][$textToFetch]['value'];
|
||||
$body = $this->User->adminMessageResolve($body);
|
||||
$password = $this->User->generateRandomPassword();
|
||||
$body = str_replace('$password', $password, $body);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
$result = $this->User->sendEmail($user, $body, false, $subject);
|
||||
if ($result) {
|
||||
$this->User->id = $user['User']['id'];
|
||||
$this->User->saveField('password', $password);
|
||||
$this->User->saveField('change_pw', '1');
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'New credentials sent.')),'status'=>200));
|
||||
}
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'There was an error notifying the user. His/her credentials were not altered.')),'status'=>200));
|
||||
return new CakeResponse($this->User->initiatePasswordReset($user, $id, $firstTime));
|
||||
} else {
|
||||
$this->layout = 'ajax';
|
||||
$this->set('user', $user);
|
||||
|
@ -1054,14 +1050,22 @@ class UsersController extends AppController {
|
|||
public function statistics($page = 'data') {
|
||||
$this->set('page', $page);
|
||||
$this->set('pages', array('data' => 'Usage data', 'orgs' => 'Organisations', 'tags' => 'Tags', 'attributehistogram' => 'Attribute histogram'));
|
||||
$result = array();
|
||||
if ($page == 'data') {
|
||||
$this->__statisticsData($this->params['named']);
|
||||
$result = $this->__statisticsData($this->params['named']);
|
||||
} else if ($page == 'orgs') {
|
||||
$this->__statisticsOrgs($this->params['named']);
|
||||
$result = $this->__statisticsOrgs($this->params['named']);
|
||||
} else if ($page == 'tags') {
|
||||
$this->__statisticsTags($this->params['named']);
|
||||
$result = $this->__statisticsTags($this->params['named']);
|
||||
} else if ($page == 'attributehistogram') {
|
||||
$this->render('statistics_histogram');
|
||||
if ($this->_isRest()) {
|
||||
return $this->histogram($selected = null);
|
||||
} else {
|
||||
$this->render('statistics_histogram');
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1078,37 +1082,45 @@ class UsersController extends AppController {
|
|||
}
|
||||
// Some additional statistics
|
||||
$this_month = strtotime('first day of this month');
|
||||
$stats[0] = $this->User->Event->find('count', null);
|
||||
$stats[1] = $this->User->Event->find('count', array('conditions' => array('Event.timestamp >' => $this_month)));
|
||||
$stats['event_count'] = $this->User->Event->find('count', null);
|
||||
$stats['event_count_month'] = $this->User->Event->find('count', array('conditions' => array('Event.timestamp >' => $this_month)));
|
||||
|
||||
$stats[2] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.deleted' => 0)));
|
||||
$stats[3] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.timestamp >' => $this_month, 'Attribute.deleted' => 0)));
|
||||
$stats['attribute_count'] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.deleted' => 0)));
|
||||
$stats['attribute_count_month'] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.timestamp >' => $this_month, 'Attribute.deleted' => 0)));
|
||||
|
||||
$this->loadModel('Correlation');
|
||||
$this->Correlation->recursive = -1;
|
||||
$stats[4] = $this->Correlation->find('count', null);
|
||||
$stats[4] = $stats[4] / 2;
|
||||
$stats['correlation_count'] = $this->Correlation->find('count', null);
|
||||
$stats['correlation_count'] = $stats['correlation_count'] / 2;
|
||||
|
||||
$stats[5] = $this->User->Event->ShadowAttribute->find('count', null);
|
||||
$stats['proposal_count'] = $this->User->Event->ShadowAttribute->find('count', null);
|
||||
|
||||
$stats[6] = $this->User->find('count', null);
|
||||
$stats[7] = count($orgs);
|
||||
$stats['user_count'] = $this->User->find('count', null);
|
||||
$stats['org_count'] = count($orgs);
|
||||
|
||||
$this->loadModel('Thread');
|
||||
$stats[8] = $this->Thread->find('count', array('conditions' => array('Thread.post_count >' => 0)));
|
||||
$stats[9] = $this->Thread->find('count', array('conditions' => array('Thread.date_created >' => date("Y-m-d H:i:s",$this_month), 'Thread.post_count >' => 0)));
|
||||
$stats['thread_count'] = $this->Thread->find('count', array('conditions' => array('Thread.post_count >' => 0)));
|
||||
$stats['thread_count_month'] = $this->Thread->find('count', array('conditions' => array('Thread.date_created >' => date("Y-m-d H:i:s",$this_month), 'Thread.post_count >' => 0)));
|
||||
|
||||
$stats[10] = $this->Thread->Post->find('count', null);
|
||||
$stats[11] = $this->Thread->Post->find('count', array('conditions' => array('Post.date_created >' => date("Y-m-d H:i:s",$this_month))));
|
||||
$stats['post_count'] = $this->Thread->Post->find('count', null);
|
||||
$stats['post_count_month'] = $this->Thread->Post->find('count', array('conditions' => array('Post.date_created >' => date("Y-m-d H:i:s",$this_month))));
|
||||
|
||||
$this->set('stats', $stats);
|
||||
$this->set('orgs', $orgs);
|
||||
$this->set('start', strtotime(date('Y-m-d H:i:s') . ' -5 months'));
|
||||
$this->set('end', strtotime(date('Y-m-d H:i:s')));
|
||||
$this->set('startDateCal', $year . ', ' . $month . ', 01');
|
||||
$range = '[5, 10, 50, 100]';
|
||||
$this->set('range', $range);
|
||||
$this->render('statistics_data');
|
||||
|
||||
if ($this->_isRest()) {
|
||||
$data = array(
|
||||
'stats' => $stats
|
||||
);
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->set('stats', $stats);
|
||||
$this->set('orgs', $orgs);
|
||||
$this->set('start', strtotime(date('Y-m-d H:i:s') . ' -5 months'));
|
||||
$this->set('end', strtotime(date('Y-m-d H:i:s')));
|
||||
$this->set('startDateCal', $year . ', ' . $month . ', 01');
|
||||
$range = '[5, 10, 50, 100]';
|
||||
$this->set('range', $range);
|
||||
$this->render('statistics_data');
|
||||
}
|
||||
}
|
||||
|
||||
private function __statisticsOrgs($params = array()) {
|
||||
|
@ -1155,9 +1167,13 @@ class UsersController extends AppController {
|
|||
$orgs[$k]['logo'] = true;
|
||||
}
|
||||
}
|
||||
$this->set('scope', $params['scope']);
|
||||
$this->set('orgs', $orgs);
|
||||
$this->render('statistics_orgs');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($orgs, $this->response->type());
|
||||
} else {
|
||||
$this->set('scope', $params['scope']);
|
||||
$this->set('orgs', $orgs);
|
||||
$this->render('statistics_orgs');
|
||||
}
|
||||
}
|
||||
|
||||
public function tagStatisticsGraph() {
|
||||
|
@ -1198,19 +1214,31 @@ class UsersController extends AppController {
|
|||
}
|
||||
$taxonomyColourCodes = array();
|
||||
$taxonomies = array_merge(array('custom'), $taxonomies);
|
||||
$this->set('taxonomyColourCodes', $taxonomyColourCodes);
|
||||
$this->set('taxonomies', $taxonomies);
|
||||
$this->set('flatData', $flatData);
|
||||
$this->set('treemap', $treemap);
|
||||
$this->set('tags', $tags);
|
||||
$this->layout = 'treemap';
|
||||
$this->render('ajax/tag_statistics_graph');
|
||||
if ($this->_isRest()) {
|
||||
$data = array(
|
||||
'flatData' => $flatData,
|
||||
'treemap' => $treemap
|
||||
);
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->set('taxonomyColourCodes', $taxonomyColourCodes);
|
||||
$this->set('taxonomies', $taxonomies);
|
||||
$this->set('flatData', $flatData);
|
||||
$this->set('treemap', $treemap);
|
||||
$this->set('tags', $tags);
|
||||
$this->layout = 'treemap';
|
||||
$this->render('ajax/tag_statistics_graph');
|
||||
}
|
||||
}
|
||||
|
||||
private function __statisticsTags($params = array()) {
|
||||
$trending_tags = array();
|
||||
$all_tags = array();
|
||||
$this->render('statistics_tags');
|
||||
if ($this->_isRest()) {
|
||||
return $this->tagStatisticsGraph();
|
||||
} else {
|
||||
$this->render('statistics_tags');
|
||||
}
|
||||
}
|
||||
|
||||
public function verifyGPG() {
|
||||
|
|
|
@ -496,4 +496,32 @@ class NidsExport {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getProtocolPort($protocol, $customPort) {
|
||||
if($customPort == null) {
|
||||
switch ($protocol) {
|
||||
case "http":
|
||||
return '$HTTP_PORTS';
|
||||
case "https":
|
||||
return '443';
|
||||
case "ssh":
|
||||
return '22';
|
||||
case "ftp":
|
||||
return '[20,21]';
|
||||
default:
|
||||
return 'any';
|
||||
}
|
||||
} else {
|
||||
return $customPort;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getCustomIP($customIP) {
|
||||
if(filter_var($customIP, FILTER_VALIDATE_IP)) {
|
||||
return $customIP;
|
||||
}
|
||||
else {
|
||||
return '$EXTERNAL_NET';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,28 +88,124 @@ class NidsSuricataExport extends NidsExport {
|
|||
}
|
||||
|
||||
public function urlRule($ruleFormat, $attribute, &$sid) {
|
||||
// TODO in hindsight, an url should not be excluded given a host or domain name.
|
||||
//$hostpart = parse_url($attribute['value'], PHP_URL_HOST);
|
||||
//$overruled = $this->checkNames($hostpart);
|
||||
// warning: only suricata compatible
|
||||
$createRule = true;
|
||||
$overruled = $this->checkWhitelist($attribute['value']);
|
||||
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
|
||||
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_uri;';
|
||||
$this->rules[] = sprintf($ruleFormat,
|
||||
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
|
||||
'http', // proto
|
||||
'$HOME_NET', // src_ip
|
||||
'any', // src_port
|
||||
'->', // direction
|
||||
'$EXTERNAL_NET', // dst_ip
|
||||
'any', // dst_port
|
||||
'Outgoing HTTP URL: ' . $attribute['value'], // msg
|
||||
$content, // rule_content
|
||||
'tag:session,600,seconds;', // tag
|
||||
$sid, // sid
|
||||
1 // rev
|
||||
);
|
||||
}
|
||||
|
||||
$scheme = parse_url($attribute['value'], PHP_URL_SCHEME);
|
||||
$data = parse_url($attribute['value']);
|
||||
if (!array_key_exists('port', $data)) {
|
||||
$data['port'] = null;
|
||||
}
|
||||
|
||||
switch ($scheme) {
|
||||
case "http":
|
||||
$data['host'] = NidsExport::replaceIllegalChars($data['host']);
|
||||
|
||||
$suricata_protocol = 'http';
|
||||
$suricata_src_ip = '$HOME_NET';
|
||||
$suricata_src_port = 'any';
|
||||
$suricata_dst_ip = NidsExport::getCustomIP($data['host']);
|
||||
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
|
||||
$tag = 'tag:session,600,seconds;';
|
||||
|
||||
if (!array_key_exists('path', $data)) {
|
||||
$data['path'] = NidsExport::replaceIllegalChars($data['host']);
|
||||
$content = 'flow:to_server,established; content:"' . $data['host'] . '"; nocase; http_header;';
|
||||
} else {
|
||||
$content = 'flow:to_server,established; content:"' . $data['host'] . '"; fast_pattern; nocase; http_header; content:"' . $data['path'] . '"; nocase; http_uri;';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "https":
|
||||
$data['host'] = NidsExport::replaceIllegalChars($data['host']);
|
||||
$tag = 'tag:session,600,seconds;';
|
||||
|
||||
# IP: classic IP rule for HTTPS
|
||||
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
|
||||
$suricata_protocol = 'tcp';
|
||||
$suricata_src_ip = '$HOME_NET';
|
||||
$suricata_src_port = 'any';
|
||||
$suricata_dst_ip = $data['host'];
|
||||
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
|
||||
$content = 'flow:to_server; app-layer-protocol:tls;';
|
||||
}
|
||||
# Domain: rule on https certificate subject
|
||||
else {
|
||||
$suricata_protocol = 'tls';
|
||||
$suricata_src_ip = '$EXTERNAL_NET';
|
||||
$suricata_src_port = NidsExport::getProtocolPort($scheme, $data['port']);
|
||||
$suricata_dst_ip = '$HOME_NET';
|
||||
$suricata_dst_port = 'any';
|
||||
$content = 'tls_cert_subject; content:"' . $data['host'] . '"; nocase; pcre:"/' . $data['host'] . '$/";';
|
||||
}
|
||||
break;
|
||||
|
||||
case "ssh":
|
||||
# IP: classic IP rule for SSH
|
||||
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
|
||||
$suricata_protocol = 'tcp';
|
||||
$suricata_src_ip = '$HOME_NET';
|
||||
$suricata_src_port = 'any';
|
||||
$suricata_dst_ip = $data['host'];
|
||||
$suricata_dst_port = '$SSH_PORTS';
|
||||
$content = 'flow:to_server; app-layer-protocol:ssh;';
|
||||
$tag = '';
|
||||
}
|
||||
# Cannot create a satisfaisant rule (user could create a domain attribute if needed)
|
||||
else {
|
||||
$createRule = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case "ftp":
|
||||
# IP: classic IP rule for FTP
|
||||
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
|
||||
$suricata_protocol = 'tcp';
|
||||
$suricata_src_ip = '$HOME_NET';
|
||||
$suricata_src_port = 'any';
|
||||
$suricata_dst_ip = $data['host'];
|
||||
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
|
||||
$content = 'flow:to_server; app-layer-protocol:ftp;';
|
||||
$tag = '';
|
||||
}
|
||||
# Cannot create a satisfaisant rule (user could create a domain attribute if needed)
|
||||
else {
|
||||
$createRule = false;
|
||||
}
|
||||
break;
|
||||
|
||||
# Unknown/No protocol: keep old behaviour
|
||||
default:
|
||||
$suricata_protocol = 'http';
|
||||
$suricata_src_ip = '$HOME_NET';
|
||||
$suricata_src_port = 'any';
|
||||
$suricata_dst_ip = '$EXTERNAL_NET';
|
||||
$suricata_dst_port = 'any';
|
||||
|
||||
$url = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
|
||||
$content = 'flow:to_server,established; content:"' . $url . '"; fast_pattern; nocase; http_uri;';
|
||||
$tag = 'tag:session,600,seconds;';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($createRule) {
|
||||
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
|
||||
$this->rules[] = sprintf($ruleFormat, ($overruled) ? '#OVERRULED BY WHITELIST# ' : '', $suricata_protocol, // proto
|
||||
$suricata_src_ip, // src_ip
|
||||
$suricata_src_port, // src_port
|
||||
'->', // direction
|
||||
$suricata_dst_ip, // dst_ip
|
||||
$suricata_dst_port, // dst_port
|
||||
'Outgoing URL: ' . $attribute['value'], // msg
|
||||
$content, // rule_content
|
||||
$tag, // tag
|
||||
$sid, // sid
|
||||
1 // rev
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function userAgentRule($ruleFormat, $attribute, &$sid) {
|
||||
$overruled = $this->checkWhitelist($attribute['value']);
|
||||
|
@ -132,4 +228,4 @@ class NidsSuricataExport extends NidsExport {
|
|||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ class ComplexTypeTool {
|
|||
'/^h\[tt\]p/i' => 'http',
|
||||
'/\[\.\]/' => '.',
|
||||
'/\[dot\]/' => '.',
|
||||
'/\(dot\)/' => '.',
|
||||
'/\\\\\./' => '.',
|
||||
'/\.+/' => '.'
|
||||
);
|
||||
|
@ -97,7 +98,7 @@ class ComplexTypeTool {
|
|||
* values: Expects an array (or a comma separated string) with numeric values denoting the columns containing indicators. If this is not set then every value will be checked. (column numbers start at 1)
|
||||
*/
|
||||
public function checkCSV($input, $settings = array()) {
|
||||
$delimiter = isset($settings['delimiter']) ? $settings['delimiter'] : ",";
|
||||
$delimiter = !empty($settings['delimiter']) ? $settings['delimiter'] : ",";
|
||||
$lines = explode("\n", $input);
|
||||
unset($input);
|
||||
$values = !empty($settings['value']) ? $settings['value'] : array();
|
||||
|
@ -203,17 +204,26 @@ class ComplexTypeTool {
|
|||
}
|
||||
$inputRefanged = rtrim($inputRefanged, ".");
|
||||
if (strpos($input, '@') !== false) {
|
||||
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
|
||||
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
|
||||
}
|
||||
// note down and remove the port if it's a url / domain name / hostname / ip
|
||||
// input2 from here on is the variable containing the original input with the port removed. It is only used by url / domain name / hostname / ip
|
||||
$comment = false;
|
||||
if (preg_match('/(:[0-9]{2,5})$/', $inputRefanged, $port)) {
|
||||
$comment = 'On port ' . substr($port[0], 1);
|
||||
$inputRefangedNoPort = str_replace($port[0], '', $inputRefanged);
|
||||
} else $inputRefangedNoPort = $inputRefanged;
|
||||
$port = substr($port[0], 1);
|
||||
} else {
|
||||
unset($port);
|
||||
$inputRefangedNoPort = $inputRefanged;
|
||||
}
|
||||
// check for IP
|
||||
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
|
||||
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) {
|
||||
if (isset($port)) {
|
||||
return array('types' => array('ip-dst|port', 'ip-src|port', 'ip-src|port/ip-dst|port'), 'to_ids' => true, 'default_type' => 'ip-dst|port', 'comment' => $comment, 'value' => $inputRefangedNoPort . '|' . $port);
|
||||
} else {
|
||||
return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
|
||||
}
|
||||
}
|
||||
if (strpos($inputRefangedNoPort, '/')) {
|
||||
$temp = explode('/', $inputRefangedNoPort);
|
||||
if (count($temp) == 2) {
|
||||
|
|
|
@ -39,6 +39,13 @@ class JSONConverterTool {
|
|||
$ra = array('Attribute' => $ra);
|
||||
}
|
||||
}
|
||||
if (isset($event['Event']['Attribute'][$key]['AttributeTag'])) {
|
||||
foreach ($event['Event']['Attribute'][$key]['AttributeTag'] as $atk => $tag) {
|
||||
unset($tag['Tag']['org_id']);
|
||||
$event['Event']['Attribute'][$key]['Tag'][$atk] = $tag['Tag'];
|
||||
}
|
||||
unset($event['Event']['Attribute'][$key]['AttributeTag']);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($event['Event']['RelatedAttribute']);
|
||||
|
|
|
@ -115,6 +115,13 @@ class XMLConverterTool {
|
|||
$event['Event']['Attribute'][$key]['SharingGroup'][0] = $event['Event']['Attribute'][$key]['SharingGroup'];
|
||||
unset($event['Event']['Attribute'][$key]['SharingGroup']);
|
||||
}
|
||||
if (isset($event['Event']['Attribute'][$key]['AttributeTag'])) {
|
||||
foreach ($event['Event']['Attribute'][$key]['AttributeTag'] as $atk => $tag) {
|
||||
unset($tag['Tag']['org_id']);
|
||||
$event['Event']['Attribute'][$key]['Tag'][$atk] = $tag['Tag'];
|
||||
}
|
||||
unset($event['Event']['Attribute'][$key]['AttributeTag']);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($event['Event']['RelatedAttribute']);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
App::uses('Model', 'Model');
|
||||
App::uses('LogableBehavior', 'Assets.models/behaviors');
|
||||
|
||||
class AppModel extends Model {
|
||||
|
||||
public $name;
|
||||
|
@ -41,7 +40,8 @@ class AppModel extends Model {
|
|||
32 => false, 33 => true, 38 => true, 39 => true, 40 => false,
|
||||
42 => false, 44 => false, 45 => false, 49 => true, 50 => false,
|
||||
51 => false, 52 => false, 55 => true, 56 => true, 57 => true,
|
||||
58 => false, 59 => false
|
||||
58 => false, 59 => false, 60 => false, 61 => false, 62 => false,
|
||||
63 => false, 64 => false, 65 => false
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -111,27 +111,30 @@ class AppModel extends Model {
|
|||
|
||||
// SQL scripts for updates
|
||||
public function updateDatabase($command) {
|
||||
$sql = '';
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$sqlArray = array();
|
||||
$indexArray = array();
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$clean = true;
|
||||
switch ($command) {
|
||||
case 'extendServerOrganizationLength':
|
||||
$sql = 'ALTER TABLE `servers` MODIFY COLUMN `organization` varchar(255) NOT NULL;';
|
||||
$sqlArray[] = 'ALTER TABLE `servers` MODIFY COLUMN `organization` varchar(255) NOT NULL;';
|
||||
break;
|
||||
case 'convertLogFieldsToText':
|
||||
$sql = 'ALTER TABLE `logs` MODIFY COLUMN `title` text, MODIFY COLUMN `change` text;';
|
||||
$sqlArray[] = 'ALTER TABLE `logs` MODIFY COLUMN `title` text, MODIFY COLUMN `change` text;';
|
||||
break;
|
||||
case 'addEventBlacklists':
|
||||
$sql = 'CREATE TABLE IF NOT EXISTS `event_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
|
||||
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `event_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
|
||||
break;
|
||||
case 'addOrgBlacklists':
|
||||
$sql = 'CREATE TABLE IF NOT EXISTS `org_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `org_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `org_name` varchar(255) COLLATE utf8_bin NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
|
||||
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `org_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `org_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `org_name` varchar(255) COLLATE utf8_bin NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
|
||||
break;
|
||||
case 'addEventBlacklistsContext':
|
||||
$sql = 'ALTER TABLE `event_blacklists` ADD `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , ADD `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, ADD `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;';
|
||||
$sqlArray[] = 'ALTER TABLE `event_blacklists` ADD `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , ADD `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, ADD `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;';
|
||||
break;
|
||||
case 'addSightings':
|
||||
$sql = "CREATE TABLE IF NOT EXISTS sightings (
|
||||
$sqlArray[] = "CREATE TABLE IF NOT EXISTS sightings (
|
||||
id int(11) NOT NULL AUTO_INCREMENT,
|
||||
attribute_id int(11) NOT NULL,
|
||||
event_id int(11) NOT NULL,
|
||||
|
@ -145,22 +148,22 @@ class AppModel extends Model {
|
|||
break;
|
||||
case 'makeAttributeUUIDsUnique':
|
||||
$this->__dropIndex('attributes', 'uuid');
|
||||
$sql = 'ALTER TABLE `attributes` ADD UNIQUE (uuid);';
|
||||
$sqlArray[] = 'ALTER TABLE `attributes` ADD UNIQUE (uuid);';
|
||||
break;
|
||||
case 'makeEventUUIDsUnique':
|
||||
$this->__dropIndex('events', 'uuid');
|
||||
$sql = 'ALTER TABLE `events` ADD UNIQUE (uuid);';
|
||||
$sqlArray[] = 'ALTER TABLE `events` ADD UNIQUE (uuid);';
|
||||
break;
|
||||
case 'cleanSessionTable':
|
||||
$sql = 'DELETE FROM cake_sessions WHERE expires < ' . time() . ';';
|
||||
$sqlArray[] = 'DELETE FROM cake_sessions WHERE expires < ' . time() . ';';
|
||||
$clean = false;
|
||||
break;
|
||||
case 'destroyAllSessions':
|
||||
$sql = 'DELETE FROM cake_sessions;';
|
||||
$sqlArray[] = 'DELETE FROM cake_sessions;';
|
||||
$clean = false;
|
||||
break;
|
||||
case 'addIPLogging':
|
||||
$sql = 'ALTER TABLE `logs` ADD `ip` varchar(45) COLLATE utf8_bin DEFAULT NULL;';
|
||||
$sqlArray[] = 'ALTER TABLE `logs` ADD `ip` varchar(45) COLLATE utf8_bin DEFAULT NULL;';
|
||||
break;
|
||||
case 'addCustomAuth':
|
||||
$sqlArray[] = "ALTER TABLE `users` ADD `external_auth_required` tinyint(1) NOT NULL DEFAULT 0;";
|
||||
|
@ -530,6 +533,74 @@ class AppModel extends Model {
|
|||
$sqlArray[] = "ALTER TABLE taxonomy_entries ADD colour varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '';";
|
||||
$sqlArray[] = "ALTER TABLE taxonomy_predicates ADD colour varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '';";
|
||||
break;
|
||||
case '2.4.60':
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `attribute_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`attribute_id` int(11) NOT NULL,
|
||||
`event_id` int(11) NOT NULL,
|
||||
`tag_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;';
|
||||
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `attribute_id` (`attribute_id`);';
|
||||
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `event_id` (`event_id`);';
|
||||
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `tag_id` (`tag_id`);';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS attribute_tags (
|
||||
id bigserial NOT NULL,
|
||||
attribute_id bigint NOT NULL,
|
||||
event_id bigint NOT NULL,
|
||||
tag_id bigint NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);';
|
||||
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_attribute_id ON attribute_tags (attribute_id);';
|
||||
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_event_id ON attribute_tags (event_id);';
|
||||
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_tag_id ON attribute_tags (tag_id);';
|
||||
}
|
||||
$this->__dropIndex('attribute_tags', 'attribute_id');
|
||||
$this->__dropIndex('attribute_tags', 'tag_id');
|
||||
break;
|
||||
case '2.4.61':
|
||||
$sqlArray[] = 'ALTER TABLE feeds ADD input_source varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "network";';
|
||||
$sqlArray[] = 'ALTER TABLE feeds ADD delete_local_file tinyint(1) DEFAULT 0;';
|
||||
$indexArray[] = array('feeds', 'input_source');
|
||||
break;
|
||||
case '2.4.62':
|
||||
$sqlArray[] = 'ALTER TABLE logs CHANGE `org` `org` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "";';
|
||||
$sqlArray[] = 'ALTER TABLE logs CHANGE `email` `email` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "";';
|
||||
$sqlArray[] = 'ALTER TABLE logs CHANGE `change` `change` text COLLATE utf8_bin NOT NULL DEFAULT "";';
|
||||
break;
|
||||
case '2.4.63':
|
||||
$sqlArray[] = 'ALTER TABLE events DROP COLUMN org;';
|
||||
$sqlArray[] = 'ALTER TABLE events DROP COLUMN orgc;';
|
||||
$sqlArray[] = 'ALTER TABLE event_blacklists CHANGE comment comment TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci;';
|
||||
break;
|
||||
case '2.4.64':
|
||||
$indexArray[] = array('feeds', 'input_source');
|
||||
$indexArray[] = array('attributes', 'value1', 255);
|
||||
$indexArray[] = array('attributes', 'value2', 255);
|
||||
$indexArray[] = array('attributes', 'type');
|
||||
$indexArray[] = array('galaxy_reference', 'galaxy_cluster_id');
|
||||
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_id');
|
||||
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_value', 255);
|
||||
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_type', 255);
|
||||
$indexArray[] = array('correlations', '1_event_id');
|
||||
$indexArray[] = array('warninglist_entries', 'warninglist_id');
|
||||
$indexArray[] = array('galaxy_clusters', 'value', 255);
|
||||
$indexArray[] = array('galaxy_clusters', 'tag_name');
|
||||
$indexArray[] = array('galaxy_clusters', 'uuid');
|
||||
$indexArray[] = array('galaxy_clusters', 'type');
|
||||
$indexArray[] = array('galaxies', 'name');
|
||||
$indexArray[] = array('galaxies', 'uuid');
|
||||
$indexArray[] = array('galaxies', 'type');
|
||||
break;
|
||||
case '2.4.65':
|
||||
$sqlArray[] = 'ALTER TABLE feeds CHANGE `enabled` `enabled` tinyint(1) DEFAULT 0;';
|
||||
$sqlArray[] = 'ALTER TABLE feeds CHANGE `default` `default` tinyint(1) DEFAULT 0;';
|
||||
$sqlArray[] = 'ALTER TABLE feeds CHANGE `distribution` `distribution` tinyint(4) NOT NULL DEFAULT 0;';
|
||||
$sqlArray[] = 'ALTER TABLE feeds CHANGE `sharing_group_id` `sharing_group_id` int(11) NOT NULL DEFAULT 0;';
|
||||
$sqlArray[] = 'ALTER TABLE attributes CHANGE `comment` `comment` text COLLATE utf8_bin;';
|
||||
break;
|
||||
case 'fixNonEmptySharingGroupID':
|
||||
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
|
@ -550,7 +621,6 @@ class AppModel extends Model {
|
|||
return false;
|
||||
break;
|
||||
}
|
||||
if (!isset($sqlArray)) $sqlArray = array($sql);
|
||||
foreach ($sqlArray as $sql) {
|
||||
try {
|
||||
$this->query($sql);
|
||||
|
@ -579,6 +649,13 @@ class AppModel extends Model {
|
|||
));
|
||||
}
|
||||
}
|
||||
foreach ($indexArray as $iA) {
|
||||
if (isset($iA[2])) {
|
||||
$this->__addIndex($iA[0], $iA[1], $iA[2]);
|
||||
} else {
|
||||
$this->__addIndex($iA[0], $iA[1]);
|
||||
}
|
||||
}
|
||||
if ($clean) $this->cleanCacheFiles();
|
||||
return true;
|
||||
}
|
||||
|
@ -628,16 +705,18 @@ class AppModel extends Model {
|
|||
if ($dataSource == 'Database/Postgres') {
|
||||
$addIndex = "CREATE INDEX idx_" . $table . "_" . $field . " ON " . $table . " (" . $field . ");";
|
||||
} else {
|
||||
if (isset($length)) {
|
||||
if (!$length) {
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`);";
|
||||
} else {
|
||||
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`(" . $length . "));";
|
||||
}
|
||||
}
|
||||
$result = true;
|
||||
$duplicate = false;
|
||||
try {
|
||||
$this->query($addIndex);
|
||||
} catch (Exception $e) {
|
||||
$duplicate = (strpos($e->getMessage(), '1061') !== false);
|
||||
$result = false;
|
||||
}
|
||||
$this->Log->create();
|
||||
|
@ -648,8 +727,8 @@ class AppModel extends Model {
|
|||
'email' => 'SYSTEM',
|
||||
'action' => 'update_database',
|
||||
'user_id' => 0,
|
||||
'title' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
|
||||
'change' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
|
||||
'title' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table . ($duplicate ? ' (index already set)' : ''),
|
||||
'change' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table . ($duplicate ? ' (index already set)' : ''),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -709,7 +788,16 @@ class AppModel extends Model {
|
|||
$requiresLogout = true;
|
||||
} else {
|
||||
$this->__runCleanDB();
|
||||
$db_version = $this->AdminSetting->find('first', array('conditions' => array('setting' => 'db_version')));
|
||||
$db_version = $this->AdminSetting->find('all', array('conditions' => array('setting' => 'db_version')));
|
||||
if (count($db_version) > 1) {
|
||||
// we ran into a bug where we have more than one db_version entry. This bug happened in some rare circumstances around 2.4.50-2.4.57
|
||||
foreach ($db_version as $k => $v) {
|
||||
if ($k > 0) {
|
||||
$this->AdminSetting->delete($v['AdminSetting']['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$db_version = $db_version[0];
|
||||
$updates = $this->__findUpgrades($db_version['AdminSetting']['value']);
|
||||
if (!empty($updates)) {
|
||||
foreach ($updates as $update => $temp) {
|
||||
|
|
|
@ -88,7 +88,7 @@ class Attribute extends AppModel {
|
|||
'hostname' => array('desc' => 'A full host/dnsname of an attacker', 'formdesc' => "A full host/dnsname of an attacker. Also set the IDS flag on when this hostname is hardcoded in malware", 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'domain' => array('desc' => 'A domain name used in the malware', 'formdesc' => "A domain name used in the malware. Use this instead of hostname when the upper domain is important or can be used to create links between events.", 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'domain|ip' => array('desc' => 'A domain name and its IP address (as found in DNS lookup) separated by a |','formdesc' => "A domain name and its IP address (as found in DNS lookup) separated by a | (no spaces)", 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'email-src' => array('desc' => "The email address (or domainname) used to send the malware.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
|
||||
'email-src' => array('desc' => "The email address used to send the malware.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
|
||||
'email-dst' => array('desc' => "A recipient email address", 'formdesc' => "A recipient email address that is not related to your constituency.", 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'email-subject' => array('desc' => "The subject of the email", 'default_category' => 'Payload delivery', 'to_ids' => 0),
|
||||
'email-attachment' => array('desc' => "File name of the email attachment.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
|
||||
|
@ -459,6 +459,12 @@ class Attribute extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
public $hasMany = array(
|
||||
'AttributeTag' => array(
|
||||
'dependent' => true
|
||||
)
|
||||
);
|
||||
|
||||
public $hashTypes = array(
|
||||
'md5' => array(
|
||||
'length' => 32,
|
||||
|
@ -1252,6 +1258,94 @@ class Attribute extends AppModel {
|
|||
}
|
||||
}
|
||||
|
||||
// using Alnitak's solution from http://stackoverflow.com/questions/594112/matching-an-ip-to-a-cidr-mask-in-php5
|
||||
private function __ipv4InCidr($ip, $cidr) {
|
||||
list ($subnet, $bits) = explode('/', $cidr);
|
||||
$ip = ip2long($ip);
|
||||
$subnet = ip2long($subnet);
|
||||
$mask = -1 << (32 - $bits);
|
||||
$subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
|
||||
return ($ip & $mask) == $subnet;
|
||||
}
|
||||
|
||||
// using Snifff's solution from http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet
|
||||
private function __ipv6InCidr($ip, $cidr) {
|
||||
$ip = inet_pton($ip);
|
||||
$binaryip = $this->__inet_to_bits($ip);
|
||||
list($net, $maskbits) = explode('/', $cidr);
|
||||
$net = inet_pton($net);
|
||||
$binarynet = $this->__inet_to_bits($net);
|
||||
$ip_net_bits = substr($binaryip, 0, $maskbits);
|
||||
$net_bits = substr($binarynet, 0, $maskbits);
|
||||
return ($ip_net_bits === $net_bits);
|
||||
}
|
||||
|
||||
private function __cidrCorrelation($a) {
|
||||
$ipValues = array();
|
||||
$ip = $a['type'] == 'domain-ip' ? $a['value2'] : $a['value1'];
|
||||
if (strpos($ip, '/') !== false) {
|
||||
$ip_array = explode('/', $ip);
|
||||
$ip_version = filter_var($ip_array[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 : 6;
|
||||
$ipList = $this->find('list', array(
|
||||
'conditions' => array(
|
||||
'type' => array('ip-src', 'ip-dst', 'domain_ip'),
|
||||
),
|
||||
'fields' => array('value1', 'value2'),
|
||||
'order' => false
|
||||
));
|
||||
$ipList = array_merge(array_keys($ipList), array_values($ipList));
|
||||
foreach ($ipList as $key => $value) {
|
||||
if ($value == '') {
|
||||
unset($ipList[$key]);
|
||||
}
|
||||
}
|
||||
foreach ($ipList as $ipToCheck) {
|
||||
if (filter_var($ipToCheck, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && $ip_version == 4) {
|
||||
if ($ip_version == 4) {
|
||||
if ($this->__ipv4InCidr($ipToCheck, $ip)) {
|
||||
$ipValues[] = $ipToCheck;
|
||||
}
|
||||
} else {
|
||||
if ($this->__ipv6InCidr($ipToCheck, $ip)) {
|
||||
$ipValues[] = $ipToCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ip = $a['value1'];
|
||||
$ip_version = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 : 6;
|
||||
$cidrList = $this->find('list', array(
|
||||
'conditions' => array(
|
||||
'type' => array('ip-src', 'ip-dst'),
|
||||
'value1 LIKE' => '%/%'
|
||||
),
|
||||
'fields' => array('value1'),
|
||||
'order' => false
|
||||
));
|
||||
foreach ($cidrList as $cidr) {
|
||||
$cidr_ip = explode('/', $cidr)[0];
|
||||
if (filter_var($cidr_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && $ip_version == 4) {
|
||||
if ($this->__ipv4InCidr($ip, $cidr)) {
|
||||
$ipValues[] = $cidr;
|
||||
}
|
||||
} else {
|
||||
if ($this->__ipv6InCidr($ip, $cidr)) {
|
||||
$ipValues[] = $cidr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($ipValues)) {
|
||||
$extraConditions = array('OR' => array(
|
||||
'Attribute.value1' => $ipValues,
|
||||
'Attribute.value2' => $ipValues
|
||||
));
|
||||
return $extraConditions;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __afterSaveCorrelation($a, $full = false, $event = false) {
|
||||
// Don't do any correlation if the type is a non correlating type
|
||||
if (!in_array($a['type'], $this->nonCorrelatingTypes)) {
|
||||
|
@ -1266,23 +1360,30 @@ class Attribute extends AppModel {
|
|||
if ($event['Event']['disable_correlation']) {
|
||||
return true;
|
||||
}
|
||||
if (Configure::read('MISP.enable_advanced_correlations') && in_array($a['type'], array('ip-src', 'ip-dst', 'domain-ip'))) {
|
||||
$extraConditions = $this->__cidrCorrelation($a);
|
||||
}
|
||||
$this->Correlation = ClassRegistry::init('Correlation');
|
||||
$correlatingValues = array($a['value1']);
|
||||
if (!empty($a['value2'])) $correlatingValues[] = $a['value2'];
|
||||
foreach ($correlatingValues as $k => $cV) {
|
||||
$correlatingAttributes[$k] = $this->find('all', array(
|
||||
'conditions' => array(
|
||||
'AND' => array(
|
||||
'OR' => array(
|
||||
'Attribute.value1' => $cV,
|
||||
'Attribute.value2' => $cV
|
||||
),
|
||||
'Attribute.type !=' => $this->nonCorrelatingTypes,
|
||||
'Attribute.disable_correlation' => 0,
|
||||
'Event.disable_correlation' => 0
|
||||
),
|
||||
'Attribute.deleted' => 0
|
||||
$conditions = array(
|
||||
'AND' => array(
|
||||
'OR' => array(
|
||||
'Attribute.value1' => $cV,
|
||||
'Attribute.value2' => $cV
|
||||
),
|
||||
'Attribute.type !=' => $this->nonCorrelatingTypes,
|
||||
'Attribute.disable_correlation' => 0,
|
||||
'Event.disable_correlation' => 0
|
||||
),
|
||||
'Attribute.deleted' => 0
|
||||
);
|
||||
if (!empty($extraConditions)) {
|
||||
$conditions['AND']['OR'][] = $extraConditions;
|
||||
}
|
||||
$correlatingAttributes[$k] = $this->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive => -1',
|
||||
'fields' => array('Attribute.event_id', 'Attribute.id', 'Attribute.distribution', 'Attribute.sharing_group_id', 'Attribute.deleted'),
|
||||
'contain' => array('Event' => array('fields' => array('Event.id', 'Event.date', 'Event.info', 'Event.org_id', 'Event.distribution', 'Event.sharing_group_id'))),
|
||||
|
@ -1492,10 +1593,13 @@ class Attribute extends AppModel {
|
|||
return $rules;
|
||||
}
|
||||
|
||||
public function text($user, $type, $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false) {
|
||||
//restricting to non-private or same org if the user is not a site-admin.
|
||||
public function text($user, $type, $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false, $allowNotPublished = false) {
|
||||
//permissions are taken care of in fetchAttributes()
|
||||
$conditions['AND'] = array();
|
||||
if ($allowNonIDS === false) $conditions['AND'] = array('Attribute.to_ids' => 1, 'Event.published' => 1);
|
||||
if ($allowNonIDS === false) {
|
||||
$conditions['AND']['Attribute.to_ids'] = 1;
|
||||
if ($allowNotPublished === false) $conditions['AND']['Event.published'] = 1;
|
||||
}
|
||||
if ($type !== 'all') $conditions['AND']['Attribute.type'] = $type;
|
||||
if ($from) $conditions['AND']['Event.date >='] = $from;
|
||||
if ($to) $conditions['AND']['Event.date <='] = $to;
|
||||
|
@ -1991,6 +2095,8 @@ class Attribute extends AppModel {
|
|||
),
|
||||
),
|
||||
);
|
||||
$params['contain']['AttributeTag'] = array('Tag' => array('conditions' => array()));
|
||||
if (empty($options['includeAllTags'])) $params['contain']['AttributeTag']['Tag']['conditions']['exportable'] = 1;
|
||||
if (isset($options['contain'])) $params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
|
||||
else $option['contain']['Event']['fields'] = array('id', 'info', 'org_id', 'orgc_id');
|
||||
if (Configure::read('MISP.proposals_block_attributes') && isset($options['conditions']['AND']['Attribute.to_ids']) && $options['conditions']['AND']['Attribute.to_ids'] == 1) {
|
||||
|
@ -2142,4 +2248,35 @@ class Attribute extends AppModel {
|
|||
}
|
||||
else return 'Could not save changes.';
|
||||
}
|
||||
|
||||
public function saveAndEncryptAttribute($attribute, $user) {
|
||||
$hashes = array('md5' => 'malware-sample', 'sha1' => 'filename|sha1', 'sha256' => 'filename|sha256');
|
||||
if ($attribute['encrypt']) {
|
||||
$result = $this->handleMaliciousBase64($attribute['event_id'], $attribute['value'], $attribute['data'], array_keys($hashes));
|
||||
if (!$result['success']) {
|
||||
return 'Could not handle the sample';
|
||||
}
|
||||
foreach ($hashes as $hash => $typeName) {
|
||||
if (!$result[$hash]) continue;
|
||||
$attributeToSave = array(
|
||||
'Attribute' => array(
|
||||
'value' => $attribute['value'] . '|' . $result[$hash],
|
||||
'category' => $attribute['category'],
|
||||
'type' => $typeName,
|
||||
'event_id' => $attribute['event_id'],
|
||||
'comment' => $attribute['comment'],
|
||||
'to_ids' => 1,
|
||||
'distribution' => $attribute['distribution'],
|
||||
'sharing_group_id' => isset($attribute['sharing_group_id']) ? $attribute['sharing_group_id'] : 0,
|
||||
)
|
||||
);
|
||||
if ($hash == 'md5') $attributeToSave['Attribute']['data'] = $result['data'];
|
||||
$this->create();
|
||||
if (!$this->save($attributeToSave)) {
|
||||
return $this->validationErrors;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
|
||||
class AttributeTag extends AppModel {
|
||||
|
||||
public $actsAs = array('Containable');
|
||||
|
||||
public $validate = array(
|
||||
'attribute_id' => array(
|
||||
'valueNotEmpty' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
),
|
||||
'tag_id' => array(
|
||||
'valueNotEmpty' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public $belongsTo = array(
|
||||
'Attribute' => array(
|
||||
'className' => 'Attribute',
|
||||
),
|
||||
'Tag' => array(
|
||||
'className' => 'Tag',
|
||||
),
|
||||
);
|
||||
|
||||
public function attachTagToAttribute($attribute_id, $event_id, $tag_id) {
|
||||
$existingAssociation = $this->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array(
|
||||
'tag_id' => $tag_id,
|
||||
'attribute_id' => $attribute_id
|
||||
)
|
||||
));
|
||||
if (empty($existingAssociation)) {
|
||||
$this->create();
|
||||
if (!$this->save(array('attribute_id' => $attribute_id, 'event_id' => $event_id, 'tag_id' => $tag_id))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -461,6 +461,38 @@ class Event extends AppModel {
|
|||
return $events;
|
||||
}
|
||||
|
||||
public function attachDiscussionsCountToEvents($user, $events) {
|
||||
$eventIds = Set::extract('/Event/id', $events);
|
||||
$this->Thread = ClassRegistry::init('Thread');
|
||||
$threads = $this->Thread->find('list', array(
|
||||
'conditions' => array('Thread.event_id' => $eventIds),
|
||||
'fields' => array('Thread.event_id', 'Thread.id')
|
||||
));
|
||||
$posts = $this->Thread->Post->find('all', array(
|
||||
'conditions' => array('Post.thread_id' => $threads),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Count(id) AS post_count', 'thread_id', 'max(date_modified) as last_post'),
|
||||
'group' => array('Post.thread_id')
|
||||
));
|
||||
$event_threads = array();
|
||||
foreach ($posts as $k => $v) {
|
||||
foreach ($threads as $k2 => $v2) {
|
||||
if ($v2 == $v['Post']['thread_id']) {
|
||||
$event_threads[$k2] = array(
|
||||
'post_count' => $v[0]['post_count'],
|
||||
'last_post' => strtotime($v[0]['last_post'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($events as $k => $v) {
|
||||
$events[$k]['Event']['post_count'] = !empty($event_threads[$events[$k]['Event']['id']]) ? $event_threads[$events[$k]['Event']['id']]['post_count'] : 0;
|
||||
$events[$k]['Event']['last_post'] = !empty($event_threads[$events[$k]['Event']['id']]) ? $event_threads[$events[$k]['Event']['id']]['last_post'] : 0;
|
||||
|
||||
}
|
||||
return $events;
|
||||
}
|
||||
|
||||
private function __buildEventConditionsCorrelation($user, $eventIds, $sgids) {
|
||||
if (!is_array($eventIds)) $eventIds = array($eventIds);
|
||||
if (!$user['Role']['perm_site_admin']) {
|
||||
|
@ -892,8 +924,14 @@ class Event extends AppModel {
|
|||
// cleanup the array from things we do not want to expose
|
||||
foreach (array('Org', 'org_id', 'orgc_id', 'proposal_email_lock', 'org', 'orgc') as $field) unset($event['Event'][$field]);
|
||||
foreach ($event['Event']['EventTag'] as $kt => $tag) {
|
||||
if (!$tag['Tag']['exportable']) unset($event['Event']['EventTag'][$kt]);
|
||||
if (!$tag['Tag']['exportable']) {
|
||||
unset($event['Event']['EventTag'][$kt]);
|
||||
} else {
|
||||
unset($tag['org_id']);
|
||||
$event['Event']['Tag'][] = $tag['Tag'];
|
||||
}
|
||||
}
|
||||
unset($event['Event']['EventTag']);
|
||||
|
||||
// Add the local server to the list of instances in the SG
|
||||
if (isset($event['Event']['SharingGroup']) && isset($event['Event']['SharingGroup']['SharingGroupServer'])) {
|
||||
|
@ -935,6 +973,16 @@ class Event extends AppModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
foreach ($attribute['AttributeTag'] as $kt => $tag) {
|
||||
if (!$tag['Tag']['exportable']) {
|
||||
unset($attribute['AttributeTag'][$kt]);
|
||||
} else {
|
||||
unset($tag['Tag']['org_id']);
|
||||
$attribute['Tag'][] = $tag['Tag'];
|
||||
}
|
||||
}
|
||||
unset($attribute['AttributeTag']);
|
||||
|
||||
|
||||
// remove value1 and value2 from the output
|
||||
unset($attribute['value1']);
|
||||
|
@ -1021,7 +1069,7 @@ class Event extends AppModel {
|
|||
}
|
||||
}
|
||||
|
||||
public function downloadEventFromServer($eventId, $server, $HttpSocket=null, $proposalDownload = false) {
|
||||
public function downloadEventFromServer($eventId, $server, $HttpSocket=null) {
|
||||
$url = $server['Server']['url'];
|
||||
$authkey = $server['Server']['authkey'];
|
||||
if (null == $HttpSocket) {
|
||||
|
@ -1040,18 +1088,12 @@ class Event extends AppModel {
|
|||
//'Connection' => 'keep-alive' // // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
|
||||
)
|
||||
);
|
||||
if (!$proposalDownload) {
|
||||
$uri = $url . '/events/view/' . $eventId . '/deleted:true';
|
||||
} else {
|
||||
$uri = $url . '/shadow_attributes/getProposalsByUuid/' . $eventId;
|
||||
}
|
||||
$uri = $url . '/events/view/' . $eventId . '/deleted:true';
|
||||
$response = $HttpSocket->get($uri, $data = '', $request);
|
||||
if ($response->isOk()) {
|
||||
return json_decode($response->body, true);
|
||||
} else {
|
||||
// TODO parse the XML response and keep the reason why it failed
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function downloadProposalsFromServer($uuidList, $server, $HttpSocket = null) {
|
||||
|
@ -1074,17 +1116,12 @@ class Event extends AppModel {
|
|||
$response = $HttpSocket->post($uri, json_encode($uuidList), $request);
|
||||
if ($response->isOk()) {
|
||||
return(json_decode($response->body, true));
|
||||
} else if ($response->code == '405') {
|
||||
// HACKY: without correct permission, the returning null causes Fallback for < 2.4.7 instances
|
||||
// which queries every event, for proposal, which it doesn't have permission for
|
||||
return array();
|
||||
} else {
|
||||
// TODO parse the XML response and keep the reason why it failed
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function fetchEventIds($user, $from = false, $to = false, $last = false, $list = false, $timestamp = false, $publish_timestamp = false) {
|
||||
public function fetchEventIds($user, $from = false, $to = false, $last = false, $list = false, $timestamp = false, $publish_timestamp = false, $eventIdList = false) {
|
||||
$conditions = array();
|
||||
// restricting to non-private or same org if the user is not a site-admin.
|
||||
if (!$user['Role']['perm_site_admin']) {
|
||||
|
@ -1115,6 +1152,7 @@ class Event extends AppModel {
|
|||
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
|
||||
if ($timestamp) $conditions['AND'][] = array('Event.timestamp >=' => $timestamp);
|
||||
if ($publish_timestamp) $conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp);
|
||||
if ($eventIdList) $conditions['AND'][] = array('Event.id' => $eventIdList);
|
||||
if ($list) {
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
|
@ -1215,7 +1253,6 @@ class Event extends AppModel {
|
|||
if ($options['to']) $conditions['AND'][] = array('Event.date <=' => $options['to']);
|
||||
if ($options['last']) $conditions['AND'][] = array('Event.publish_timestamp >=' => $options['last']);
|
||||
if ($options['event_uuid']) $conditions['AND'][] = array('Event.uuid' => $options['event_uuid']);
|
||||
|
||||
if (isset($options['deleted']) && $options['deleted']) {
|
||||
if (!$user['Role']['perm_sync']) {
|
||||
$conditionsAttributes['AND'][] = array(
|
||||
|
@ -1308,6 +1345,7 @@ class Event extends AppModel {
|
|||
unset($params['contain']['Attribute']);
|
||||
unset($params['contain']['ShadowAttribute']);
|
||||
}
|
||||
$params['contain']['Attribute']['AttributeTag'] = array('Tag' => array('conditions' => $tagConditions));
|
||||
if ($user['Role']['perm_site_admin']) {
|
||||
$params['contain']['User'] = array('fields' => 'email');
|
||||
}
|
||||
|
@ -1344,14 +1382,17 @@ class Event extends AppModel {
|
|||
foreach ($event['Galaxy'] as $k => $galaxy) {
|
||||
if ($galaxy['id'] == $cluster['GalaxyCluster']['Galaxy']['id']) {
|
||||
$found = true;
|
||||
unset($cluster['GalaxyCluster']['Galaxy']);
|
||||
$event['Galaxy'][$k]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
|
||||
$temp = $cluster;
|
||||
unset($temp['GalaxyCluster']['Galaxy']);
|
||||
$event['Galaxy'][$k]['GalaxyCluster'][] = $temp['GalaxyCluster'];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$event['Galaxy'][] = $cluster['GalaxyCluster']['Galaxy'];
|
||||
unset($cluster['GalaxyCluster']['Galaxy']);
|
||||
$event['Galaxy'][count($event['Galaxy']) - 1]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
|
||||
$temp = $cluster;
|
||||
unset($temp['GalaxyCluster']['Galaxy']);
|
||||
$event['Galaxy'][count($event['Galaxy']) - 1]['GalaxyCluster'][] = $temp['GalaxyCluster'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1395,14 +1436,24 @@ class Event extends AppModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
// unset empty attribute tags that got added because the tag wasn't exportable
|
||||
if (!empty($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $atk => $attributeTag) {
|
||||
if (empty($attributeTag['Tag'])) unset($event['Attribute'][$key]['AttributeTag'][$atk]);
|
||||
}
|
||||
$event['Attribute'][$key]['AttributeTag'] = array_values($event['Attribute'][$key]['AttributeTag']);
|
||||
}
|
||||
$event['Attribute'][$key]['ShadowAttribute'] = array();
|
||||
// If a shadowattribute can be linked to an attribute, link it to it then remove it from the event
|
||||
// This is to differentiate between proposals that were made to an attribute for modification and between proposals for new attributes
|
||||
foreach ($event['ShadowAttribute'] as $k => $sa) {
|
||||
if (!empty($sa['old_id'])) {
|
||||
if ($event['ShadowAttribute'][$k]['old_id'] == $attribute['id']) {
|
||||
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
|
||||
unset($results[$eventKey]['ShadowAttribute'][$k]);
|
||||
|
||||
if (isset($event['ShadowAttribute'])) {
|
||||
foreach ($event['ShadowAttribute'] as $k => $sa) {
|
||||
if (!empty($sa['old_id'])) {
|
||||
if ($event['ShadowAttribute'][$k]['old_id'] == $attribute['id']) {
|
||||
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
|
||||
unset($results[$eventKey]['ShadowAttribute'][$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1429,6 +1480,10 @@ class Event extends AppModel {
|
|||
}
|
||||
$event['ShadowAttribute'] = array_values($event['ShadowAttribute']);
|
||||
}
|
||||
if ($event['Event']['orgc_id'] === $user['org_id'] && $user['Role']['perm_audit']) {
|
||||
$UserEmail = $this->User->getAuthUser($event['Event']['user_id'])['email'];
|
||||
$event['Event']['event_creator_email'] = $UserEmail;
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
@ -1679,17 +1734,17 @@ class Event extends AppModel {
|
|||
$body .= 'Tags: ' . $tags . "\n";
|
||||
$body .= 'Threat Level: ' . $event['ThreatLevel']['name'] . "\n";
|
||||
$body .= 'Analysis : ' . $this->analysisLevels[$event['Event']['analysis']] . "\n";
|
||||
$body .= 'Description : ' . $event['Event']['info'] . "\n\n";
|
||||
$body .= 'Description : ' . $event['Event']['info'] . "\n";
|
||||
$relatedEvents = $this->getRelatedEvents($user, $event['Event']['id'], array());
|
||||
if (!empty($relatedEvents)) {
|
||||
$body .= '==============================================' . "\n";
|
||||
$body .= 'Related to : '. "\n";
|
||||
$body .= 'Related to: '. "\n";
|
||||
foreach ($relatedEvents as &$relatedEvent) {
|
||||
$body .= Configure::read('MISP.baseurl') . '/events/view/' . $relatedEvent['Event']['id'] . ' (' . $relatedEvent['Event']['date'] . ') ' ."\n";
|
||||
}
|
||||
$body .= '==============================================' . "\n";
|
||||
}
|
||||
$body .= 'Attributes (* indicates a new or modified attribute) :' . "\n";
|
||||
$body .= 'Attributes (* indicates a new or modified attribute):' . "\n";
|
||||
$bodyTempOther = "";
|
||||
if (isset($event['Attribute'])) {
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
|
@ -1700,9 +1755,9 @@ class Event extends AppModel {
|
|||
$strRepeatCount = $appendlen - 2 - strlen($attribute['type']);
|
||||
$strRepeat = ($strRepeatCount > 0) ? str_repeat(' ', $strRepeatCount) : '';
|
||||
if (isset($oldpublish) && isset($attribute['timestamp']) && $attribute['timestamp'] > $oldpublish) {
|
||||
$line = '* ' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . " *\n";
|
||||
$line = '* ' . $attribute['category'] . '/' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . " *\n";
|
||||
} else {
|
||||
$line = $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . "\n";
|
||||
$line = $attribute['category'] . '/' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . "\n";
|
||||
}
|
||||
// Defanging URLs (Not "links") emails domains/ips in notification emails
|
||||
if ('url' == $attribute['type']) {
|
||||
|
@ -1714,7 +1769,16 @@ class Event extends AppModel {
|
|||
else if ('hostname' == $attribute['type'] or 'domain' == $attribute['type'] or 'ip-src' == $attribute['type'] or 'ip-dst' == $attribute['type']) {
|
||||
$line = str_replace(".","[.]", $line);
|
||||
}
|
||||
|
||||
if (!empty($attribute['AttributeTag'])) {
|
||||
$line .= ' - Tags: ';
|
||||
foreach ($attribute['AttributeTag'] as $k => $aT) {
|
||||
if ($k > 0) {
|
||||
$line .= ', ';
|
||||
}
|
||||
$line .= $aT['Tag']['name'];
|
||||
}
|
||||
$line .= "\n";
|
||||
}
|
||||
if ('other' == $attribute['type']) // append the 'other' attribute types to the bottom.
|
||||
$bodyTempOther .= $line;
|
||||
else $body .= $line;
|
||||
|
@ -1854,7 +1918,7 @@ class Event extends AppModel {
|
|||
unset($data['Event']['SharingGroup']);
|
||||
}
|
||||
if (isset($data['Event']['Attribute'])) {
|
||||
foreach ($data['Event']['Attribute'] as $k => &$a) {
|
||||
foreach ($data['Event']['Attribute'] as $k => $a) {
|
||||
unset($data['Event']['Attribute']['id']);
|
||||
if (isset($a['distribution']) && $a['distribution'] == 4) {
|
||||
$data['Event']['Attribute'][$k]['sharing_group_id'] = $this->SharingGroup->captureSG($data['Event']['Attribute'][$k]['SharingGroup'], $user);
|
||||
|
@ -1893,6 +1957,30 @@ class Event extends AppModel {
|
|||
}
|
||||
unset($data['Event']['Tag']);
|
||||
}
|
||||
|
||||
if (isset($data['Event']['Attribute'])) {
|
||||
foreach ($data['Event']['Attribute'] as $k => $a) {
|
||||
if (isset($data['Event']['Attribute'][$k]['AttributeTag'])) {
|
||||
if (isset($data['Event']['Attribute'][$k]['AttributeTag']['id'])) $data['Event']['Attribute'][$k]['AttributeTag'] = array($data['Event']['Attribute'][$k]['AttributeTag']);
|
||||
$attributeTags = array();
|
||||
foreach ($data['Event']['Attribute'][$k]['AttributeTag'] as $tk => $tag) {
|
||||
$attributeTags[] = array('tag_id' => $this->Attribute->AttributeTag->Tag->captureTag($data['Event']['Attribute'][$k]['AttributeTag'][$tk]['Tag'], $user));
|
||||
unset($data['Event']['Attribute'][$k]['AttributeTag'][$tk]);
|
||||
}
|
||||
$data['Event']['Attribute'][$k]['AttributeTag'] = $attributeTags;
|
||||
} else {
|
||||
$data['Event']['Attribute'][$k]['AttributeTag'] = array();
|
||||
}
|
||||
if (isset($data['Event']['Attribute'][$k]['Tag'])) {
|
||||
if (isset($data['Event']['Attribute'][$k]['Tag']['name'])) $data['Event']['Attribute'][$k]['Tag'] = array($data['Event']['Attribute'][$k]['Tag']);
|
||||
foreach ($data['Event']['Attribute'][$k]['Tag'] as $tag) {
|
||||
$tag_id = $this->Attribute->AttributeTag->Tag->captureTag($tag, $user);
|
||||
if ($tag_id) $data['Event']['Attribute'][$k]['AttributeTag'][] = array('tag_id' => $tag_id);
|
||||
}
|
||||
unset($data['Event']['Attribute'][$k]['Tag']);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
@ -1992,21 +2080,58 @@ class Event extends AppModel {
|
|||
foreach ($data['Event']['Attribute'] as $k => &$attribute) {
|
||||
$attribute['event_id'] = $this->id;
|
||||
unset($attribute['id']);
|
||||
$this->Attribute->create();
|
||||
if (!$this->Attribute->save($attribute, array('fieldList' => $fieldList['Attribute']))) {
|
||||
$validationErrors['Attribute'][$k] = $this->Attribute->validationErrors;
|
||||
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'add',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
|
||||
'change' => json_encode($this->Attribute->validationErrors),
|
||||
));
|
||||
if (isset($attribute['encrypt'])) {
|
||||
$saveResult = $this->Attribute->saveAndEncryptAttribute($attribute, $user);
|
||||
if ($saveResult !== true) {
|
||||
$validationErrors['Attribute'][$k] = $saveResult;
|
||||
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'add',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
|
||||
'change' => json_encode($saveResult ? $saveResult : array()),
|
||||
));
|
||||
} else {
|
||||
if (isset($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $at) {
|
||||
$this->Attribute->AttributeTag->create();
|
||||
$at['attribute_id'] = $this->Attribute->id;
|
||||
$at['event_id'] = $this->id;
|
||||
$this->Attribute->AttributeTag->save($at);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Attribute->create();
|
||||
if (!$this->Attribute->save($attribute, array('fieldList' => $fieldList['Attribute']))) {
|
||||
$validationErrors['Attribute'][$k] = $this->Attribute->validationErrors;
|
||||
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'add',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
|
||||
'change' => json_encode($this->Attribute->validationErrors),
|
||||
));
|
||||
} else {
|
||||
if (isset($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $at) {
|
||||
$this->Attribute->AttributeTag->create();
|
||||
$at['attribute_id'] = $this->Attribute->id;
|
||||
$at['event_id'] = $this->id;
|
||||
$this->Attribute->AttributeTag->save($at);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2082,8 +2207,8 @@ class Event extends AppModel {
|
|||
if (isset($data['Event']['published']) && $data['Event']['published'] && !$user['Role']['perm_publish']) $data['Event']['published'] = 0;
|
||||
if (!isset($data['Event']['published'])) $data['Event']['published'] = 0;
|
||||
$fieldList = array(
|
||||
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'distribution', 'timestamp', 'sharing_group_id'),
|
||||
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp', 'comment', 'sharing_group_id', 'deleted')
|
||||
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'distribution', 'timestamp', 'sharing_group_id', 'disable_correlation'),
|
||||
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp', 'comment', 'sharing_group_id', 'deleted', 'disable_correlation')
|
||||
);
|
||||
$saveResult = $this->save(array('Event' => $data['Event']), array('fieldList' => $fieldList['Event']));
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
|
@ -2091,43 +2216,79 @@ class Event extends AppModel {
|
|||
$validationErrors = array();
|
||||
if (isset($data['Event']['Attribute'])) {
|
||||
foreach ($data['Event']['Attribute'] as $k => $attribute) {
|
||||
if (isset($attribute['uuid'])) {
|
||||
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
|
||||
if (count($existingAttribute)) {
|
||||
if ($existingAttribute['Attribute']['event_id'] != $id) {
|
||||
$result = $this->Log->save(array(
|
||||
$attribute['event_id'] = $existingEvent['Event']['id'];
|
||||
if (isset($attribute['encrypt'])) {
|
||||
if (isset($attribute['uuid'])) {
|
||||
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
|
||||
if (!empty($existingAttribute)) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Event',
|
||||
'model_id' => $id,
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'edit',
|
||||
'action' => 'add',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Duplicate UUID found in attribute',
|
||||
'change' => 'An attribute was blocked from being saved due to a duplicate UUID. The uuid in question is: ' . $attribute['uuid'],
|
||||
'title' => 'Attribute dropped because the encrypt parameter was passed along an attribute that already exists',
|
||||
'change' => '',
|
||||
));
|
||||
unset($data['Event']['Attribute'][$k]);
|
||||
} else {
|
||||
// If a field is not set in the request, just reuse the old value
|
||||
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment', 'sharing_group_id');
|
||||
foreach ($recoverFields as $rF) if (!isset($attribute[$rF])) $data['Event']['Attribute'][$k][$rF] = $existingAttribute['Attribute'][$rF];
|
||||
$data['Event']['Attribute'][$k]['id'] = $existingAttribute['Attribute']['id'];
|
||||
// Check if the attribute's timestamp is bigger than the one that already exists.
|
||||
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
|
||||
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
|
||||
if (isset($data['Event']['Attribute'][$k]['timestamp'])) {
|
||||
if ($data['Event']['Attribute'][$k]['timestamp'] <= $existingAttribute['Attribute']['timestamp']) {
|
||||
unset($data['Event']['Attribute'][$k]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$saveResult = $this->Attribute->saveAndEncryptAttribute($attribute, $user);
|
||||
if ($saveResult !== true) {
|
||||
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'add',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Attribute dropped due to validation for Event ' . $id . ' failed: ' . $attribute_short,
|
||||
'change' => json_encode($saveResult ? $saveResult : array()),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (isset($attribute['uuid'])) {
|
||||
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
|
||||
if (count($existingAttribute)) {
|
||||
if ($existingAttribute['Attribute']['event_id'] != $id) {
|
||||
$result = $this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attribute',
|
||||
'model_id' => 0,
|
||||
'email' => $user['email'],
|
||||
'action' => 'edit',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Duplicate UUID found in attribute',
|
||||
'change' => 'An attribute was blocked from being saved due to a duplicate UUID. The uuid in question is: ' . $attribute['uuid'],
|
||||
));
|
||||
unset($data['Event']['Attribute'][$k]);
|
||||
} else {
|
||||
$data['Event']['Attribute'][$k]['timestamp'] = $date;
|
||||
// If a field is not set in the request, just reuse the old value
|
||||
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment', 'sharing_group_id');
|
||||
foreach ($recoverFields as $rF) if (!isset($attribute[$rF])) $data['Event']['Attribute'][$k][$rF] = $existingAttribute['Attribute'][$rF];
|
||||
$data['Event']['Attribute'][$k]['id'] = $existingAttribute['Attribute']['id'];
|
||||
// Check if the attribute's timestamp is bigger than the one that already exists.
|
||||
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
|
||||
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
|
||||
if (isset($data['Event']['Attribute'][$k]['timestamp'])) {
|
||||
if ($data['Event']['Attribute'][$k]['timestamp'] <= $existingAttribute['Attribute']['timestamp']) {
|
||||
unset($data['Event']['Attribute'][$k]);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$data['Event']['Attribute'][$k]['timestamp'] = $date;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Attribute->create();
|
||||
}
|
||||
} else {
|
||||
$this->Attribute->create();
|
||||
}
|
||||
} else {
|
||||
$this->Attribute->create();
|
||||
}
|
||||
$data['Event']['Attribute'][$k]['event_id'] = $this->id;
|
||||
if ($data['Event']['Attribute'][$k]['distribution'] == 4) {
|
||||
|
@ -2147,12 +2308,42 @@ class Event extends AppModel {
|
|||
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
|
||||
'change' => json_encode($this->Attribute->validationErrors),
|
||||
));
|
||||
} else {
|
||||
if (isset($data['Event']['Attribute'][$k]['Tag']) && $user['Role']['perm_tagger']) {
|
||||
foreach ($data['Event']['Attribute'][$k]['Tag'] as $tag) {
|
||||
$tag_id = $this->Attribute->AttributeTag->Tag->captureTag($tag, $user);
|
||||
if ($tag_id) {
|
||||
$this->Attribute->AttributeTag->attachTagToAttribute($this->Attribute->id, $this->id, $tag_id);
|
||||
} else {
|
||||
// If we couldn't attach the tag it is most likely because we couldn't create it - which could have many reasons
|
||||
// However, if a tag couldn't be added, it could also be that the user is a tagger but not a tag editor
|
||||
// In which case if no matching tag is found, no tag ID is returned. Logging these is pointless as it is the correct behaviour.
|
||||
if ($user['Role']['perm_tag_editor']) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Attrubute',
|
||||
'model_id' => $this->Attribute->id,
|
||||
'email' => $user['email'],
|
||||
'action' => 'edit',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Failed create or attach Tag ' . $tag['name'] . ' to the attribute.',
|
||||
'change' => ''
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($data['Event']['EventTag']) && $user['Role']['perm_tagger']) {
|
||||
foreach ($data['Event']['EventTag'] as $tag) {
|
||||
$tag_id = $this->EventTag->Tag->captureTag($tag['Tag'], $user);
|
||||
if (isset($event['Event']['EventTag'])) {
|
||||
$event['Event']['Tag'] = $event['Event']['EventTag']['Tag'];
|
||||
unset($event['Event']['EventTag']);
|
||||
}
|
||||
if (isset($data['Event']['Tag']) && $user['Role']['perm_tagger']) {
|
||||
foreach ($data['Event']['Tag'] as $tag) {
|
||||
$tag_id = $this->EventTag->Tag->captureTag($tag, $user);
|
||||
if ($tag_id) {
|
||||
$this->EventTag->attachTagToEvent($this->id, $tag_id);
|
||||
} else {
|
||||
|
@ -2270,7 +2461,8 @@ class Event extends AppModel {
|
|||
'fields' => array('id', 'url', 'name')
|
||||
)
|
||||
),
|
||||
)
|
||||
),
|
||||
'AttributeTag' => array('Tag')
|
||||
),
|
||||
'EventTag' => array('Tag'),
|
||||
'Org' => array('fields' => array('id', 'uuid', 'name', 'local')),
|
||||
|
|
|
@ -63,7 +63,7 @@ class EventTag extends AppModel {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function getSortedTagList($context = false) {
|
||||
$conditions = array();
|
||||
$tag_counts = $this->find('all', array(
|
||||
|
|
|
@ -23,8 +23,8 @@ class Feed extends AppModel {
|
|||
|
||||
public $validate = array(
|
||||
'url' => array( // TODO add extra validation to refuse multiple time the same url from the same org
|
||||
'rule' => array('url'),
|
||||
'message' => 'Please enter a valid url.',
|
||||
'rule' => array('urlOrExistingFilepath'),
|
||||
'message' => 'Please enter a valid url or file path (make sure that the choice matches the input source setting).',
|
||||
),
|
||||
'provider' => 'valueNotEmpty',
|
||||
'name' => 'valueNotEmpty',
|
||||
|
@ -47,6 +47,26 @@ class Feed extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
public function urlOrExistingFilepath($fields) {
|
||||
$input_source = empty($this->data['Feed']['input_source']) ? 'network' : $this->data['Feed']['input_source'];
|
||||
if ($input_source == 'local') {
|
||||
if ($this->data['Feed']['source_format'] == 'misp') {
|
||||
if (!is_dir($this->data['Feed']['url'])) {
|
||||
return 'For MISP type local feeds, please specify the containing directory.';
|
||||
}
|
||||
} else {
|
||||
if (!file_exists($this->data['Feed']['url'])) {
|
||||
return 'For non-MISP type local feeds, please specify the file to be ingested.';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!filter_var($this->data['Feed']['url'], FILTER_VALIDATE_URL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFeedTypesOptions() {
|
||||
$result = array();
|
||||
foreach ($this->feed_types as $key => $value) {
|
||||
|
@ -59,11 +79,19 @@ class Feed extends AppModel {
|
|||
// returns an array with the UUIDs of events that are new or that need updating
|
||||
public function getNewEventUuids($feed, $HttpSocket) {
|
||||
$result = array();
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/manifest.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) return 1;
|
||||
$manifest = json_decode($response->body, true);
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($feed['Feed']['url'] . '/manifest.json')) {
|
||||
$data = file_get_contents($feed['Feed']['url'] . '/manifest.json');
|
||||
}
|
||||
} else {
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/manifest.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) return 1;
|
||||
$data = $response->body;
|
||||
unset($response);
|
||||
}
|
||||
$manifest = json_decode($data, true);
|
||||
if (!$manifest) return 2;
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$events = $this->Event->find('all', array(
|
||||
|
@ -74,10 +102,16 @@ class Feed extends AppModel {
|
|||
'fields' => array('Event.id', 'Event.uuid', 'Event.timestamp')
|
||||
));
|
||||
foreach ($events as $event) {
|
||||
if ($event['Event']['timestamp'] < $manifest[$event['Event']['uuid']]['timestamp']) $result['edit'][] = array('uuid' => $event['Event']['uuid'], 'id' => $event['Event']['id']);
|
||||
if ($event['Event']['timestamp'] < $manifest[$event['Event']['uuid']]['timestamp']) {
|
||||
$result['edit'][] = array('uuid' => $event['Event']['uuid'], 'id' => $event['Event']['id']);
|
||||
} else {
|
||||
$this->__cleanupFile($feed, '/' . $event['Event']['uuid'] . '.json');
|
||||
}
|
||||
unset($manifest[$event['Event']['uuid']]);
|
||||
}
|
||||
$result['add'] = array_keys($manifest);
|
||||
if (!empty($manifest)) {
|
||||
$result['add'] = array_keys($manifest);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -85,10 +119,21 @@ class Feed extends AppModel {
|
|||
public function getManifest($feed, $HttpSocket) {
|
||||
$result = array();
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/manifest.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($feed['Feed']['url'] . '/manifest.json')) {
|
||||
$data = file_get_contents($feed['Feed']['url'] . '/manifest.json');
|
||||
}
|
||||
} else {
|
||||
$uri = $feed['Feed']['url'] . '/manifest.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) {
|
||||
return false;
|
||||
}
|
||||
$data = $response->body;
|
||||
unset($response);
|
||||
}
|
||||
try {
|
||||
$events = json_decode($response->body, true);
|
||||
$events = json_decode($data, true);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
@ -98,20 +143,26 @@ class Feed extends AppModel {
|
|||
|
||||
public function getFreetextFeed($feed, $HttpSocket, $type = 'freetext', $page = 1, $limit = 60, &$params = array()) {
|
||||
$result = array();
|
||||
$feedCache = APP . 'tmp' . DS . 'cache' . DS . 'misp_feed_' . intval($feed['Feed']['id']) . '.cache';
|
||||
$doFetch = true;
|
||||
if (file_exists($feedCache)) {
|
||||
$file = new File($feedCache);
|
||||
if (time() - $file->lastChange() < 600) {
|
||||
$doFetch = false;
|
||||
$data = file_get_contents($feedCache);
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($feed['Feed']['url'])) {
|
||||
$data = file_get_contents($feed['Feed']['url']);
|
||||
}
|
||||
}
|
||||
if ($doFetch) {
|
||||
$response = $HttpSocket->get($feed['Feed']['url'], '', array());
|
||||
if ($response->code == 200) {
|
||||
$data = $response->body;
|
||||
file_put_contents($feedCache, $data);
|
||||
} else {
|
||||
$feedCache = APP . 'tmp' . DS . 'cache' . DS . 'misp_feed_' . intval($feed['Feed']['id']) . '.cache';
|
||||
$doFetch = true;
|
||||
if (file_exists($feedCache)) {
|
||||
$file = new File($feedCache);
|
||||
if (time() - $file->lastChange() < 600) {
|
||||
$doFetch = false;
|
||||
$data = file_get_contents($feedCache);
|
||||
}
|
||||
}
|
||||
if ($doFetch) {
|
||||
$response = $HttpSocket->get($feed['Feed']['url'], '', array());
|
||||
if ($response->code == 200) {
|
||||
$data = $response->body;
|
||||
file_put_contents($feedCache, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
App::uses('ComplexTypeTool', 'Tools');
|
||||
|
@ -182,6 +233,7 @@ class Feed extends AppModel {
|
|||
if (isset($actions['add']) && !empty($actions['add'])) {
|
||||
foreach ($actions['add'] as $uuid) {
|
||||
$result = $this->__addEventFromFeed($HttpSocket, $feed, $uuid, $user, $filterRules);
|
||||
$this->__cleanupFile($feed, '/' . $uuid . '.json');
|
||||
if ($result === 'blocked') continue;
|
||||
if ($result === true) {
|
||||
$results['add']['success'] = $uuid;
|
||||
|
@ -198,6 +250,7 @@ class Feed extends AppModel {
|
|||
if (isset($actions['edit']) && !empty($actions['edit'])) {
|
||||
foreach ($actions['edit'] as $editTarget) {
|
||||
$result = $this->__updateEventFromFeed($HttpSocket, $feed, $editTarget['uuid'], $editTarget['id'], $user, $filterRules);
|
||||
$this->__cleanupFile($feed, '/' . $uuid . '.json');
|
||||
if ($result === 'blocked') continue;
|
||||
if ($result === true) {
|
||||
$results['edit']['success'] = $uuid;
|
||||
|
@ -309,15 +362,22 @@ class Feed extends AppModel {
|
|||
}
|
||||
|
||||
public function downloadEventFromFeed($feed, $uuid, $user) {
|
||||
$HttpSocket = $this->__setupHttpSocket($feed);
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) {
|
||||
return false;
|
||||
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($path)) {
|
||||
$data = file_get_contents($path);
|
||||
}
|
||||
} else {
|
||||
return $this->__prepareEvent($response->body, $feed);
|
||||
$HttpSocket = $this->__setupHttpSocket($feed);
|
||||
$request = $this->__createFeedRequest();
|
||||
$response = $HttpSocket->get($path, '', $request);
|
||||
if ($response->code != 200) {
|
||||
return false;
|
||||
}
|
||||
$data = $response->body;
|
||||
unset($response->body);
|
||||
}
|
||||
return $this->__prepareEvent($data, $feed);
|
||||
}
|
||||
|
||||
private function __saveEvent($event, $user) {
|
||||
|
@ -348,7 +408,9 @@ class Feed extends AppModel {
|
|||
if (!isset($event['Event']['uuid'])) return false;
|
||||
$event['Event']['distribution'] = $feed['Feed']['distribution'];
|
||||
$event['Event']['sharing_group_id'] = $feed['Feed']['sharing_group_id'];
|
||||
foreach ($event['Event']['Attribute'] as $key => $attribute) $event['Event']['Attribute'][$key]['distribution'] = 5;
|
||||
if (!empty($event['Event']['Attribute'])) {
|
||||
foreach ($event['Event']['Attribute'] as $key => $attribute) $event['Event']['Attribute'][$key]['distribution'] = 5;
|
||||
}
|
||||
if ($feed['Feed']['tag_id']) {
|
||||
if (!isset($event['Event']['Tag'])) $event['Event']['Tag'] = array();
|
||||
$found = false;
|
||||
|
@ -392,31 +454,49 @@ class Feed extends AppModel {
|
|||
}
|
||||
|
||||
private function __addEventFromFeed($HttpSocket, $feed, $uuid, $user, $filterRules) {
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) {
|
||||
if (!Validation::uuid($uuid)) {
|
||||
return false;
|
||||
} else {
|
||||
$event = $this->__prepareEvent($response->body, $feed);
|
||||
if (is_array($event)) {
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
return $this->Event->_add($event, true, $user);
|
||||
} else return $event;
|
||||
}
|
||||
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($path)) {
|
||||
$data = file_get_contents($path);
|
||||
}
|
||||
} else {
|
||||
$request = $this->__createFeedRequest();
|
||||
$response = $HttpSocket->get($path, '', $request);
|
||||
if ($response->code != 200) {
|
||||
return false;
|
||||
}
|
||||
$data = $response->body;
|
||||
unset($response);
|
||||
}
|
||||
$event = $this->__prepareEvent($data, $feed);
|
||||
if (is_array($event)) {
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
return $this->Event->_add($event, true, $user);
|
||||
} else return $event;
|
||||
}
|
||||
|
||||
private function __updateEventFromFeed($HttpSocket, $feed, $uuid, $eventId, $user, $filterRules) {
|
||||
$request = $this->__createFeedRequest();
|
||||
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
if ($response->code != 200) {
|
||||
if (!Validation::uuid($uuid)) {
|
||||
return false;
|
||||
} else {
|
||||
$event = $this->__prepareEvent($response->body, $feed);
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
return $this->Event->_edit($event, $user, $uuid, $jobId = null);
|
||||
}
|
||||
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (file_exists($path)) {
|
||||
$data = file_get_contents($path);
|
||||
}
|
||||
} else {
|
||||
$request = $this->__createFeedRequest();
|
||||
$response = $HttpSocket->get($path, '', $request);
|
||||
if ($response->code != 200) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$event = $this->__prepareEvent($response->body, $feed);
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
return $this->Event->_edit($event, $user, $uuid, $jobId = null);
|
||||
}
|
||||
|
||||
public function addDefaultFeeds($newFeeds) {
|
||||
|
@ -450,7 +530,11 @@ class Feed extends AppModel {
|
|||
if (isset($this->data['Feed']['settings']) && !empty($this->data['Feed']['settings'])) {
|
||||
$this->data['Feed']['settings'] = json_decode($this->data['Feed']['settings'], true);
|
||||
}
|
||||
$HttpSocket = $syncTool->setupHttpSocketFeed($this->data);
|
||||
if (isset($this->data['Feed']['input_source']) && $this->data['Feed']['input_source'] == 'local') {
|
||||
$HttpSocket = false;
|
||||
} else {
|
||||
$HttpSocket = $syncTool->setupHttpSocketFeed($this->data);
|
||||
}
|
||||
if ($this->data['Feed']['source_format'] == 'misp') {
|
||||
if ($jobId) {
|
||||
$job->id = $jobId;
|
||||
|
@ -461,7 +545,15 @@ class Feed extends AppModel {
|
|||
$job->id = $jobId;
|
||||
$job->saveField('message', 'Fetching events.');
|
||||
}
|
||||
if (empty($actions)) {
|
||||
if ($jobId) {
|
||||
$job->id = $jobId;
|
||||
$job->saveField('message', 'Job complete.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
$result = $this->downloadFromFeed($actions, $this->data, $HttpSocket, $user, $jobId);
|
||||
$this->__cleanupFile($feed, '/manifest.json');
|
||||
if ($jobId) {
|
||||
$job->id = $jobId;
|
||||
$job->saveField('message', 'Job complete.');
|
||||
|
@ -489,6 +581,7 @@ class Feed extends AppModel {
|
|||
if ($result !== true) {
|
||||
return false;
|
||||
}
|
||||
$this->__cleanupFile($this->data, '');
|
||||
if ($jobId) {
|
||||
$job->saveField('progress', '100');
|
||||
$job->saveField('message', 'Job complete.');
|
||||
|
@ -497,6 +590,17 @@ class Feed extends AppModel {
|
|||
return $result;
|
||||
}
|
||||
|
||||
private function __cleanupFile($feed, $file) {
|
||||
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
|
||||
if (isset($feed['Feed']['delete_local_file']) && $feed['Feed']['delete_local_file']) {
|
||||
if (file_exists($feed['Feed']['url'] . $file)) {
|
||||
unlink($feed['Feed']['url'] . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function saveFreetextFeedData($feed, $data, $user, $jobId = false) {
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$event = false;
|
||||
|
@ -551,12 +655,20 @@ class Feed extends AppModel {
|
|||
if (empty($data)) {
|
||||
return true;
|
||||
}
|
||||
$prunedCopy = array();
|
||||
foreach ($data as $key => $value) {
|
||||
foreach ($prunedCopy as $copy) {
|
||||
if ($copy['type'] == $value['type'] && $copy['category'] == $value['category'] && $copy['value'] == $value['value']) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$data[$key]['event_id'] = $event['Event']['id'];
|
||||
$data[$key]['distribution'] = $feed['Feed']['distribution'];
|
||||
$data[$key]['sharing_group_id'] = $feed['Feed']['sharing_group_id'];
|
||||
$data[$key]['to_ids'] = $feed['Feed']['override_ids'] ? 0 : $data[$key]['to_ids'];
|
||||
$prunedCopy[] = $data[$key];
|
||||
}
|
||||
$data = $prunedCopy;
|
||||
if ($jobId) {
|
||||
$job = ClassRegistry::init('Job');
|
||||
$job->id = $jobId;
|
||||
|
|
|
@ -43,7 +43,8 @@ class Log extends AppModel {
|
|||
'merge',
|
||||
'undelete',
|
||||
'file_upload',
|
||||
'export'
|
||||
'export',
|
||||
'pruneUpdateLogs'
|
||||
)),
|
||||
'message' => 'Options : ...'
|
||||
)
|
||||
|
@ -85,6 +86,7 @@ class Log extends AppModel {
|
|||
if (!isset($this->data['Log'][$field]) || empty($this->data['Log'][$field])) $this->data['Log'][$field] = $empty;
|
||||
}
|
||||
if (!isset($this->data['Log']['created'])) $this->data['Log']['created'] = date('Y-m-d H:i:s');
|
||||
if (!isset($this->data['Log']['org'])) $this->data['Log']['org'] = 'SYSTEM';
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -140,4 +142,78 @@ class Log extends AppModel {
|
|||
'model_id' => $model_id,
|
||||
));
|
||||
}
|
||||
|
||||
// to combat a certain bug that causes the upgrade scripts to loop without being able to set the correct version
|
||||
// this function remedies a fixed upgrade bug instance by eliminating the massive number of erroneous upgrade log entries
|
||||
public function pruneUpdateLogs($jobId = false, $user) {
|
||||
$max = $this->find('first', array('fields' => array('MAX(id) AS lastid')));
|
||||
if (!empty($max)) {
|
||||
$max = $max[0]['lastid'];
|
||||
}
|
||||
if ($jobId) {
|
||||
$this->Job = ClassRegistry::init('Job');
|
||||
$this->Job->id = $jobId;
|
||||
if (!$this->Job->exists()) {
|
||||
$jobId = false;
|
||||
}
|
||||
}
|
||||
$iterations = ($max / 1000);
|
||||
for ($i = 0; $i < $iterations; $i++) {
|
||||
$this->deleteAll(array(
|
||||
'OR' => array(
|
||||
'action' => 'update_database',
|
||||
'AND' => array(
|
||||
'action' => 'edit',
|
||||
'model' => 'AdminSetting'
|
||||
)
|
||||
),
|
||||
'id >' => $i * 1000,
|
||||
'id <' => ($i+1) * 1000));
|
||||
if ($jobId) {
|
||||
$this->Job->saveField('progress', $i * 100 / $iterations);
|
||||
}
|
||||
}
|
||||
$this->create();
|
||||
$this->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'email' =>$user['email'],
|
||||
'user_id' => $user['id'],
|
||||
'action' => 'pruneUpdateLogs',
|
||||
'title' => 'Pruning updates',
|
||||
'change' => 'Pruning completed in ' . $i . ' iteration(s).',
|
||||
'model' => 'Log',
|
||||
'model_id' => 0
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
public function pruneUpdateLogsRouter($user) {
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
$job = ClassRegistry::init('Job');
|
||||
$job->create();
|
||||
$data = array(
|
||||
'worker' => 'default',
|
||||
'job_type' => 'prune_update_logs',
|
||||
'job_input' => 'All update entries',
|
||||
'status' => 0,
|
||||
'retries' => 0,
|
||||
'org_id' => $user['org_id'],
|
||||
'org' => $user['Organisation']['name'],
|
||||
'message' => 'Purging the heretic.',
|
||||
);
|
||||
$job->save($data);
|
||||
$jobId = $job->id;
|
||||
$process_id = CakeResque::enqueue(
|
||||
'default',
|
||||
'AdminShell',
|
||||
array('prune_update_logs', $jobId, $user['id']),
|
||||
true
|
||||
);
|
||||
$job->saveField('process_id', $process_id);
|
||||
return $process_id;
|
||||
} else {
|
||||
$result = $this->pruneUpdateLogs(false, $user);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class Organisation extends AppModel{
|
|||
$this->data['Organisation']['uuid'] = CakeText::uuid();
|
||||
}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
if (!isset($this->data['Organisation']['date_created']) || empty($this->data['Organisation']['date_created'])) $this->data['Organisation']['date_created'] = $date;
|
||||
if (!isset($this->data['Organisation']['id'])) $this->data['Organisation']['date_created'] = $date;
|
||||
$this->data['Organisation']['date_modified'] = $date;
|
||||
if (!isset($this->data['Organisation']['nationality']) || empty($this->data['Organisation']['nationality'])) $this->data['Organisation']['nationality'] = 'Not specified';
|
||||
return true;
|
||||
|
|
|
@ -128,6 +128,15 @@ class Server extends AppModel {
|
|||
'test' => 'testLive',
|
||||
'type' => 'boolean',
|
||||
),
|
||||
'enable_advanced_correlations' => array(
|
||||
'level' => 0,
|
||||
'description' => 'Enable some performance heavy correlations (currently CIDR correlation)',
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'maintenance_message' => array(
|
||||
'level' => 2,
|
||||
'description' => 'The message that users will see if the instance is not live.',
|
||||
|
@ -598,6 +607,15 @@ class Server extends AppModel {
|
|||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'showDiscussionsCountOnIndex' => array(
|
||||
'level' => 1,
|
||||
'description' => 'When enabled, the aggregate number of discussion posts for the event becomes visible to the currently logged in user on the event index UI.',
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'disableUserSelfManagement' => array(
|
||||
'level' => 1,
|
||||
'description' => 'When enabled only Org and Site admins can edit a user\'s profile.',
|
||||
|
@ -891,6 +909,15 @@ class Server extends AppModel {
|
|||
'test' => 'testPasswordRegex',
|
||||
'type' => 'string',
|
||||
),
|
||||
'sanitise_attribute_on_delete' => array(
|
||||
'level' => 1,
|
||||
'description' => 'Enabling this setting will sanitise the contents of an attribute on a soft delete',
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
)
|
||||
),
|
||||
'SecureAuth' => array(
|
||||
'branch' => 1,
|
||||
|
@ -923,7 +950,7 @@ class Server extends AppModel {
|
|||
),
|
||||
'defaults' => array(
|
||||
'level' => 0,
|
||||
'description' => 'The session type used by MISP. The default setting is database, which will use the MySQL tables for the session data (supported options: database, php). The recommended option is php and setting your PHP up to use redis sessions via your php.ini. Just add \'session.save_handler = redis\' and "session.save_path = \'tcp://localhost:6379\'" (replace the latter with your redis connection) to ',
|
||||
'description' => 'The session type used by MISP. The default setting is php, which will use the session settings configured in php.ini for the session data (supported options: php, database). The recommended option is php and setting your PHP up to use redis sessions via your php.ini. Just add \'session.save_handler = redis\' and "session.save_path = \'tcp://localhost:6379\'" (replace the latter with your redis connection) to ',
|
||||
'value' => '',
|
||||
'errorMessage' => '',
|
||||
'test' => 'testForSessionDefaults',
|
||||
|
@ -1329,6 +1356,7 @@ class Server extends AppModel {
|
|||
'errorMessage' => '',
|
||||
'test' => 'testDebugAdmin',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1552,54 +1580,18 @@ class Server extends AppModel {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Fallback for < 2.4.7 instances
|
||||
$k = 0;
|
||||
foreach ($events as $eid => $event) {
|
||||
$proposals = $eventModel->downloadEventFromServer($event, $server, null, true);
|
||||
if (null != $proposals) {
|
||||
if (isset($proposals['ShadowAttribute']['id'])) {
|
||||
$temp = $proposals['ShadowAttribute'];
|
||||
$proposals['ShadowAttribute'] = array(0 => $temp);
|
||||
}
|
||||
foreach ($proposals['ShadowAttribute'] as &$proposal) {
|
||||
$oldsa = $shadowAttribute->findOldProposal($proposal);
|
||||
$proposal['event_id'] = $eid;
|
||||
if (!$oldsa || $oldsa['timestamp'] < $proposal['timestamp']) {
|
||||
if ($oldsa) $shadowAttribute->delete($oldsa['id']);
|
||||
if (!isset($pulledProposals[$eid])) $pulledProposals[$eid] = 0;
|
||||
$pulledProposals[$eid]++;
|
||||
if (isset($proposal['old_id'])) {
|
||||
$oldAttribute = $eventModel->Attribute->find('first', array('recursive' => -1, 'conditions' => array('uuid' => $proposal['uuid'])));
|
||||
if ($oldAttribute) $proposal['old_id'] = $oldAttribute['Attribute']['id'];
|
||||
else $proposal['old_id'] = 0;
|
||||
}
|
||||
// check if this is a proposal from an old MISP instance
|
||||
if (!isset($proposal['Org']) && isset($proposal['org']) && !empty($proposal['org'])) {
|
||||
$proposal['Org'] = $proposal['org'];
|
||||
$proposal['EventOrg'] = $proposal['event_org'];
|
||||
} else if (!isset($proposal['Org']) && !isset($proposal['EventOrg'])) {
|
||||
continue;
|
||||
}
|
||||
$proposal['org_id'] = $this->Organisation->captureOrg($proposal['Org'], $user);
|
||||
$proposal['event_org_id'] = $this->Organisation->captureOrg($proposal['EventOrg'], $user);
|
||||
unset($proposal['Org']);
|
||||
unset($proposal['EventOrg']);
|
||||
$shadowAttribute->create();
|
||||
if (!isset($proposal['deleted']) || !$proposal['deleted']) {
|
||||
if ($shadowAttribute->save($proposal)) $shadowAttribute->sendProposalAlertEmail($eid);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($jobId) {
|
||||
if ($k % 10 == 0) {
|
||||
$job->id = $jobId;
|
||||
$job->saveField('progress', 50 * (($k + 1) / count($events)));
|
||||
}
|
||||
}
|
||||
$k++;
|
||||
}
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Server',
|
||||
'model_id' => $id,
|
||||
'email' => $user['email'],
|
||||
'action' => 'error',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Pulling of proposals has failed.',
|
||||
'change' => ''
|
||||
));
|
||||
}
|
||||
}
|
||||
if ($jobId) {
|
||||
|
@ -2123,7 +2115,6 @@ class Server extends AppModel {
|
|||
}
|
||||
|
||||
public function testDebugAdmin($value) {
|
||||
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
|
||||
if ($this->testBool($value) !== true) return 'This setting has to be either true or false.';
|
||||
if (!$value) return true;
|
||||
return 'Enabling debug is not recommended. Turn this on temporarily if you need to see a stack trace to debug an issue, but make sure this is not left on.';
|
||||
|
@ -2160,7 +2151,6 @@ class Server extends AppModel {
|
|||
}
|
||||
|
||||
public function testBool($value) {
|
||||
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
|
||||
if ($value !== true && $value !== false) return 'Value is not a boolean, make sure that you convert \'true\' to true for example.';
|
||||
return true;
|
||||
}
|
||||
|
@ -3294,4 +3284,12 @@ class Server extends AppModel {
|
|||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function databaseEncodingDiagnostics(&$diagnostic_errors) {
|
||||
if (!isset($this->getDataSource()->config['encoding']) || strtolower($this->getDataSource()->config['encoding']) != 'utf8') {
|
||||
$diagnostic_errors++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class Sighting extends AppModel {
|
|||
return true;
|
||||
}
|
||||
|
||||
public function attachToEvent(&$event, &$user) {
|
||||
public function attachToEvent(&$event, $user) {
|
||||
$ownEvent = false;
|
||||
if ($user['Role']['perm_site_admin'] || $event['Event']['org_id'] == $user['org_id']) $ownEvent = true;
|
||||
$conditions = array('Sighting.event_id' => $event['Event']['id']);
|
||||
|
|
|
@ -45,6 +45,9 @@ class Tag extends AppModel {
|
|||
'TemplateTag',
|
||||
'FavouriteTag' => array(
|
||||
'dependent' => true
|
||||
),
|
||||
'AttributeTag' => array(
|
||||
'dependent' => true
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -104,6 +107,25 @@ class Tag extends AppModel {
|
|||
return $ids;
|
||||
}
|
||||
|
||||
public function findAttributeIdsByAttributeTagNames($array) {
|
||||
$ids = array();
|
||||
foreach ($array as $a) {
|
||||
$conditions['OR'][] = array('LOWER(name) LIKE' => strtolower($a));
|
||||
}
|
||||
$params = array(
|
||||
'recursive' => 1,
|
||||
'contain' => 'AttributeTag',
|
||||
'conditions' => $conditions
|
||||
);
|
||||
$result = $this->find('all', $params);
|
||||
foreach ($result as $tag) {
|
||||
foreach ($tag['AttributeTag'] as $attributeTag) {
|
||||
$ids[] = $attributeTag['attribute_id'];
|
||||
}
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
public function captureTag($tag, $user) {
|
||||
$existingTag = $this->find('first', array(
|
||||
'recursive' => -1,
|
||||
|
@ -176,9 +198,11 @@ class Tag extends AppModel {
|
|||
}
|
||||
|
||||
public function getTagsForNamespace($namespace) {
|
||||
$contain = array('EventTag');
|
||||
$contain[] = 'AttributeTag';
|
||||
$tags_temp = $this->find('all', array(
|
||||
'recursive' => -1,
|
||||
'contain' => 'EventTag',
|
||||
'contain' => $contain,
|
||||
'conditions' => array('UPPER(name) LIKE' => strtoupper($namespace) . '%'),
|
||||
));
|
||||
$tags = array();
|
||||
|
|
|
@ -3,7 +3,7 @@ App::uses('AppModel', 'Model');
|
|||
App::uses('AuthComponent', 'Controller/Component');
|
||||
App::uses('RandomTool', 'Tools');
|
||||
|
||||
class User extends AppModel {
|
||||
class User extends AppModel {
|
||||
|
||||
public $displayField = 'email';
|
||||
|
||||
|
@ -242,6 +242,7 @@ class User extends AppModel {
|
|||
$this->data['User']['confirm_password'] = $this->data['User']['password'];
|
||||
}
|
||||
}
|
||||
if (!isset($this->data['User']['certif_public']) || empty($this->data['User']['certif_public'])) $this->data['User']['certif_public'] = '';
|
||||
if (!isset($this->data['User']['authkey']) || empty($this->data['User']['authkey'])) $this->data['User']['authkey'] = $this->generateAuthKey();
|
||||
if (!isset($this->data['User']['nids_sid']) || empty($this->data['User']['nids_sid'])) $this->data['User']['nids_sid'] = mt_rand(1000000, 9999999);
|
||||
return true;
|
||||
|
@ -882,21 +883,35 @@ class User extends AppModel {
|
|||
return $fields;
|
||||
}
|
||||
|
||||
public function getMembersCount() {
|
||||
public function getMembersCount($org_id = false) {
|
||||
// for Organizations List
|
||||
$conditions = array();
|
||||
$findType = 'all';
|
||||
if ($org_id !== false) {
|
||||
$findType = 'first';
|
||||
$conditions = array('User.org_id' => $org_id);
|
||||
}
|
||||
$fields = array('org_id', 'COUNT(User.id) AS num_members');
|
||||
$params = array(
|
||||
'fields' => $fields,
|
||||
'recursive' => -1,
|
||||
'group' => array('org_id'),
|
||||
'order' => array('org_id'),
|
||||
'conditions' => $conditions
|
||||
);
|
||||
$orgs = $this->find('all', $params);
|
||||
$usersPerOrg = [];
|
||||
foreach ($orgs as $key => $value) {
|
||||
$usersPerOrg[$value['User']['org_id']] = $value[0]['num_members'];
|
||||
$orgs = $this->find($findType, $params);
|
||||
if (empty($orgs)) {
|
||||
return 0;
|
||||
}
|
||||
if ($org_id !== false) {
|
||||
return $orgs[0]['num_members'];
|
||||
} else {
|
||||
$usersPerOrg = [];
|
||||
foreach ($orgs as $key => $value) {
|
||||
$usersPerOrg[$value['User']['org_id']] = $value[0]['num_members'];
|
||||
}
|
||||
return $usersPerOrg;
|
||||
}
|
||||
return $usersPerOrg;
|
||||
}
|
||||
|
||||
public function findAdminsResponsibleForUser($user){
|
||||
|
@ -928,4 +943,40 @@ class User extends AppModel {
|
|||
|
||||
return $admin['User'];
|
||||
}
|
||||
|
||||
public function initiatePasswordReset($user, $firstTime = false, $simpleReturn = false, $fixedPassword = false) {
|
||||
$org = Configure::read('MISP.org');
|
||||
$options = array('passwordResetText', 'newUserText');
|
||||
$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);
|
||||
$result = $this->sendEmail($user, $body, false, $subject);
|
||||
if ($result) {
|
||||
$this->id = $user['User']['id'];
|
||||
$this->saveField('password', $password);
|
||||
$this->saveField('change_pw', '1');
|
||||
if ($simpleReturn) {
|
||||
return true;
|
||||
} else {
|
||||
return array('body'=> json_encode(array('saved' => true, 'success' => 'New credentials sent.')),'status'=>200);
|
||||
}
|
||||
}
|
||||
if ($simpleReturn) {
|
||||
return false;
|
||||
} else {
|
||||
return array('body'=> json_encode(array('saved' => false, 'errors' => 'There was an error notifying the user. His/her credentials were not altered.')),'status'=>200);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ class Warninglist extends AppModel{
|
|||
}
|
||||
|
||||
private function __checkValue($listValues, $value, $type, $listType) {
|
||||
if (strpos($type, '|')) $value = explode('|', $value);
|
||||
if (strpos($type, '|') || $type = 'malware-sample') $value = explode('|', $value);
|
||||
else $value = array($value);
|
||||
$components = array(0, 1);
|
||||
foreach ($components as $component) {
|
||||
|
@ -164,6 +164,10 @@ class Warninglist extends AppModel{
|
|||
$result = $this->__evalCIDRList($listValues, $value[$component]);
|
||||
} else if ($listType === 'string') {
|
||||
$result = $this->__evalString($listValues, $value[$component]);
|
||||
} else if ($listType === 'substring') {
|
||||
$result = $this->__evalSubString($listValues, $value[$component]);
|
||||
} else if ($listType === 'hostname') {
|
||||
$result = $this->__evalHostname($listValues, $value[$component]);
|
||||
}
|
||||
if ($result) return ($component + 1);
|
||||
}
|
||||
|
@ -243,6 +247,43 @@ class Warninglist extends AppModel{
|
|||
return false;
|
||||
}
|
||||
|
||||
private function __evalSubString($listValues, $value) {
|
||||
foreach ($listValues as $listValue) {
|
||||
if (strpos($value, $listValue) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function __evalHostname($listValues, $value) {
|
||||
// php's parse_url is dumb, so let's use some hacky workarounds
|
||||
if (strpos($value, '//') == false) {
|
||||
$value = 'http://' . $value;
|
||||
}
|
||||
$hostname = parse_url($value, PHP_URL_HOST);
|
||||
// If the hostname is not found, just return false
|
||||
if (!isset($hostname)) {
|
||||
return false;
|
||||
}
|
||||
$value = explode('.', $hostname);
|
||||
$pieces = count($value);
|
||||
foreach ($listValues as $listValue) {
|
||||
$listValue = explode('.', $listValue);
|
||||
if (count($listValue) > $pieces) {
|
||||
continue;
|
||||
}
|
||||
$piecesListValue = count($listValue);
|
||||
$listValue = implode('.', $listValue);
|
||||
$temp = array_slice($value, -$piecesListValue, $piecesListValue);
|
||||
$temp = implode('.', $temp);
|
||||
if ($listValue == $temp) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function fetchTLDLists() {
|
||||
$tldLists = $this->find('list', array('conditions' => array('Warninglist.name' => $this->__tlds, 'Warninglist.enabled' => 1), 'recursive' => -1, 'fields' => array('Warninglist.id', 'Warninglist.name')));
|
||||
$tlds = array();
|
||||
|
|
|
@ -109,13 +109,14 @@
|
|||
}
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var fieldsArray = new Array('AttributeCategory', 'AttributeType', 'AttributeValue', 'AttributeDistribution', 'AttributeComment', 'AttributeToIds', 'AttributeBatchImport', 'AttributeSharingGroupId');
|
||||
<?php
|
||||
$formInfoTypes = array('distribution' => 'Distribution', 'category' => 'Category', 'type' => 'Type');
|
||||
echo 'var formInfoFields = ' . json_encode($formInfoTypes) . PHP_EOL;
|
||||
foreach ($formInfoTypes as $formInfoType => $humanisedName) {
|
||||
echo 'var ' . $formInfoType . 'FormInfoValues = {' . PHP_EOL;
|
||||
foreach ($info[$formInfoType] as $key => $formInfoData) {
|
||||
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
|
||||
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
|
||||
}
|
||||
echo '}' . PHP_EOL;
|
||||
}
|
||||
|
@ -157,11 +158,10 @@ $(document).ready(function() {
|
|||
$('#SGContainer').hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#AttributeCategory, #AttributeType, #AttributeDistribution").change(function() {
|
||||
initPopoverContent('Attribute');
|
||||
});
|
||||
|
||||
<?php if ($ajax): ?>
|
||||
$('#cancel_attribute_add').click(function() {
|
||||
cancelPopoverForm();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Event']['orgc_id'] == $me['org_id']) || ($isAclModifyOrg && $event['Event']['orgc_id'] == $me['org_id']));
|
||||
echo $this->element('ajaxAttributeTags', array('attributeId' => $attributeId, 'attributeTags' => $attributeTags, 'tagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id'])));
|
||||
?>
|
|
@ -33,6 +33,8 @@
|
|||
));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
echo $this->Form->input('comment', array(
|
||||
'type' => 'textarea',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<div class="confirmation">
|
||||
<?php
|
||||
echo $this->Form->create($model, array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/' . strtolower($model) . 's/removeTag/' . $id . '/' . $tag_id));
|
||||
$action = "removeObjectTag('" . $model . "', '" . h($id) . "', '" . h($tag_id) . "');";
|
||||
?>
|
||||
<legend>Remove Tag</legend>
|
||||
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
|
||||
<p>Remove tag (<?php echo h($tag_id); ?>) from <?php echo ucfirst(h($model)); ?> (<?php echo h($id); ?>)?</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span id="PromptYesButton" class="btn btn-primary" onClick="<?php echo $action; ?>">Yes</span>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();">No</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</div>
|
|
@ -67,13 +67,14 @@
|
|||
echo $this->element('side_menu', array('menuList' => 'event', 'menuItem' => 'addAttribute', 'event' => $event));
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var fieldsArray = new Array('AttributeCategory', 'AttributeType', 'AttributeValue', 'AttributeDistribution', 'AttributeComment', 'AttributeToIds', 'AttributeBatchImport', 'AttributeSharingGroupId');
|
||||
<?php
|
||||
$formInfoTypes = array('distribution' => 'Distribution', 'category' => 'Category', 'type' => 'Type');
|
||||
echo 'var formInfoFields = ' . json_encode($formInfoTypes) . PHP_EOL;
|
||||
foreach ($formInfoTypes as $formInfoType => $humanisedName) {
|
||||
echo 'var ' . $formInfoType . 'FormInfoValues = {' . PHP_EOL;
|
||||
foreach ($info[$formInfoType] as $key => $formInfoData) {
|
||||
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
|
||||
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
|
||||
}
|
||||
echo '}' . PHP_EOL;
|
||||
}
|
||||
|
@ -101,7 +102,7 @@ $(document).ready(function() {
|
|||
if ($('#AttributeDistribution').val() == 4) $('#SGContainer').show();
|
||||
else $('#SGContainer').hide();
|
||||
});
|
||||
|
||||
|
||||
$("#AttributeCategory").on('change', function(e) {
|
||||
formCategoryChanged('Attribute');
|
||||
if ($(this).val() === 'Attribution' || $(this).val() === 'Targeting data') {
|
||||
|
@ -114,7 +115,7 @@ $(document).ready(function() {
|
|||
$('#SGContainer').hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#AttributeCategory, #AttributeType, #AttributeDistribution").change(function() {
|
||||
initPopoverContent('Attribute');
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
if ($isSearch == 1) {
|
||||
echo "<h4>Results for all attributes";
|
||||
if ($keywordSearch != null) echo " with the value containing \"<b>" . h($keywordSearch) . "</b>\"";
|
||||
if ($attributeTags != null) echo " being tagged with \"<b>" . h($attributeTags) . "</b>\"";
|
||||
if ($keywordSearch2 != null) echo " from the events \"<b>" . h($keywordSearch2) . "</b>\"";
|
||||
if ($tags != null) echo " from events tagged \"<b>" . h($tags) . "</b>\"";
|
||||
if ($categorySearch != "ALL") echo " of category \"<b>" . h($categorySearch) . "</b>\"";
|
||||
|
@ -36,6 +37,7 @@ if ($isSearch == 1) {
|
|||
<th><?php echo $this->Paginator->sort('category');?></th>
|
||||
<th><?php echo $this->Paginator->sort('type');?></th>
|
||||
<th><?php echo $this->Paginator->sort('value');?></th>
|
||||
<th>Tags</th>
|
||||
<th><?php echo $this->Paginator->sort('comment');?></th>
|
||||
<th<?php echo ' title="' . $attrDescriptions['signature']['desc'] . '"';?>>
|
||||
<?php echo $this->Paginator->sort('IDS');?></th>
|
||||
|
@ -101,6 +103,21 @@ foreach ($attributes as $attribute):
|
|||
}
|
||||
?>
|
||||
</td>
|
||||
<td style = "max-width:200px;width:10px;">
|
||||
<?php foreach ($attribute['AttributeTag'] as $tag):
|
||||
$tagText = " ";
|
||||
if (Configure::read('MISP.full_tags_on_attribute_index') == 1) $tagText = h($tag['Tag']['name']);
|
||||
else if (Configure::read('MISP.full_tags_on_attribute_index') == 2) {
|
||||
if (strpos($tag['Tag']['name'], '=')) {
|
||||
$tagText = explode('=', $tag['Tag']['name']);
|
||||
$tagText = h(trim(end($tagText), "\""));
|
||||
}
|
||||
else $tagText = h($tag['Tag']['name']);
|
||||
}
|
||||
?>
|
||||
<span class="tag useCursorPointer" style="margin-bottom:3px;background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>;" title="<?php echo h($tag['Tag']['name']); ?>" onClick="document.location.href='<?php echo $baseurl; ?>/attributes/search/attributetag:<?php echo h($tag['Tag']['id']);?>';"><?php echo $tagText; ?></span>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<td ondblclick="document.location ='document.location ='<?php echo $baseurl;?>/events/view/<?php echo $attribute['Event']['id'];?>';">
|
||||
<?php
|
||||
$sigDisplay = nl2br(h($attribute['Attribute']['comment']));
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
You can search for attributes based on contained expression within the value, event ID, submitting organisation, category and type. <br />For the value, event ID and organisation, you can enter several search terms by entering each term as a new line. To exclude things from a result, use the NOT operator (!) in front of the term.<br/><br />
|
||||
<?php
|
||||
echo $this->Form->input('keyword', array('type' => 'textarea', 'rows' => 2, 'label' => 'Containing the following expressions', 'div' => 'clear', 'class' => 'input-xxlarge'));
|
||||
echo $this->Form->input('attributetags', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being an attribute matching the following tags', 'div' => 'clear', 'class' => 'input-xxlarge'));
|
||||
echo $this->Form->input('keyword2', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being attributes of the following event IDs, event UUIDs or attribute UUIDs', 'div' => 'clear', 'class' => 'input-xxlarge'));
|
||||
echo $this->Form->input('tags', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being an attribute of an event matching the following tags', 'div' => 'clear', 'class' => 'input-xxlarge'));
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<?php
|
||||
endif;
|
||||
endif;
|
||||
$date = time();
|
||||
$day = 86400;
|
||||
?>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<th>Clusters</th>
|
||||
|
@ -37,6 +39,9 @@
|
|||
<?php if (Configure::read('MISP.showProposalsOnIndex')):?>
|
||||
<th title="Proposal Count">#Prop</th>
|
||||
<?php endif; ?>
|
||||
<?php if (Configure::read('MISP.showDiscussionsCountOnIndex')):?>
|
||||
<th title="Post Count">#Posts</th>
|
||||
<?php endif; ?>
|
||||
<?php if ($isSiteAdmin): ?>
|
||||
<th><?php echo $this->Paginator->sort('user_id', 'Email');?></th>
|
||||
<?php endif; ?>
|
||||
|
@ -163,6 +168,21 @@
|
|||
<?php echo !empty($event['Event']['proposals_count']) ? h($event['Event']['proposals_count']) : ''; ?>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<?php if (Configure::read('MISP.showDiscussionsCountOnIndex')): ?>
|
||||
<td class = "bold" style="width:30px;" ondblclick="location.href ='<?php echo $baseurl."/events/view/".$event['Event']['id'];?>'" title="<?php echo (!empty($event['Event']['proposals_count']) ? h($event['Event']['proposals_count']) : '0') . ' proposal(s)';?>">
|
||||
<?php
|
||||
if (!empty($event['Event']['post_count'])) {
|
||||
$post_count = h($event['Event']['post_count']);
|
||||
if (($date - $event['Event']['last_post']) < $day) {
|
||||
$post_count .= ' (<span class="red bold">NEW</span>)';
|
||||
}
|
||||
} else {
|
||||
$post_count = '';
|
||||
}
|
||||
?>
|
||||
<span style=" white-space: nowrap;"><?php echo $post_count?></span>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<?php if ('true' == $isSiteAdmin): ?>
|
||||
<td class="short" ondblclick="location.href ='<?php echo $baseurl."/events/view/".$event['Event']['id'];?>'">
|
||||
<?php echo h($event['User']['email']); ?>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<div style="width:100%;display:inline-block;">
|
||||
<?php
|
||||
$full = $isAclTagger && $tagAccess;
|
||||
foreach ($attributeTags as $tag):
|
||||
$tagClass = $full ? 'tagFirstHalf' : 'tag';
|
||||
?>
|
||||
<div style="padding:1px; overflow:hidden; white-space:nowrap; display:flex; float:left; margin-right:2px;">
|
||||
<a href="<?php echo $baseurl;?>/attributes/search/attributetag:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
|
||||
<?php if ($full): ?>
|
||||
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeObjectTagPopup('attribute', '<?php echo h($attributeId); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
<div style="float:left">
|
||||
<?php if ($full): ?>
|
||||
<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup('<?php echo h($attributeId); ?>' + '/true', 'tags', 'selectTaxonomy');">+</button>
|
||||
<?php else:?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
|
@ -1,33 +1,20 @@
|
|||
<div style="width:100%;display:inline-block;">
|
||||
<?php
|
||||
foreach ($tags as $tag): ?>
|
||||
<div style="overflow:hidden;white-space:nowrap;float:left;">
|
||||
<div style="padding-right:0px;float: left;">
|
||||
<?php if ($isAclTagger && $tagAccess): ?>
|
||||
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class="tagFirstHalf" style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
|
||||
<?php else: ?>
|
||||
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class=tag style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div style="padding-left:0px;padding-right:5px;float:left;">
|
||||
<?php if ($isAclTagger && $tagAccess): ?>
|
||||
<?php
|
||||
echo $this->Form->create('Event', array('id' => 'removeTag_' . h($tag['Tag']['id']), 'url' => '/events/removeTag/' . h($event['Event']['id']) . '/' . h($tag['Tag']['id']), 'style' => 'margin:0px;'));
|
||||
?>
|
||||
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeEventTag('<?php echo h($event['Event']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
<?php else: ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
$full = $isAclTagger && $tagAccess;
|
||||
foreach ($tags as $tag):
|
||||
$tagClass = $full ? 'tagFirstHalf' : 'tag';
|
||||
?>
|
||||
<div style="padding:1px; overflow:hidden; white-space:nowrap; display:flex; float:left; margin-right:2px;">
|
||||
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
|
||||
<?php if ($full): ?>
|
||||
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeObjectTagPopup('event', '<?php echo h($event['Event']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
<div style="float:left">
|
||||
<?php if ($isAclTagger && $tagAccess): ?>
|
||||
<?php if ($full): ?>
|
||||
<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'tags', 'selectTaxonomy');">+</button>
|
||||
<?php else:?>
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
<div class="tabMenu tabMenuEditBlock noPrint">
|
||||
<span id="create-button" title="Add attribute" class="icon-plus useCursorPointer" onClick="clickCreateButton(<?php echo $event['Event']['id']; ?>, '<?php echo $possibleAction; ?>');"></span>
|
||||
<span id="multi-edit-button" title="Edit selected Attributes" class="icon-edit mass-select useCursorPointer" onClick="editSelectedAttributes(<?php echo $event['Event']['id']; ?>);"></span>
|
||||
<span id="multi-tag-button" title="Tag selected Attributes" class="icon-tag mass-select useCursorPointer" onClick="getPopup('selected/true', 'tags', 'selectTaxonomy');"></span>
|
||||
<span id="multi-delete-button" title="Delete selected Attributes" class = "icon-trash mass-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'deleteAttributes');"></span>
|
||||
<span id="multi-accept-button" title="Accept selected Proposals" class="icon-ok mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'acceptProposals');"></span>
|
||||
<span id="multi-discard-button" title="Discard selected Proposals" class = "icon-remove mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'discardProposals');"></span>
|
||||
|
@ -169,6 +170,7 @@
|
|||
<th><?php echo $this->Paginator->sort('category');?></th>
|
||||
<th><?php echo $this->Paginator->sort('type');?></th>
|
||||
<th><?php echo $this->Paginator->sort('value');?></th>
|
||||
<th>Tags</th>
|
||||
<th><?php echo $this->Paginator->sort('comment');?></th>
|
||||
<?php
|
||||
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
|
||||
|
@ -292,8 +294,7 @@
|
|||
$extension = explode('.', $object['value']);
|
||||
$extension = end($extension);
|
||||
$uri = 'data:image/' . strtolower(h($extension)) . ';base64,' . h($object['image']);
|
||||
$img = '<img src="' . $uri . '" style="width:200px;" title="' . h($object['value']) . '" />';
|
||||
echo '<a href="' . $baseurl . '/' . ($object['objectType'] == 0 ? 'attributes' : 'shadow_attributes') . '/download/' . h($object['id']) . '">' . $img . '</a>';
|
||||
echo '<img class="screenshot screenshot-collapsed useCursorPointer" src="' . $uri . '" title="' . h($object['value']) . '" />';
|
||||
} else {
|
||||
$t = ($object['objectType'] == 0 ? 'attributes' : 'shadow_attributes');
|
||||
$filenameHash = explode('|', nl2br(h($object['value'])));
|
||||
|
@ -305,12 +306,12 @@
|
|||
} else {
|
||||
echo '<a href="' . $baseurl . '/' . h($t) . '/download/' . h($object['id']) . '" class="' . $linkClass . '">' . h($filenameHash[0]) . '</a>';
|
||||
}
|
||||
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
|
||||
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
|
||||
}
|
||||
} else if (strpos($object['type'], '|') !== false) {
|
||||
$filenameHash = explode('|', $object['value']);
|
||||
echo h($filenameHash[0]);
|
||||
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
|
||||
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
|
||||
} else if ('vulnerability' == $object['type']) {
|
||||
if (! is_null(Configure::read('MISP.cveurl'))) {
|
||||
$cveUrl = Configure::read('MISP.cveurl');
|
||||
|
@ -350,6 +351,21 @@
|
|||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="shortish <?php echo $extra; ?>">
|
||||
<?php
|
||||
if ($object['objectType'] == 0):
|
||||
?>
|
||||
<div class="attributeTagContainer">
|
||||
<?php echo $this->element('ajaxAttributeTags', array('attributeId' => $object['id'], 'attributeTags' => $object['AttributeTag'], 'tagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id']) )); ?>
|
||||
</div>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td class="showspaces bitwider <?php echo $extra; ?>">
|
||||
<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" ondblclick="activateField('<?php echo $currentType; ?>', '<?php echo $object['id']; ?>', 'comment', <?php echo $event['Event']['id'];?>);">
|
||||
|
@ -360,12 +376,14 @@
|
|||
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
|
||||
if ($object['objectType'] == 0):
|
||||
?>
|
||||
<td class="short" style="padding-top:3px;">
|
||||
<td class="short <?php echo $extra; ?>" style="padding-top:3px;">
|
||||
<input class="correlation-toggle" type="checkbox" data-attribute-id="<?php echo h($object['id']); ?>" <?php echo $object['disable_correlation'] ? '' : 'checked'; ?>>
|
||||
</td>
|
||||
<?php
|
||||
else:
|
||||
echo ' ';
|
||||
?>
|
||||
<td class="short <?php echo $extra; ?>" style="padding-top:3px;"> </td>
|
||||
<?php
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
|
@ -599,6 +617,9 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
|
||||
return false;
|
||||
});
|
||||
$('.screenshot').click(function() {
|
||||
screenshotPopup($(this).attr('src'), $(this).attr('title'));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
<?php
|
||||
foreach ($posts as $post) {
|
||||
?>
|
||||
<a name="message_<?php echo h($post['Post']['id']);?>"></a>
|
||||
<table class="discussionBox" id=<?php echo '"' . h($post['Post']['id']) . '"';?> >
|
||||
<a name="message_<?php echo h($post['id']);?>"></a>
|
||||
<table class="discussionBox" id=<?php echo '"' . h($post['id']) . '"';?> >
|
||||
<tr>
|
||||
<td class="discussionBoxTD discussionBoxTDtop" colspan="2">
|
||||
<div>
|
||||
|
@ -31,12 +31,12 @@
|
|||
<tr>
|
||||
<td>
|
||||
<?php
|
||||
echo 'Date: ' . h($post['Post']['date_created']);
|
||||
echo 'Date: ' . h($post['date_created']);
|
||||
?>
|
||||
</td>
|
||||
<td style="text-align:right">
|
||||
<a href="#top" class="whitelink">Top</a> |
|
||||
<a href="<?php echo "#".$post['Post']['id']; ?>" class="whitelink">#<?php echo h($post['Post']['id'])?></a>
|
||||
<a href="<?php echo "#".$post['id']; ?>" class="whitelink">#<?php echo h($post['id'])?></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -46,10 +46,10 @@
|
|||
<tr>
|
||||
<td class="discussionBoxTD discussionBoxTDMid discussionBoxTDMidLeft">
|
||||
<?php
|
||||
if (isset($post['User']['Organisation'])) {
|
||||
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS . h($post['User']['Organisation']['name']) . '.png';
|
||||
if (file_exists($imgAbsolutePath)) echo $this->Html->image('orgs/' . h($post['User']['Organisation']['name']) . '.png', array('alt' => h($post['User']['Organisation']['name']), 'title' => h($post['User']['Organisation']['name']), 'style' => 'width:48px; height:48px'));
|
||||
else echo $this->Html->tag('span', h($post['User']['Organisation']['name']), array('class' => 'welcome', 'style' => 'float:center;'));
|
||||
if (isset($post['org_name'])) {
|
||||
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS . h($post['org_name']) . '.png';
|
||||
if (file_exists($imgAbsolutePath)) echo $this->Html->image('orgs/' . h($post['org_name']) . '.png', array('alt' => h($post['org_name']), 'title' => h($post['org_name']), 'style' => 'width:48px; height:48px'));
|
||||
else echo $this->Html->tag('span', h($post['org_name']), array('class' => 'welcome', 'style' => 'float:center;'));
|
||||
} else {
|
||||
echo 'Deactivated user';
|
||||
}
|
||||
|
@ -57,22 +57,22 @@
|
|||
</td>
|
||||
<td class="discussionBoxTD discussionBoxTDMid discussionBoxTDMidRight">
|
||||
<?php
|
||||
echo $this->Command->convertQuotes(nl2br(h($post['Post']['contents'])));
|
||||
if ($post['Post']['post_id'] !=0 || ($post['Post']['date_created'] != $post['Post']['date_modified'])) {
|
||||
echo $this->Command->convertQuotes(nl2br(h($post['contents'])));
|
||||
if ($post['post_id'] !=0 || ($post['date_created'] != $post['date_modified'])) {
|
||||
?>
|
||||
<br /><br />
|
||||
<?php
|
||||
}
|
||||
if ($post['Post']['post_id'] != 0) {
|
||||
if ($post['post_id'] != 0) {
|
||||
?>
|
||||
<span style="font-style:italic">
|
||||
In reply to post
|
||||
<a href="<?php echo "#".h($post['Post']['post_id']); ?>">#<?php echo h($post['Post']['post_id'])?></a>
|
||||
<a href="<?php echo "#".h($post['post_id']); ?>">#<?php echo h($post['post_id'])?></a>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
if ($post['Post']['date_created'] != $post['Post']['date_modified']) {
|
||||
echo '<span style="font-style:italic">Message edited at ' . h($post['Post']['date_modified']) . '<span>';
|
||||
if ($post['date_created'] != $post['date_modified']) {
|
||||
echo '<span style="font-style:italic">Message edited at ' . h($post['date_modified']) . '<span>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
@ -82,24 +82,24 @@
|
|||
<table style="width:100%">
|
||||
<tr>
|
||||
<td>
|
||||
<?php echo h($post['User']['email']); ?>
|
||||
<?php echo !empty($post['user_email']) ? h($post['user_email']) : 'User ' . h($post['user_id']) . ' (' . (h($post['org_name'])) . ')'; ?>
|
||||
</td>
|
||||
<td style="text-align:right">
|
||||
<?php
|
||||
if (!$isSiteAdmin) {
|
||||
if ($post['Post']['user_id'] == $myuserid) {
|
||||
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['Post']['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
|
||||
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['Post']['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
|
||||
if ($post['user_id'] == $myuserid) {
|
||||
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
|
||||
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
|
||||
} else {
|
||||
?>
|
||||
<a href="<?php echo $baseurl.'/posts/add/post/'.h($post['Post']['id']); ?>" class="icon-comment" title = "Reply"></a>
|
||||
<a href="<?php echo $baseurl.'/posts/add/post/'.h($post['id']); ?>" class="icon-comment" title = "Reply"></a>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['Post']['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
|
||||
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['Post']['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
|
||||
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
|
||||
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
|
||||
?>
|
||||
<a href = "<?php echo $baseurl.'/posts/add/post/'.h($post['Post']['id']); ?>" class="icon-comment" title = "Reply"></a>
|
||||
<a href = "<?php echo $baseurl.'/posts/add/post/'.h($post['id']); ?>" class="icon-comment" title = "Reply"></a>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
@ -135,7 +135,7 @@
|
|||
<div class="comment">
|
||||
<?php
|
||||
if (isset($currentEvent)) $url = '/posts/add/event/' . $currentEvent;
|
||||
else $url = '/posts/add/thread/' . $thread_id;
|
||||
else $url = '/posts/add/thread/' . $thread['Thread']['id'];
|
||||
echo $this->Form->create('Post', array('url' => $url));
|
||||
?>
|
||||
<fieldset>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
}
|
||||
foreach ($cluster_fields as $cluster_field):
|
||||
?>
|
||||
<tr>
|
||||
<tr class="cluster_<?php echo h($cluster_field['key']); ?>">
|
||||
<td style="width:25%;vertical-align: text-top; padding-bottom:10px;"><?php echo h(ucfirst($cluster_field['key'])); ?></td>
|
||||
<td style="width:75%; padding-bottom:10px;">
|
||||
<?php
|
||||
|
@ -69,7 +69,11 @@
|
|||
echo nl2br(h(implode("\n", $cluster_field['value'])));
|
||||
}
|
||||
} else {
|
||||
echo h($cluster_field['value']);
|
||||
if ($cluster_field['key'] == 'source' && filter_var($cluster_field['value'], FILTER_VALIDATE_URL)) {
|
||||
echo '<a href="' . h($cluster_field['value']) . '">' . h($cluster_field['value']) . '</a>';;
|
||||
} else {
|
||||
echo h($cluster_field['value']);
|
||||
}
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
<div style="border:1px solid #dddddd; margin-top:1px; width:95%; padding:10px">
|
||||
<?php
|
||||
if (!$dbEncodingStatus):
|
||||
?>
|
||||
<div style="font-size:12pt;padding-left:3px;width:100%;background-color:red;color:white;font-weight:bold;">Incorrect database encoding setting: Your database connection is currently NOT set to UTF-8. Please make sure to uncomment the 'encoding' => 'utf8' line in <?php echo APP; ?>Config/database.php</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<h3>MISP version</h3>
|
||||
<p>Since version 2.3.14, every version of MISP includes a json file with the current version. This is checked against the latest tag on github, if there is a version mismatch the tool will warn you about it. Make sure that you update MISP regularly.</p>
|
||||
<div style="background-color:#f7f7f9;width:400px;">
|
||||
|
@ -89,7 +96,7 @@
|
|||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
<h3>PHP Settings</h3>
|
||||
<?php
|
||||
$phpcolour = 'green';
|
||||
|
@ -138,26 +145,26 @@
|
|||
endforeach;
|
||||
?>
|
||||
<h4>PHP Extensions</h4>
|
||||
<?php
|
||||
<?php
|
||||
foreach (array('web', 'cli') as $context):
|
||||
?>
|
||||
<div style="background-color:#f7f7f9;width:400px;">
|
||||
<b><?php echo ucfirst(h($context));?></b><br />
|
||||
<?php
|
||||
<?php
|
||||
if (isset($extensions[$context]['extensions'])):
|
||||
foreach ($extensions[$context]['extensions'] as $extension => $status):
|
||||
?>
|
||||
<?php echo h($extension); ?>:.... <span style="color:<?php echo $status ? 'green' : 'red';?>;font-weight:bold;"><?php echo $status ? 'OK' : 'Not loaded'; ?></span>
|
||||
<?php
|
||||
<?php
|
||||
endforeach;
|
||||
else:
|
||||
?>
|
||||
<span class="red">Issues reading PHP settings. This could be due to the test script not being readable.</span>
|
||||
<?php
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</div><br />
|
||||
<?php
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
<h3>
|
||||
|
@ -177,7 +184,7 @@
|
|||
echo 'STIX and CyBox.... <span class="red">Could not read test script (stixtest.py).</span>';
|
||||
$testReadError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$testReadError) {
|
||||
if ($stix['operational'] == 0) {
|
||||
|
@ -299,6 +306,11 @@
|
|||
</div><br />
|
||||
<span class="btn btn-inverse" style="padding-top:1px;padding-bottom:1px;" onClick="checkOrphanedAttributes();">Check for orphaned attributes</span><br /><br />
|
||||
<?php echo $this->Form->postButton('Remove orphaned attributes', $baseurl . '/attributes/pruneOrphanedAttributes', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>
|
||||
<h3>
|
||||
Database cleanup scripts
|
||||
</h3>
|
||||
<p>If you run into an issue with an infinite upgrade loop (when upgrading from version ~2.4.50) that ends up filling your database with upgrade script log messages, run the following script.</p>
|
||||
<?php echo $this->Form->postButton('Prune upgrade logs', $baseurl . '/logs/pruneUpdateLogs', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>
|
||||
<h3>
|
||||
Legacy Administrative Tools
|
||||
</h3>
|
||||
|
|
|
@ -47,13 +47,11 @@
|
|||
<?php endif; ?>
|
||||
<li class="divider"></li>
|
||||
<?php
|
||||
$publishButtons = ' style="display:none;"';
|
||||
$exportButtons = ' style="display:none;"';
|
||||
$publishButtons = ' hidden';
|
||||
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
|
||||
if (isset($event['Event']['published']) && $event['Event']['published']) $exportButtons = "";
|
||||
?>
|
||||
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
|
||||
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
|
||||
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
|
||||
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
|
||||
<?php if (Configure::read('MISP.delegation')):?>
|
||||
<?php if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))): ?>
|
||||
<li id='lidelegateEvent'><a href="#" onClick="delegatePopup('<?php echo h($event['Event']['id']); ?>');">Delegate Publishing</a></li>
|
||||
|
|
|
@ -7,16 +7,20 @@
|
|||
'label' => '<b>MISP XML or JSON file</b>',
|
||||
'type' => 'file',
|
||||
));
|
||||
if (Configure::read('MISP.take_ownership_xml_import')):
|
||||
?>
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
<?php
|
||||
if (Configure::read('MISP.take_ownership_xml_import')):
|
||||
echo $this->Form->input('Event.takeownership', array(
|
||||
'checked' => false,
|
||||
'label' => 'Take ownership of the event',
|
||||
'title' => 'Warning: This will change the creator organisation of the event, tampering with the event\'s ownership and releasability and can lead to unexpected behaviour when synchronising the event with instances that have another creator for the same event.'
|
||||
));
|
||||
endif;
|
||||
echo $this->Form->input('publish', array(
|
||||
'checked' => false,
|
||||
'label' => 'Publish imported events',
|
||||
));
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
|
|
|
@ -198,7 +198,7 @@ foreach ($sigTypes as $sigType) {
|
|||
<p>As of version 2.3.38, it is possible to restrict the text exports on two additional flags. The first allows the user to restrict based on event ID, whilst the second is a boolean switch allowing non IDS flagged attributes to be exported. Additionally, choosing "all" in the type field will return all eligible attributes. </p>
|
||||
<pre>
|
||||
<?php
|
||||
echo $baseurl.'/attributes/text/download/[type]/[tags]/[event_id]/[allowNonIDS]/[from]/[to]/[last]';
|
||||
echo $baseurl.'/attributes/text/download/[type]/[tags]/[event_id]/[allowNonIDS]/[from]/[to]/[last]/[enforceWarninglist]/[allowNotPublished]';
|
||||
?>
|
||||
</pre>
|
||||
<b>type</b>: The attribute type, any valid MISP attribute type is accepted.<br />
|
||||
|
@ -209,6 +209,7 @@ foreach ($sigTypes as $sigType) {
|
|||
<b>to</b>: Events with the date set to a date before the one specified in the to field (format: 2015-02-15). This filter will use the date of the event.<br />
|
||||
<b>last</b>: Events published within the last x amount of time, where x can be defined in days, hours, minutes (for example 5d or 12h or 30m). This filter will use the published timestamp of the event.<br />
|
||||
<b>enforceWarninglist</b>: All attributes that have a hit on a warninglist will be excluded.<br />
|
||||
<b>allowNotPublished</b>: Include not published Events.</b>
|
||||
You can also chain several tag commands together with the '&&' operator. Please be aware the colons (:) cannot be used in the tag search.
|
||||
Use semicolons instead (the search will automatically search for colons instead). For example, to include tag1 and tag2 but exclude tag3 you would use:<br />
|
||||
<pre>
|
||||
|
|
|
@ -197,19 +197,19 @@
|
|||
var options = <?php echo json_encode($optionsRearranged);?>;
|
||||
$(document).ready(function(){
|
||||
popoverStartup();
|
||||
<?php
|
||||
if (!empty($optionsRearranged)):
|
||||
?>
|
||||
$('#changeFrom').change(function(){
|
||||
changeFreetextImportFrom();
|
||||
});
|
||||
$('#changeFrom').trigger('change');
|
||||
<?php
|
||||
if (!empty($optionsRearranged)):
|
||||
?>
|
||||
$('#changeFrom').change(function(){
|
||||
changeFreetextImportFrom();
|
||||
});
|
||||
$('#changeFrom').trigger('change');
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
$('#checkAll').change(function() {
|
||||
$('.idsCheckbox').prop('checked', $('#checkAll').is(':checked'));
|
||||
});
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -15,6 +15,23 @@
|
|||
'placeholder' => 'Name of the content provider',
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
echo $this->Form->input('input_source', array(
|
||||
'label' => 'Input Source',
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
<div id="DeleteLocalFileDiv" class="optionalField">
|
||||
<?php
|
||||
echo $this->Form->input('delete_local_file', array(
|
||||
'label' => 'Remove input after ingestion'
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
echo $this->Form->input('url', array(
|
||||
'div' => 'input clear',
|
||||
'placeholder' => 'URL of the feed',
|
||||
|
@ -173,8 +190,7 @@ $(document).ready(function() {
|
|||
});
|
||||
feedFormUpdate();
|
||||
});
|
||||
|
||||
$("#FeedSourceFormat, #FeedFixedEvent").change(function() {
|
||||
$("#FeedSourceFormat, #FeedFixedEvent, #FeedInputSource").change(function() {
|
||||
feedFormUpdate();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -15,6 +15,23 @@
|
|||
'placeholder' => 'Name of the content provider',
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
echo $this->Form->input('input_source', array(
|
||||
'label' => 'Input Source',
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
<div id="DeleteLocalFileDiv" class="optionalField">
|
||||
<?php
|
||||
echo $this->Form->input('delete_local_file', array(
|
||||
'label' => 'Remove input after ingestion'
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
echo $this->Form->input('url', array(
|
||||
'div' => 'input clear',
|
||||
'placeholder' => 'URL of the feed',
|
||||
|
@ -185,7 +202,7 @@ $(document).ready(function() {
|
|||
feedFormUpdate();
|
||||
});
|
||||
|
||||
$("#FeedSourceFormat, #FeedFixedEvent").change(function() {
|
||||
$("#FeedSourceFormat, #FeedFixedEvent, #FeedInputSource").change(function() {
|
||||
feedFormUpdate();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<th><?php echo $this->Paginator->sort('name');?></th>
|
||||
<th><?php echo $this->Paginator->sort('source_format', 'Feed Format');?></th>
|
||||
<th><?php echo $this->Paginator->sort('provider');?></th>
|
||||
<th><?php echo $this->Paginator->sort('input_source', 'Input');?></th>
|
||||
<th><?php echo $this->Paginator->sort('url');?></th>
|
||||
<th>Target</th>
|
||||
<th>Publish</th>
|
||||
|
@ -73,6 +74,7 @@ foreach ($feeds as $item):
|
|||
</td>
|
||||
<td><?php echo $feed_types[$item['Feed']['source_format']]['name']; ?> </td>
|
||||
<td><?php echo h($item['Feed']['provider']); ?> </td>
|
||||
<td><?php echo h($item['Feed']['input_source']); ?> </td>
|
||||
<td><?php echo h($item['Feed']['url']); ?> </td>
|
||||
<td class="shortish">
|
||||
<?php
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<body>
|
||||
<div id="popover_form" class="ajax_popover_form"></div>
|
||||
<div id="confirmation_box" class="confirmation_box"></div>
|
||||
<div id="screenshot_box" class="screenshot_box"></div>
|
||||
<div id="gray_out" class="gray_out"></div>
|
||||
<div id="container">
|
||||
<?php echo $this->element('global_menu');
|
||||
|
|
|
@ -15,22 +15,37 @@
|
|||
),
|
||||
);
|
||||
if (!in_array($scope, array_keys($texts))) $scope = 'local';
|
||||
$partial = array();
|
||||
foreach($named as $key => $value):
|
||||
if ($key == 'page' || $key == 'viewall'):
|
||||
continue;
|
||||
endif;
|
||||
$partial[] = h($key) . ':' . h($value);
|
||||
endforeach;
|
||||
$viewall_button_text = 'Paginate';
|
||||
if (!$viewall):
|
||||
$viewall_button_text = 'View all';
|
||||
$partial[] = 'viewall:1';
|
||||
endif;
|
||||
?>
|
||||
<h2><?php echo $texts[$scope]['text'] . $texts[$scope]['extra']; ?></h2>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
$this->Paginator->options(array(
|
||||
'update' => '.span12',
|
||||
'evalScripts' => true,
|
||||
'before' => '$(".progress").show()',
|
||||
'complete' => '$(".progress").hide()',
|
||||
));
|
||||
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
<h2><?php echo $texts[$scope]['text'] . $texts[$scope]['extra']; ?></h2>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
$this->Paginator->options(array(
|
||||
'update' => '.span12',
|
||||
'evalScripts' => true,
|
||||
'before' => '$(".progress").show()',
|
||||
'complete' => '$(".progress").hide()',
|
||||
));
|
||||
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
<li class="all">
|
||||
<a href="<?php echo $baseurl . '/organisations/index/' . implode('/', $partial); ?>"><?php echo $viewall_button_text; ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tabMenuFixedContainer" style="display:inline-block;">
|
||||
|
@ -86,10 +101,12 @@ foreach ($orgs as $org): ?>
|
|||
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo h($org['Organisation']['type']); ?></td>
|
||||
<td><?php echo h($org['Organisation']['contacts']); ?></td>
|
||||
<?php if ($isSiteAdmin): ?>
|
||||
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo h($org_creator_ids[$org['Organisation']['created_by']]); ?></td>
|
||||
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'">
|
||||
<?php echo (isset($org['Organisation']['created_by_email'])) ? h($org['Organisation']['created_by_email']) : ' '; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="short <?php echo $org['Organisation']['local'] ? 'green' : 'red';?>" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo $org['Organisation']['local'] ? 'Yes' : 'No';?></td>
|
||||
<td class="short"><?php echo isset($members[$org['Organisation']['id']]) ? $members[$org['Organisation']['id']] : '0';?></td>
|
||||
<td class="short"><?php echo isset($org['Organisation']['user_count']) ? $org['Organisation']['user_count'] : '0';?></td>
|
||||
<td class="short action-links">
|
||||
<?php if ($isSiteAdmin): ?>
|
||||
<a href='/admin/organisations/edit/<?php echo $org['Organisation']['id'];?>' class = "icon-edit" title = "Edit"></a>
|
||||
|
@ -117,6 +134,9 @@ endforeach; ?>
|
|||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
<li class="all">
|
||||
<a href="<?php echo $baseurl . '/organisations/index/' . implode('/', $partial); ?>"><?php echo $viewall_button_text; ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@
|
|||
<dt><?php echo 'Created by'; ?></dt>
|
||||
<dd>
|
||||
<?php
|
||||
if (isset($creator['User']['email'])) {
|
||||
echo h($creator['User']['email']);
|
||||
if (isset($org['Organisation']['created_by_email'])) {
|
||||
echo h($org['Organisation']['created_by_email']);
|
||||
} else {
|
||||
echo "SYSTEM";
|
||||
echo "Unknown";
|
||||
}
|
||||
?>
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@ echo $this->Form->end();
|
|||
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'addRole'));
|
||||
$this->Js->get('#RolePermission')->event('change', 'deactivateActions()');
|
||||
foreach ($permFlags as $k => $flag) {
|
||||
if ($k == 'perm_audit' || $k == 'perm_auth') {
|
||||
continue;
|
||||
}
|
||||
if ($k !== 'perm_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
|
||||
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'editRole'));
|
||||
$this->Js->get('#RolePermission')->event('change', 'deactivateActions()');
|
||||
foreach ($permFlags as $k => $flag) {
|
||||
if ($k == 'perm_audit' || $k == 'perm_auth') {
|
||||
continue;
|
||||
}
|
||||
if ($k !== 'perm_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
|
||||
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
|
||||
}
|
||||
|
|
|
@ -140,10 +140,10 @@ var formInfoValues = {
|
|||
'ServerOrganization' : "The organization having the external server you want to sync with. Example: BE",
|
||||
'ServerAuthkey' : "You can find the authentication key on your profile on the external server.",
|
||||
'ServerPush' : "Allow the upload of events and their attributes.",
|
||||
'ServerPull' : "Allow the download of events and their attributes from the server.",
|
||||
'ServerUnpublishEvent' : 'Unpublish new event (working with Pull event).',
|
||||
'ServerPublishWithoutEmail' : 'Publish new event without email (working with Push event).',
|
||||
'ServerSubmittedCert' : "You can also upload a certificate file if the instance you are trying to connect to has its own signing authority.",
|
||||
'ServerPull' : "Allow the download of events and their attributes from the server.",
|
||||
'ServerUnpublishEvent' : 'Unpublish new event (working with Pull event).',
|
||||
'ServerPublishWithoutEmail' : 'Publish new event without email (working with Push event).',
|
||||
'ServerSubmittedCert' : "You can also upload a certificate file if the instance you are trying to connect to has its own signing authority. (*.pem)",
|
||||
'ServerSelfSigned' : "Click this, if you would like to allow a connection despite the other instance using a self-signed certificate (not recommended)."
|
||||
};
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
?>
|
||||
<div class="clear">
|
||||
<p>
|
||||
<span class="bold">Server certificate file: </span>
|
||||
<span class="bold">Server certificate file (*.pem): </span>
|
||||
<span id="serverEditCertValue">
|
||||
<?php
|
||||
if (isset($server['Server']['cert_file']) && !empty($server['Server']['cert_file'])) echo h($server['Server']['cert_file']);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
</div>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<th><?php echo $this->Paginator->sort('name');?></th>
|
||||
<th>Connection test</th>
|
||||
<th><?php echo $this->Paginator->sort('internal');?></th>
|
||||
|
@ -59,6 +60,7 @@ foreach ($servers as $server):
|
|||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class="short"><?php echo h($server['Server']['id']); ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if (!empty($server['Server']['name'])) echo h($server['Server']['name']);
|
||||
|
|
|
@ -145,6 +145,9 @@
|
|||
<th><?php echo $this->Paginator->sort('category');?></th>
|
||||
<th><?php echo $this->Paginator->sort('type');?></th>
|
||||
<th><?php echo $this->Paginator->sort('value');?></th>
|
||||
<?php if (Configure::read('MISP.attribute_tagging')): ?>
|
||||
<th>Tags</th>
|
||||
<?php endif; ?>
|
||||
<th><?php echo $this->Paginator->sort('comment');?></th>
|
||||
<th>Related Events</th>
|
||||
<th title="<?php echo $attrDescriptions['signature']['desc'];?>"><?php echo $this->Paginator->sort('to_ids', 'IDS');?></th>
|
||||
|
@ -177,6 +180,15 @@
|
|||
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['category']); ?></td>
|
||||
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['type']); ?></td>
|
||||
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['value']); ?></td>
|
||||
<?php if (Configure::read('MISP.attribute_tagging')): ?>
|
||||
<td class="shortish <?php echo $extra; ?>">
|
||||
<?php if (!empty($object['Tag'])) foreach ($object['Tag'] as $tag): ?>
|
||||
<span class="tag" style="background-color:<?php echo h($tag['colour']); ?>;color:<?php echo $this->TextColour->getTextColour($tag['colour']);?>">
|
||||
<?php echo h($tag['name']); ?>
|
||||
</span>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['comment']); ?></td>
|
||||
<td class="shortish <?php echo $extra; ?>">
|
||||
<ul class="inline" style="margin:0px;">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<textarea class="input-xxlarge" placeholder="A description of the sharing group." cols="30" rows="6" id="SharingGroupDescription"></textarea>
|
||||
<div style="display:block;">
|
||||
<input type="checkbox" style="float:left;" title="Active sharing groups can be selected by users of the local instance when creating events. Generally, sharing groups received through synchronisation will have this disabled until manually enabled." value="1" id="SharingGroupActive" checked></input>
|
||||
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable</label>
|
||||
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable (active)</label>
|
||||
</div>
|
||||
<span class="btn btn-inverse" onClick="simpleTabPage(2);">Next page</span>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<textarea class="input-xxlarge" placeholder="A description of the sharing group." cols="30" rows="6" id="SharingGroupDescription"><?php echo h($sharingGroup['SharingGroup']['description']); ?></textarea>
|
||||
<div style="display:block;">
|
||||
<input type="checkbox" style="float:left;" title="Active sharing groups can be selected by users of the local instance when creating events. Generally, sharing groups received through synchronisation will have this disabled until manually enabled." <?php if ($sharingGroup['SharingGroup']['active']) echo "checked"; ?> id="SharingGroupActive"></input>
|
||||
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable</label>
|
||||
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable (active)</label>
|
||||
</div>
|
||||
<span class="btn btn-inverse" onClick="simpleTabPage(2);">Next page</span>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,12 @@
|
|||
<legend>Select Tag</legend>
|
||||
<div style="display:none;">
|
||||
<?php
|
||||
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $event_id, 'style' => 'margin:0px;'));
|
||||
if (isset($attributeTag)) {
|
||||
echo $this->Form->create('Attribute', array('url' => '/attributes/addTag/' . $object_id, 'style' => 'margin:0px;'));
|
||||
} else {
|
||||
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $object_id, 'style' => 'margin:0px;'));
|
||||
}
|
||||
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
|
||||
echo $this->Form->input('tag', array('value' => 0));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
|
@ -13,15 +18,17 @@
|
|||
<div class="popover_choice_main" id ="popover_choice_main">
|
||||
<table style="width:100%;">
|
||||
<?php foreach ($options as $k => &$option): ?>
|
||||
<tr id="field_<?php echo h($k); ?>" style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitTagForm('<?php echo h($event_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
|
||||
<tr style="border-top:1px solid black;" class="templateChoiceButton" id="field_<?php echo h($k); ?>">
|
||||
<?php if (isset($attributeTag)): ?>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitAttributeTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
|
||||
<?php else: ?>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id);?>', 'tags', 'selectTaxonomy');" title="Select Taxonomy">Back to Taxonomy Selection</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="popover-back useCursorPointer" onClick="getPopup('<?php echo h($object_id); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTaxonomy');" title="Select Taxonomy">Back to Taxonomy Selection</div>
|
||||
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();">Cancel</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
@ -30,7 +37,7 @@
|
|||
resizePopoverBody();
|
||||
$("#filterField").focus();
|
||||
});
|
||||
|
||||
|
||||
$('#filterField').keyup(function() {
|
||||
var filterString = $("#filterField").val().toLowerCase();
|
||||
$.each(tags, function(index, value) {
|
||||
|
@ -41,7 +48,6 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
resizePopoverBody();
|
||||
});
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
<table style="width:100%;">
|
||||
<?php if ($favourites): ?>
|
||||
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/favourites', 'tags', 'selectTag');">Favourite Tags</td>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/favourites<?php if (isset($attributeTag)) echo '/true' ?>', 'tags', 'selectTag');">Favourite Tags</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/0', 'tags', 'selectTag');">Custom Tags</td>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/0<?php if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">Custom Tags</td>
|
||||
</tr>
|
||||
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/all', 'tags', 'selectTag');">All Tags</td>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/all<?php if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">All Tags</td>
|
||||
</tr>
|
||||
<?php foreach ($options as $k => &$option): ?>
|
||||
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/<?php echo h($k);?>', 'tags', 'selectTag');">Taxonomy Library: <?php echo h($option); ?></td>
|
||||
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/<?php echo h($k); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">Taxonomy Library: <?php echo h($option); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<th>Restricted to</th>
|
||||
<th>Taxonomy</th>
|
||||
<th>Tagged events</th>
|
||||
<th>Tagged attributes</th>
|
||||
<th>Favourite</th>
|
||||
<?php if ($isAclTagEditor): ?>
|
||||
<th class="actions"><?php echo __('Actions');?></th>
|
||||
|
@ -59,6 +60,7 @@ foreach ($list as $item): ?>
|
|||
|
||||
</td>
|
||||
<td class="shortish"><?php echo h($item['Tag']['count']); ?> </td>
|
||||
<td class="shortish"><a href="<?php echo $baseurl . "/attributes/search/attributetag:" . $item['Tag']['id']; ?>"><?php echo h($item['Tag']['attribute_count']); ?></a> </td>
|
||||
<td class="short" id ="checkbox_row_<?php echo h($item['Tag']['id']);?>">
|
||||
<input id="checkBox_<?php echo h($item['Tag']['id']); ?>" type="checkbox" onClick="toggleSetting(event, 'favourite_tag', '<?php echo h($item['Tag']['id']); ?>')" <?php echo $item['Tag']['favourite'] ? 'checked' : ''; ?>/>
|
||||
</td>
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<th><?php echo $this->Paginator->sort('tag');?></th>
|
||||
<th><?php echo $this->Paginator->sort('expanded');?></th>
|
||||
<th><?php echo $this->Paginator->sort('events');?></th>
|
||||
<th><?php echo $this->Paginator->sort('attributes');?></th>
|
||||
<th><?php echo $this->Paginator->sort('tag');?></th>
|
||||
<th>Action</th>
|
||||
</tr><?php
|
||||
|
@ -97,6 +98,17 @@
|
|||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php
|
||||
if ($item['existing_tag']):
|
||||
?>
|
||||
<a href='<?php echo $baseurl."/attributes/search/attributetag:". h($item['existing_tag']['Tag']['id']);?>'><?php echo count($item['existing_tag']['AttributeTag']);?></a>
|
||||
<?php
|
||||
else:
|
||||
echo 'N/A';
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php
|
||||
if ($item['existing_tag']):
|
||||
$url = $baseurl . '/events/index/searchtag:' . h($item['existing_tag']['Tag']['id']);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="threads view">
|
||||
<h3><?php
|
||||
if (isset($event_id)) {
|
||||
echo '<a href="' . $baseurl . '/events/view/' . $event_id . '">' . h($thread_title) . '</a>';
|
||||
echo '<a href="' . $baseurl . '/events/view/' . $event_id . '">' . h($thread['Thread']['title']) . '</a>';
|
||||
} else {
|
||||
echo h($thread_title);
|
||||
echo h($thread['Thread']['title']);
|
||||
}
|
||||
?></h3>
|
||||
<?php
|
||||
|
|
|
@ -68,13 +68,13 @@
|
|||
<div class="clear"><span onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;">Fetch GPG key</span></div>
|
||||
<?php
|
||||
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => 'SMIME key', 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => 'Paste the user\'s SMIME public key in PEM format here.'));
|
||||
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox'));
|
||||
echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests', 'type' => 'checkbox'));
|
||||
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox', 'checked' => true));
|
||||
echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests', 'type' => 'checkbox', 'checked' => true));
|
||||
?>
|
||||
<div class="clear"></div>
|
||||
<?php
|
||||
echo $this->Form->input('disabled', array('label' => 'Disable this user account'));
|
||||
|
||||
echo $this->Form->input('notify', array('label' => 'Send credentials automatically', 'type' => 'checkbox', 'checked' => true));
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="events">
|
||||
<?php echo $this->Form->create('User');?>
|
||||
<fieldset>
|
||||
<legend>Filter Event Index</legend>
|
||||
<legend>Filter User Index</legend>
|
||||
<div class="overlay_spacing">
|
||||
<?php
|
||||
echo $this->Form->input('rule', array(
|
||||
|
|
|
@ -103,7 +103,7 @@ if (h($user['User']['change_pw']) == 1) {
|
|||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$.ajax({
|
||||
url: '<?php echo $baseurl . "/events/index/searchemail:" . h($user['User']['email']); ?>',
|
||||
url: '<?php echo $baseurl . "/events/index/searchemail:" . urlencode(h($user['User']['email'])); ?>',
|
||||
type:'GET',
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loading").show();
|
||||
|
|
|
@ -5,38 +5,38 @@
|
|||
?>
|
||||
<div class = "index">
|
||||
<h2>Statistics</h2>
|
||||
<?php
|
||||
<?php
|
||||
echo $this->element('Users/statisticsMenu');
|
||||
?>
|
||||
<p>Some statistics about this instance. The changes since the beginning of this month are noted in brackets wherever applicable</p>
|
||||
<div style="width:250px;">
|
||||
<dl>
|
||||
<dt>Events</dt>
|
||||
<dd><?php echo h($stats[0]);
|
||||
if ($stats[1]) echo ' <span style="color:green">(+' . h($stats[1]) . ')</span> ';
|
||||
<dd><?php echo h($stats['event_count']);
|
||||
if ($stats['event_count_month']) echo ' <span style="color:green">(+' . h($stats['event_count_month']) . ')</span> ';
|
||||
else echo ' <span style="color:red">(0)</span> ';?>
|
||||
</dd>
|
||||
<dt><?php echo 'Attributes'; ?></dt>
|
||||
<dd><?php echo h($stats[2]);
|
||||
if ($stats[1]) echo ' <span style="color:green">(+' . h($stats[3]) . ')</span> ';
|
||||
<dd><?php echo h($stats['attribute_count']);
|
||||
if ($stats['event_count_month']) echo ' <span style="color:green">(+' . h($stats['attribute_count_month']) . ')</span> ';
|
||||
else echo ' <span style="color:red">(0)</span> ';?>
|
||||
</dd>
|
||||
<dt><?php echo 'Correlations found'; ?></dt>
|
||||
<dd><?php echo h($stats[4]); ?> </dd>
|
||||
<dd><?php echo h($stats['correlation_count']); ?> </dd>
|
||||
<dt><?php echo 'Proposals active'; ?></dt>
|
||||
<dd><?php echo h($stats[5]); ?> </dd>
|
||||
<dd><?php echo h($stats['proposal_count']); ?> </dd>
|
||||
<dt><?php echo 'Users'; ?></dt>
|
||||
<dd><?php echo h($stats[6]); ?> </dd>
|
||||
<dd><?php echo h($stats['user_count']); ?> </dd>
|
||||
<dt><?php echo 'Organisations'; ?></dt>
|
||||
<dd><?php echo h($stats[7]); ?> </dd>
|
||||
<dd><?php echo h($stats['org_count']); ?> </dd>
|
||||
<dt><?php echo 'Discussion threads'; ?></dt>
|
||||
<dd><?php echo h($stats[8]);
|
||||
if ($stats[9]) echo ' <span style="color:green">(+' . h($stats[9]) . ')</span> ';
|
||||
<dd><?php echo h($stats['thread_count']);
|
||||
if ($stats['thread_count_month']) echo ' <span style="color:green">(+' . h($stats['thread_count_month']) . ')</span> ';
|
||||
else echo ' <span style="color:red">(0)</span> ';?>
|
||||
</dd>
|
||||
<dt><?php echo 'Discussion posts'; ?></dt>
|
||||
<dd><?php echo h($stats[10]);
|
||||
if ($stats[11]) echo ' <span style="color:green">(+' . h($stats[11]) . ')</span> ';
|
||||
<dd><?php echo h($stats['post_count']);
|
||||
if ($stats['post_count_month']) echo ' <span style="color:green">(+' . h($stats['post_count_month']) . ')</span> ';
|
||||
else echo ' <span style="color:red">(0)</span> ';?>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<div class="whitelist index">
|
||||
<h2>Import Whitelist</h2>
|
||||
<h2>Signature Whitelist</h2>
|
||||
<p>Regex entries (in the standard php regex /{regex}/{modifier} format) entered below will restrict matching attributes from being included in the IDS flag sensitive exports (such as NIDS exports).</p>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<div class="whitelist index">
|
||||
<h2>Signature Whitelist</h2>
|
||||
<p>Regex entries (in the standard php regex /{regex}/{modifier} format) entered below will restrict matching attributes from being included in the IDS flag sensitive exports (such as NIDS exports).</p>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit c38f62ae12eb18a77390727df754aab3894a53ed
|
||||
Subproject commit f3f5b3b3ac4a7e453a2a25adcb0342a0454c1155
|
|
@ -1 +1 @@
|
|||
Subproject commit 0e320249de47f57e48f318709d1179fde4e0ea9c
|
||||
Subproject commit 14cf779bf348adbe29926b2527f0a8d394515fa2
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue