mirror of https://github.com/MISP/MISP
Merge branch 'master' into develop
Conflicts: app/Config/bootstrap.default.phppull/64/merge
commit
2288a18603
|
@ -15,3 +15,5 @@
|
|||
/app/webroot/img/logo.png
|
||||
/app/Config/bootstrap.php
|
||||
/app/Config/database.php
|
||||
/app/Config/core.php
|
||||
/cakephp
|
||||
|
|
|
@ -22,60 +22,141 @@ Security
|
|||
|
||||
|
||||
INSTALLATION INSTRUCTIONS
|
||||
------------------------- for ubuntu 12.04-server
|
||||
|
||||
1/ Minimal ubuntu install
|
||||
-------------------------
|
||||
Install the following libraries:
|
||||
apt-get install zip
|
||||
apt-get install php-pear
|
||||
pear install Crypt_GPG # need version >1.3.0
|
||||
Install a minimal ubuntu 12.04-server system with the software:
|
||||
- OpenSSH server
|
||||
- LAMP server
|
||||
- Mail server
|
||||
|
||||
You will get some questions, you will probably want to set:
|
||||
- Postfix Configuration: Satellite system
|
||||
|
||||
Make sure your system is up2date:
|
||||
apt-get update
|
||||
apt-get upgrade
|
||||
|
||||
|
||||
2/ Dependencies
|
||||
----------------
|
||||
Once the system is installed you can perform the following steps as root:
|
||||
|
||||
# Because vim is just so practical
|
||||
apt-get install vim
|
||||
|
||||
# Install the dependencies:
|
||||
apt-get install zip php-pear git
|
||||
pear install Crypt_GPG # we need version >1.3.0
|
||||
pear install Net_GeoIP
|
||||
# ideally make sure geoip database is updated using crontab
|
||||
#wget 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz'
|
||||
#gunzip GeoIP.dat.gz
|
||||
|
||||
|
||||
3/ CakePHP
|
||||
-----------
|
||||
# Download CakePHP from github
|
||||
cd /opt/
|
||||
git pull https://github.com/cakephp/cakephp.git
|
||||
chmod -R 755 /opt/cakephp
|
||||
git clone https://github.com/cakephp/cakephp.git
|
||||
|
||||
# You should REALLY make sure that you install security updates of CakePHP when your system is in production !
|
||||
|
||||
# Download CyDefSIG using git in the /var/www/ directory.
|
||||
# If you plan to run multiple MISP instances on a single server, only one installation of CakePHP is needed !
|
||||
|
||||
4/ MISP code
|
||||
------------
|
||||
# Download MISP using git in the /var/www/ directory.
|
||||
cd /var/www/
|
||||
git clone https://github.com/BeDefCERT/MISP.git
|
||||
git clone https://github.com/MISP/MISP.git
|
||||
|
||||
# Make git ignore filesystem permission differences
|
||||
cd /var/www/MISP
|
||||
git config core.filemode false
|
||||
|
||||
|
||||
# Check if the permissions are set correctly using the following commands as root:
|
||||
chown -R <user>:www-data /var/www/cydefsig
|
||||
chmod -R 750 /var/www/cydefsig
|
||||
chmod -R g+s /var/www/cydefsig
|
||||
cd /var/www/cydefsig/app/
|
||||
chmod -R g+w tmp
|
||||
chmod -R g+w files
|
||||
chown -R www-data:www-data /var/www/MISP
|
||||
chmod -R 750 /var/www/MISP
|
||||
cd /var/www/MISP/app/
|
||||
chmod -R g+ws tmp
|
||||
chmod -R g+ws files
|
||||
cd /var/www/MISP
|
||||
|
||||
# Import the empty MySQL database from /var/www/cydefsig/app/MYSQL.sql using phpmyadmin or mysql>.
|
||||
##
|
||||
## FIXME this is not really clean
|
||||
##
|
||||
# Currently you will need to copy the plugins to the CakePHP directory.
|
||||
cp -r /var/www/MISP/plugins/* /opt/cakephp/plugins/
|
||||
chmod -R o+rx /opt/cakephp/plugins
|
||||
|
||||
# Now configure your apache server with the DocumentRoot /var/www/cydefsig/app/webroot/
|
||||
5/ Create a database and user
|
||||
-----------------------------
|
||||
# Enter the mysql shell
|
||||
mysql -u root -p
|
||||
|
||||
mysql> create database misp;
|
||||
mysql> grant usage on *.* to misp@localhost identified by 'XXXXXXXXX';
|
||||
mysql> grant all privileges on misp.* to misp@localhost ;
|
||||
mysql> exit
|
||||
|
||||
# Import the empty MySQL database from MYSQL.sql
|
||||
mysql -u misp -p misp < INSTALL/MYSQL.sql
|
||||
|
||||
|
||||
# Configure the fields in the files:
|
||||
6/ Apache configuration
|
||||
-----------------------
|
||||
# Now configure your apache server with the DocumentRoot /var/www/MISP/app/webroot/
|
||||
# A sample ghost can be found in /var/www/MISP/INSTALL/apache.misp
|
||||
|
||||
cp /var/www/MISP/INSTALL/apache.misp /etc/apache2/sites-available/misp
|
||||
a2dissite default
|
||||
a2ensite misp
|
||||
|
||||
# Enable modules
|
||||
a2enmod rewrite
|
||||
|
||||
# Restart apache
|
||||
service apache2 reload
|
||||
|
||||
# We seriously recommend using only SSL !
|
||||
# Check out the apache.misp.ssl file for an example
|
||||
|
||||
|
||||
7/ MISP configuration
|
||||
---------------------
|
||||
# Configure the fields in the files located in /var/www/MISP/app/Config/:
|
||||
database.php : login, port, password, database
|
||||
bootstrap.php: CyDefSIG.*, GnuPG.*
|
||||
core.php : debug,
|
||||
webroot/index.php : CAKE_CORE_INCLUDE_PATH (optional for multi-cydefsig installations)
|
||||
core.php : debug, Security.*
|
||||
|
||||
# and make sure the file permissions are still OK
|
||||
chown -R www-data:www-data /var/www/MISP/app/Config
|
||||
chmod -R 750 /var/www/MISP/app/Config
|
||||
|
||||
|
||||
# Let MISP know where the CakePHP libraries are located by editing the file app/webroot/index.php and setting (on line 59):
|
||||
define('CAKE_CORE_INCLUDE_PATH', '/opt/cakephp/lib');
|
||||
|
||||
|
||||
# Generate a GPG encryption key.
|
||||
mkdir /var/www/cydefsig/.gnupg
|
||||
chown www-data:www-data /var/www/cydefsig/.gnupg
|
||||
chmod 700 /var/www/cydefsig/.gnupg
|
||||
sudo -u www-data gpg --homedir /var/www/cydefsig/.gnupg --gen-key
|
||||
mkdir /var/www/MISP/.gnupg
|
||||
chown www-data:www-data /var/www/MISP/.gnupg
|
||||
chmod 700 /var/www/MISP/.gnupg
|
||||
sudo -u www-data gpg --homedir /var/www/MISP/.gnupg --gen-key
|
||||
# Recommended key type: RSA (sign only)
|
||||
# The email address should match the one set int he bootstrap.php configuration file
|
||||
|
||||
# And export the public key to the webroot
|
||||
sudo -u www-data gpg --homedir .gnupg --export --armor no-reply > app/webroot/gpg.asc
|
||||
sudo -u www-data gpg --homedir /var/www/MISP/.gnupg --export --armor YOUR-EMAIL > /var/www/MISP/app/webroot/gpg.asc
|
||||
|
||||
|
||||
|
||||
# Create the Role Based Access Control (RBAC) tables and content:
|
||||
cd /var/www/cydefsig/app
|
||||
./Console/cake acl create aco root controllers
|
||||
./Console/cake AclExtras.AclExtras aco_sync
|
||||
cd /var/www/MISP/app
|
||||
export PATH="$PATH:/opt/cakephp/lib/Cake/Console"
|
||||
cake acl create aco root controllers
|
||||
cake AclExtras.AclExtras aco_sync
|
||||
# You might get an 'Warning Error: Argument…'
|
||||
# however if it ends with 'Aco Update Complete' it should be OK
|
||||
|
||||
|
||||
Now log in using the webinterface:
|
||||
|
@ -105,15 +186,14 @@ with <your org> being MIL.BE or NCIRC where appropriate.
|
|||
Import the regexp data in /var/www/cydefsig/app/MYSQL.regexp.sql using phpmyadmin or mysql>.
|
||||
|
||||
|
||||
Recommended patches
|
||||
Recommended actions
|
||||
-------------------
|
||||
By default CakePHP exposes his name and version in email headers. Apply a patch to remove this behavior.
|
||||
- By default CakePHP exposes his name and version in email headers. Apply a patch to remove this behavior.
|
||||
|
||||
- You should really harden your OS
|
||||
- You should really harden the configuration of Apache
|
||||
- You should really harden the configuration of MySQL
|
||||
- Keep your software up2date (MISP, CakePHP and everything else)
|
||||
- Log and audit
|
||||
|
||||
Multiple instances on a single server
|
||||
-------------------------------------
|
||||
If you want to install multiple instances on a single server, extract the CakePHP sources
|
||||
in a central location like /opt/cakephp.
|
||||
|
||||
Then edit /var/www/cydefsig/app/webroot/index.php and change :
|
||||
define('CAKE_CORE_INCLUDE_PATH', '/opt/cakephp/lib');
|
||||
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
INSTALLATION INSTRUCTIONS
|
||||
-------------------------
|
||||
If on Ubuntu, besides the DocumentRoot,
|
||||
you have to change the AllowOverride from None to All as well.
|
||||
|
||||
DocumentRoot /var/www/cydefsig/app/webroot/
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
<Directory /var/www/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
Find the original below, for reference.
|
||||
|
||||
DocumentRoot /var/www
|
||||
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
</Directory>
|
||||
<Directory /var/www/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
Now /etc/init.d/apache2 restart
|
||||
and you are done, and now able to use the application.
|
|
@ -1,26 +0,0 @@
|
|||
VIRTUAL HOST INSTRUCTION
|
||||
------------------------
|
||||
|
||||
CyDefSIG is able to run in an Apache virtual host setup.
|
||||
This takes 2 variables, the hostname and CyDefSIG directory.
|
||||
To this one must enter the hostname in /etc/hosts
|
||||
and create an Apache config in apache2/sites-available.
|
||||
|
||||
Say we have a hostname cydefsig2.local.net and
|
||||
CyDefSIG installed in /var/www/second_instance/cydefsig,
|
||||
we will add to /etc/hosts:
|
||||
|
||||
127.0.1.1 cydefsig2.local.net
|
||||
|
||||
And create a file /etc/apache2/sites-available/<second_instance_name>
|
||||
containing:
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@example.com
|
||||
ServerName cydefsig2.local.net
|
||||
ServerAlias mysite
|
||||
|
||||
# Indexes + Directory Root.
|
||||
DirectoryIndex index.php
|
||||
DocumentRoot /var/www/second_instance/cydefsig/app/webroot
|
||||
</VirtualHost>
|
|
@ -0,0 +1,16 @@
|
|||
<VirtualHost *:80>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes FollowSymLinks
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
|
@ -0,0 +1,21 @@
|
|||
<VirtualHost 192.168.1.1:443>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes FollowSymLinks
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
|
@ -119,7 +119,7 @@ Configure::write('CyDefSIG.logo', 'orgs/ORGNAME.png'); // used in Events::in
|
|||
|
||||
|
||||
Configure::write('CyDefSIG.showorg', 'true'); // show the name/flag of the organisation that uploaded the data
|
||||
Configure::write('CyDefSIG.showowner', 'false'); // show the email of the owner that uploaded the data
|
||||
|
||||
Configure::write('CyDefSIG.sync', 'true'); // enable features related to syncing with other CyDefSIG instances - should be always on because of the current distribution model.
|
||||
Configure::write('CyDefSIG.private', 'true'); // respect private to org or server.
|
||||
if ('true' == Configure::read('CyDefSIG.private')) {
|
||||
|
@ -136,11 +136,6 @@ Configure::write('GnuPG.homedir', '/path/to/your/.gnupg/');
|
|||
Configure::write('SecureAuth.amount', 5); // the maximum amount of failed logins
|
||||
Configure::write('SecureAuth.expire', 300); // the time-window for the maximum amount of logins in seconds
|
||||
|
||||
Configure::write('CyDefSIG.correlation', 'db'); // correlation between attributes of events.
|
||||
// possible values:
|
||||
// - default, like it was (this is depreciated, use 'db' instead)
|
||||
// - db, correlation in database
|
||||
// - sql, selection on event i.s.o. per attribute (improvement possible) (this is depreciated, use 'db' instead)
|
||||
/**
|
||||
* Network activity, ip-src
|
||||
* 30 class-C network ip addresses
|
||||
|
@ -246,3 +241,4 @@ CakeLog::config('error', array(
|
|||
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
||||
'file' => 'error',
|
||||
));
|
||||
|
||||
|
|
|
@ -936,142 +936,6 @@ class AttributesController extends AppController {
|
|||
$this->render('xml');
|
||||
}
|
||||
|
||||
/**
|
||||
* event method (bluntly copied from EventsController.view()
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws NotFoundException // TODO Exception
|
||||
*/
|
||||
public function event($id = null) {
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
|
||||
// search the db
|
||||
$conditions = array();
|
||||
if (isset($this->params['named']['event'])) {
|
||||
$attributeId = $this->params['named']['event'];
|
||||
} else {
|
||||
$attributeId = $id;
|
||||
}
|
||||
$conditions['Attribute.event_id ='] = $attributeId;
|
||||
|
||||
$this->paginate = array(
|
||||
'order' => array('Attribute.category_order' => 'asc', 'Attribute.type' => 'asc'),
|
||||
'limit' => 60,
|
||||
'conditions' => $conditions
|
||||
);
|
||||
$this->set('attributes', Sanitize::clean($this->paginate()));
|
||||
|
||||
// the parent event..
|
||||
$event = ClassRegistry::init('Event')->findById($attributeId);
|
||||
$this->set('event', Sanitize::clean($event));
|
||||
$this->loadModel('Event');
|
||||
$this->set('eventDescriptions', $this->Event->fieldDescriptions);
|
||||
|
||||
// get related
|
||||
$relatedAttributes = array();
|
||||
$this->loadModel('Attribute');
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
$this->loadModel('Correlation');
|
||||
$fields = array('Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$fields2 = array('Correlation.1_attribute_id','Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$relatedAttributes2 = array();
|
||||
$relatedAttributes2 = $this->Correlation->find('all',array(
|
||||
'fields' => $fields2,
|
||||
'conditions' => array(
|
||||
'OR' => array(
|
||||
'Correlation.1_event_id' => $id
|
||||
)
|
||||
),
|
||||
'recursive' => 0));
|
||||
foreach ($relatedAttributes2 as $relatedAttribute2) {
|
||||
$relatedAttributes[$relatedAttribute2['Correlation']['1_attribute_id']][] = $relatedAttribute2;
|
||||
}
|
||||
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encodedFile;
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEventDates = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Correlation']['event_id'];
|
||||
$relatedEventsDates[$item['Correlation']['event_id']] = $item['Correlation']['date'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($relatedEventsDates)) {
|
||||
arsort($relatedEventsDates);
|
||||
$relatedEventsDates = array_unique($relatedEventsDates);
|
||||
foreach ($relatedEventsDates as $key => $relatedEventsDate) {
|
||||
$relatedEvents[] = array('id' => $key, 'date' => $relatedEventsDate);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
$double = $this->Attribute->doubleAttributes();
|
||||
}
|
||||
foreach ($event['Attribute'] as &$attribute) {
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
if (in_array($attribute['value1'],$double) || in_array($attribute['value2'],$double)) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = array();
|
||||
}
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
}
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encodedFile;
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
}
|
||||
}
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$findParams = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $findParams);
|
||||
}
|
||||
}
|
||||
$this->set('correlation', Configure::read('CyDefSIG.correlation'));
|
||||
$this->set('relatedAttributes', $relatedAttributes);
|
||||
|
||||
$this->set('relatedEvents', $relatedEvents);
|
||||
|
||||
$this->set('categories', $this->Attribute->validate['category']['rule'][1]);
|
||||
}
|
||||
|
||||
public function checkComposites() {
|
||||
if (!self::_isAdmin()) throw new NotFoundException();
|
||||
|
||||
|
|
|
@ -181,129 +181,84 @@ class EventsController extends AppController {
|
|||
$relatedAttributes = array();
|
||||
$this->loadModel('Attribute');
|
||||
$this->loadModel('Event');
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
$this->loadModel('Correlation');
|
||||
$fields = array('Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$fields2 = array('Correlation.1_attribute_id','Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date', 'Correlation.private', 'Correlation.org');
|
||||
$relatedAttributes2 = array();
|
||||
if (('true' == Configure::read('CyDefSIG.private')) && ('ADMIN' != $this->Auth->user('org'))) {
|
||||
$conditionsCorrelation =
|
||||
array('AND' => array('Correlation.1_event_id' => $id),
|
||||
array("OR" => array('Correlation.org =' => $this->Auth->user('org'), 'Correlation.private !=' => 1,
|
||||
'AND' => array('Correlation.private =' => 1,'Correlation.cluster =' => 1)),
|
||||
));
|
||||
} else {
|
||||
$conditionsCorrelation =
|
||||
array('AND' => array('Correlation.1_event_id' => $id,));
|
||||
}
|
||||
$relatedAttributes2 = $this->Correlation->find('all',array(
|
||||
'fields' => $fields2,
|
||||
'conditions' => $conditionsCorrelation,
|
||||
'recursive' => 0, 'order' => array('Correlation.event_id DESC')));
|
||||
|
||||
if (empty($relatedAttributes2)) {
|
||||
$relatedEvents = null;
|
||||
} else {
|
||||
foreach ($relatedAttributes2 as $relatedAttribute2) {
|
||||
$helpArray = array();
|
||||
if (!isset($helpArray[$relatedAttribute2['Correlation']['1_attribute_id']]) || !in_array($relatedAttribute2['Correlation']['event_id'], $helpArray[$relatedAttribute2['Correlation']['1_attribute_id']])) {
|
||||
$helpArray[$relatedAttribute2['Correlation']['1_attribute_id']][] = $relatedAttribute2['Correlation']['event_id'];
|
||||
$relatedAttributes[$relatedAttribute2['Correlation']['1_attribute_id']][] = array('Attribute' => $relatedAttribute2['Correlation']);
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEventDates = array();
|
||||
$relatedEventInfos = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
$relatedEventsDates[$item['Attribute']['event_id']] = $item['Attribute']['date'];
|
||||
$temp = $this->Event->find('first', array(
|
||||
'conditions' => array('Event.id' => $item['Attribute']['event_id']),
|
||||
'fields' => array('info', 'orgc'),
|
||||
'recursive' => 0,
|
||||
));
|
||||
$item['Attribute']['event_info'] = $temp['Event']['info'];
|
||||
$item['Attribute']['relatedOrg'] = $temp['Event']['orgc'];
|
||||
$relatedEventInfos[$item['Attribute']['event_id']] = $temp['Event']['info'];
|
||||
$relatedEventOrgs[$item['Attribute']['event_id']] = $temp['Event']['orgc'];
|
||||
}
|
||||
}
|
||||
if (isset($relatedEventsDates)) {
|
||||
foreach ($relatedEventsDates as $key => $relatedEventsDate) {
|
||||
$relatedEvents[] = array('Event' => array('id' => $key, 'date' => $relatedEventsDate));
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($relatedEventInfos as $info) {
|
||||
$relatedEvents[$i]['Event']['info'] = $info;
|
||||
$i++;
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($relatedEventOrgs as $org) {
|
||||
$relatedEvents[$i]['Event']['org'] = $org;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
usort($relatedEvents, array($this, 'compareRelatedEvents'));
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encodedFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->loadModel('Correlation');
|
||||
$fields = array('Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date');
|
||||
$fields2 = array('Correlation.1_attribute_id','Correlation.event_id', 'Correlation.attribute_id', 'Correlation.date', 'Correlation.private', 'Correlation.org');
|
||||
$relatedAttributes2 = array();
|
||||
if (('true' == Configure::read('CyDefSIG.private')) && ('ADMIN' != $this->Auth->user('org'))) {
|
||||
$conditionsCorrelation =
|
||||
array('AND' => array('Correlation.1_event_id' => $id),
|
||||
array("OR" => array('Correlation.org =' => $this->Auth->user('org'), 'Correlation.private !=' => 1,
|
||||
'AND' => array('Correlation.private =' => 1,'Correlation.cluster =' => 1)),
|
||||
));
|
||||
} else {
|
||||
$fields = array('Attribute.id', 'Attribute.event_id', 'Attribute.uuid');
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
$double = $this->Attribute->doubleAttributes();
|
||||
}
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
if ('sql' == Configure::read('CyDefSIG.correlation')) {
|
||||
if (in_array($attribute['value1'],$double) || in_array($attribute['value2'],$double)) {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = array();
|
||||
}
|
||||
} else {
|
||||
$relatedAttributes[$attribute['id']] = $this->Attribute->getRelatedAttributes($attribute, $fields);
|
||||
}
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->_isRest() && $this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encodedFile;
|
||||
$conditionsCorrelation =
|
||||
array('AND' => array('Correlation.1_event_id' => $id,));
|
||||
}
|
||||
$relatedAttributes2 = $this->Correlation->find('all',array(
|
||||
'fields' => $fields2,
|
||||
'conditions' => $conditionsCorrelation,
|
||||
'recursive' => 0, 'order' => array('Correlation.event_id DESC')));
|
||||
|
||||
if (empty($relatedAttributes2)) {
|
||||
$relatedEvents = null;
|
||||
} else {
|
||||
foreach ($relatedAttributes2 as $relatedAttribute2) {
|
||||
$helpArray = array();
|
||||
if (!isset($helpArray[$relatedAttribute2['Correlation']['1_attribute_id']]) || !in_array($relatedAttribute2['Correlation']['event_id'], $helpArray[$relatedAttribute2['Correlation']['1_attribute_id']])) {
|
||||
$helpArray[$relatedAttribute2['Correlation']['1_attribute_id']][] = $relatedAttribute2['Correlation']['event_id'];
|
||||
$relatedAttributes[$relatedAttribute2['Correlation']['1_attribute_id']][] = array('Attribute' => $relatedAttribute2['Correlation']);
|
||||
}
|
||||
}
|
||||
|
||||
// search for related Events using the results form the related attributes
|
||||
// This is a lot faster (only additional query) than $this->Event->getRelatedEvents()
|
||||
$relatedEventIds = array();
|
||||
$relatedEventDates = array();
|
||||
$relatedEventInfos = array();
|
||||
$relatedEvents = array();
|
||||
foreach ($relatedAttributes as &$relatedAttribute) {
|
||||
if (null == $relatedAttribute) continue;
|
||||
foreach ($relatedAttribute as &$item) {
|
||||
$relatedEventsIds[] = $item['Attribute']['event_id'];
|
||||
$relatedEventsDates[$item['Attribute']['event_id']] = $item['Attribute']['date'];
|
||||
$temp = $this->Event->find('first', array(
|
||||
'conditions' => array('Event.id' => $item['Attribute']['event_id']),
|
||||
'fields' => array('info', 'orgc'),
|
||||
'recursive' => 0,
|
||||
));
|
||||
$item['Attribute']['event_info'] = $temp['Event']['info'];
|
||||
$item['Attribute']['relatedOrg'] = $temp['Event']['orgc'];
|
||||
$relatedEventInfos[$item['Attribute']['event_id']] = $temp['Event']['info'];
|
||||
$relatedEventOrgs[$item['Attribute']['event_id']] = $temp['Event']['orgc'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($relatedEventsIds)) {
|
||||
$relatedEventsIds = array_unique($relatedEventsIds);
|
||||
$findParams = array(
|
||||
'conditions' => array('OR' => array('Event.id' => $relatedEventsIds)), //array of conditions
|
||||
'recursive' => 0, //int
|
||||
'fields' => array('Event.id', 'Event.date', 'Event.uuid', 'Event.info', 'Event.orgc'), //array of field names
|
||||
'order' => array('Event.date DESC'), //string or array defining order
|
||||
);
|
||||
$relatedEvents = $this->Event->find('all', $findParams);
|
||||
if (isset($relatedEventsDates)) {
|
||||
foreach ($relatedEventsDates as $key => $relatedEventsDate) {
|
||||
$relatedEvents[] = array('Event' => array('id' => $key, 'date' => $relatedEventsDate));
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($relatedEventInfos as $info) {
|
||||
$relatedEvents[$i]['Event']['info'] = $info;
|
||||
$i++;
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($relatedEventOrgs as $org) {
|
||||
$relatedEvents[$i]['Event']['org'] = $org;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
usort($relatedEvents, array($this, 'compareRelatedEvents'));
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
foreach ($this->Event->data['Attribute'] as &$attribute) {
|
||||
// for REST requests also add the encoded attachment
|
||||
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
|
||||
// LATER check if this has a serious performance impact on XML conversion and memory usage
|
||||
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
|
||||
$attribute['data'] = $encodedFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1045,7 +1000,7 @@ class EventsController extends AppController {
|
|||
|
||||
$bodyEncSig = $gpg->encrypt($bodySigned, true);
|
||||
|
||||
$this->set('body', Sanitize::clean($bodyEncSig));
|
||||
$this->set('body', $bodyEncSig);
|
||||
$this->Email->send();
|
||||
} catch (Exception $e){
|
||||
// catch errors like expired PGP keys
|
||||
|
|
|
@ -389,15 +389,13 @@ class Attribute extends AppModel {
|
|||
}
|
||||
|
||||
public function afterSave($created) {
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
// update correlation..
|
||||
$this->__afterSaveCorrelation($this->data['Attribute']);
|
||||
}
|
||||
// update correlation..
|
||||
$this->__afterSaveCorrelation($this->data['Attribute']);
|
||||
|
||||
$result = true;
|
||||
// if the 'data' field is set on the $this->data then save the data to the correct file
|
||||
if (isset($this->data['Attribute']['type']) && $this->typeIsAttachment($this->data['Attribute']['type']) && !empty($this->data['Attribute']['data'])) {
|
||||
$result = $result && $this->saveBase64EncodedAttachment($this->data['Attribute']);
|
||||
$result = $result && $this->saveBase64EncodedAttachment($this->data['Attribute']); // TODO : is this correct?
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -417,10 +415,9 @@ class Attribute extends AppModel {
|
|||
}
|
||||
}
|
||||
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) {
|
||||
// update correlation..
|
||||
$this->__beforeDeleteCorrelation($this->data['Attribute']['id']);
|
||||
}
|
||||
// update correlation..
|
||||
$this->__beforeDeleteCorrelation($this->data['Attribute']['id']);
|
||||
|
||||
}
|
||||
|
||||
public function massageData(&$data) {
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
<div class="event view"><!-- bluntly copied from View/Events/view.ctp -->
|
||||
<div class="actions" style="float:right;"><?php
|
||||
if ( 0 == $event['Event']['published'] && ($isAdmin || $event['Event']['org'] == $me['org'])):
|
||||
// only show button if alert has not been sent // LATER show the ALERT button in red-ish
|
||||
?>
|
||||
<ul><li><?php
|
||||
echo $this->Form->postLink('Publish Event', array('controller' => 'events', 'action' => 'alert', $event['Event']['id']), null, 'Are you sure this event is complete and everyone should be informed?');
|
||||
echo $this->Form->postLink('Publish (no email)', array('controller' => 'events', 'action' => 'publish', $event['Event']['id']), null, 'Publish but do NOT send alert email? Only for minor changes!');
|
||||
?> </li></ul><?php
|
||||
elseif (0 == $event['Event']['published']): ?>
|
||||
<ul><li>Not published</li></ul><?php
|
||||
else: ?>
|
||||
<!-- ul><li>Alert already sent</li></ul --><?php
|
||||
endif; ?>
|
||||
<ul><li><?php echo $this->Html->link(__('Contact reporter', true), array('controller' => 'events', 'action' => 'contact', $event['Event']['id'])); ?> </li></ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2>Event</h2>
|
||||
<dl>
|
||||
<dt>ID</dt>
|
||||
<dd>
|
||||
<?php echo h($event['Event']['id']); ?>
|
||||
|
||||
</dd><?php
|
||||
if ('true' == Configure::read('CyDefSIG.showorg') || $isAdmin): ?>
|
||||
<dt>Org</dt>
|
||||
<dd>
|
||||
<?php echo h($event['Event']['org']); ?>
|
||||
|
||||
</dd>
|
||||
<dt>Email</dt>
|
||||
<dd>
|
||||
<?php echo h($event['User']['email']); ?>
|
||||
|
||||
</dd><?php
|
||||
endif; ?>
|
||||
<dt>Date</dt>
|
||||
<dd>
|
||||
<?php echo h($event['Event']['date']); ?>
|
||||
|
||||
</dd>
|
||||
<dt<?php echo ' title="' . $eventDescriptions['risk']['desc'] . '"';?>>Risk</dt>
|
||||
<dd>
|
||||
<?php echo $event['Event']['risk']; ?>
|
||||
|
||||
</dd><?php
|
||||
if ('true' == Configure::read('CyDefSIG.sync')): ?>
|
||||
<dt>Distribution</dt>
|
||||
<dd>
|
||||
<?php echo ($event['Event']['private'])? 'Yes, never upload Event or any Attributes.' : 'No, upload Event and all Attributes except those marked as Private.'; ?>
|
||||
|
||||
</dd><?php
|
||||
endif; ?>
|
||||
<!-- dt>UUID</dt>
|
||||
<dd>
|
||||
<?php echo $event['Event']['uuid']; ?>
|
||||
|
||||
</dd -->
|
||||
<dt>Info</dt>
|
||||
<dd>
|
||||
<?php echo nl2br(h($event['Event']['info'])); ?>
|
||||
|
||||
</dd>
|
||||
</dl><?php
|
||||
if (!empty($relatedEvents)):?>
|
||||
<div class="related">
|
||||
<h3>Related Events</h3>
|
||||
<ul><?php
|
||||
foreach ($relatedEvents as $relatedEvent): ?>
|
||||
<li><?php
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) { // TODO array key
|
||||
$linkText = $relatedEvent['date'] . ' (' . $relatedEvent['id'] . ')';
|
||||
echo $this->Html->link($linkText, array('controller' => 'attributes', 'action' => 'event', $relatedEvent['id']));
|
||||
} else {
|
||||
$linkText = $relatedEvent['Event']['date'] . ' (' . $relatedEvent['Event']['id'] . ')';
|
||||
echo $this->Html->link($linkText, array('controller' => 'attributes', 'action' => 'event', $relatedEvent['Event']['id']));
|
||||
}?></li><?php
|
||||
endforeach; ?>
|
||||
</ul>
|
||||
</div><?php
|
||||
endif; ?>
|
||||
|
||||
<div class="related">
|
||||
<h3>Attributes</h3><?php
|
||||
if (!empty($event['Attribute'])):?>
|
||||
<table cellpadding = "0" cellspacing = "0">
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Type</th>
|
||||
<th>Value</th>
|
||||
<th>Related Events</th>
|
||||
<th <?php echo "title='" . $attrDescriptions['signature']['desc'] . "'";?>>IDS Signature</th><?php
|
||||
if ('true' == Configure::read('CyDefSIG.sync')): ?>
|
||||
<th <?php echo "title='" . $attrDescriptions['private']['desc'] . "'";?>>Private</th><?php
|
||||
endif;?><?php
|
||||
if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<th class="actions">Actions</th><?php
|
||||
endif;?>
|
||||
</tr><?php
|
||||
foreach ($categories as $category):
|
||||
$first = 1;
|
||||
foreach ($attributes as $attribute):
|
||||
if ($attribute['Attribute']['category'] != $category) continue;?>
|
||||
<tr>
|
||||
<td class="short" title="<?php if ('' != $attribute['Attribute']['category']) echo $categoryDefinitions[$attribute['Attribute']['category']]['desc'];?>"><?php
|
||||
if ($first) {
|
||||
if ('' == $attribute['Attribute']['category']) echo '(no category)';
|
||||
echo $attribute['Attribute']['category'];
|
||||
} else {
|
||||
echo ' ';
|
||||
}?></td>
|
||||
<td class="short" title="<?php echo $typeDefinitions[$attribute['Attribute']['type']]['desc'];?>">
|
||||
<?php echo $attribute['Attribute']['type'];?></td>
|
||||
<td><?php
|
||||
$sigDisplay = nl2br(h($attribute['Attribute']['value']));
|
||||
if ('attachment' == $attribute['Attribute']['type'] ||
|
||||
'malware-sample' == $attribute['Attribute']['type'] ) {
|
||||
$filenameHash = explode('|', h($attribute['Attribute']['value']));
|
||||
echo $this->Html->link($filenameHash[0], array('controller' => 'attributes', 'action' => 'download', $attribute['Attribute']['id']));
|
||||
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
|
||||
} elseif (strpos($attribute['Attribute']['type'], '|') !== false) {
|
||||
$filenameHash = explode('|', h($attribute['Attribute']['value']));
|
||||
echo $filenameHash[0];
|
||||
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
|
||||
} elseif ('vulnerability' == $attribute['Attribute']['type']) {
|
||||
echo $this->Html->link($sigDisplay, 'http://www.google.com/search?q=' . $sigDisplay, array('target' => '_blank'));
|
||||
} elseif ('link' == $attribute['Attribute']['type']) {
|
||||
echo $this->Html->link($sigDisplay, $sigDisplay);
|
||||
} else {
|
||||
echo $sigDisplay;
|
||||
}?></td>
|
||||
<td class="short" style="text-align: center;"><?php
|
||||
$first = 0;
|
||||
if (isset($relatedAttributes[$attribute['Attribute']['id']]) && (null != $relatedAttributes[$attribute['Attribute']['id']])) {
|
||||
foreach ($relatedAttributes[$attribute['Attribute']['id']] as $relatedAttribute) {
|
||||
if ('db' == Configure::read('CyDefSIG.correlation')) { // TODO array key
|
||||
echo $this->Html->link($relatedAttribute['Correlation']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Correlation']['event_id']));
|
||||
} else {
|
||||
echo $this->Html->link($relatedAttribute['Attribute']['event_id'], array('controller' => 'events', 'action' => 'view', $relatedAttribute['Attribute']['event_id']));
|
||||
}
|
||||
echo ' ';
|
||||
}
|
||||
}?>
|
||||
</td>
|
||||
<td class="short" style="text-align: center;"><?php echo $attribute['Attribute']['to_ids'] ? 'Yes' : 'No';?></td><?php
|
||||
if ('true' == Configure::read('CyDefSIG.sync')): ?>
|
||||
<td class="short" style="text-align: center;"><?php echo $attribute['Attribute']['private'] ? 'Private' : ' ';?></td><?php
|
||||
endif;?><?php
|
||||
if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<td class="actions">
|
||||
<?php
|
||||
echo $this->Html->link(__('Edit', true), array('controller' => 'attributes', 'action' => 'edit', $attribute['Attribute']['id']));
|
||||
echo $this->Form->postLink(__('Delete'), array('controller' => 'attributes', 'action' => 'delete', $attribute['Attribute']['id']), null, __('Are you sure you want to delete this attribute? Keep in mind that this will also delete this attribute on remote MISP instances.'));
|
||||
?>
|
||||
</td><?php
|
||||
endif;?>
|
||||
</tr><?php
|
||||
endforeach; ?><?php
|
||||
endforeach; ?>
|
||||
</table>
|
||||
<p>
|
||||
<?php
|
||||
echo $this->Paginator->counter(array(
|
||||
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
|
||||
));
|
||||
?> </p>
|
||||
|
||||
<div class="paging"><?php
|
||||
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
|
||||
echo $this->Paginator->numbers(array('separator' => ''));
|
||||
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
|
||||
?>
|
||||
</div><?php
|
||||
endif; ?><?php
|
||||
if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<div class="actions">
|
||||
<ul>
|
||||
<li><?php echo $this->Html->link('Add Attribute', array('controller' => 'attributes', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link('Add Attachment', array('controller' => 'attributes', 'action' => 'add_attachment', $event['Event']['id']));?> </li>
|
||||
</ul>
|
||||
</div><?php
|
||||
endif; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<ul><?php
|
||||
if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
|
||||
<li><?php echo $this->Html->link(__('Add Attribute', true), array('controller' => 'attributes', 'action' => 'add', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Add Attachment', true), array('controller' => 'attributes', 'action' => 'add_attachment', $event['Event']['id']));?> </li>
|
||||
<li><?php echo $this->Html->link(__('Edit Event', true), array('controller' => 'events', 'action' => 'edit', $event['Event']['id'])); ?> </li>
|
||||
<li><?php echo $this->Form->postLink(__('Delete Event'), array('controller' => 'events', 'action' => 'delete', $event['Event']['id']), null, __('Are you sure you want to delete # %s?', $event['Event']['id'])); ?></li>
|
||||
<li> </li><?php
|
||||
endif; ?>
|
||||
<?php echo $this->element('actions_menu'); ?>
|
||||
</ul>
|
||||
</div>
|
|
@ -16,7 +16,7 @@ endif; ?>
|
|||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<th><?php echo $this->Paginator->sort('attribute_count', '#Attr.');?></th>
|
||||
<?php
|
||||
if ('true' == Configure::read('CyDefSIG.showowner') || $isAdmin): ?>
|
||||
if ($isAdmin): ?>
|
||||
<th><?php echo $this->Paginator->sort('user_id', 'Email');?></th>
|
||||
<?php
|
||||
endif; ?>
|
||||
|
@ -72,9 +72,9 @@ foreach ($events as $event):?>
|
|||
</td>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true);?>';">
|
||||
<?php echo $event['Event']['attribute_count']; ?> </td><?php
|
||||
if ('true' == Configure::read('CyDefSIG.showowner') || $isAdmin): ?>
|
||||
if ($isAdmin): ?>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true);?>';">
|
||||
<?php if('false' == Configure::read('CyDefSIG.showowner') && ($isSiteAdmin || $event['Event']['org'] == $me['org'])) echo h($event['User']['email']);
|
||||
<?php if($isSiteAdmin || $event['Event']['org'] == $me['org']) echo h($event['User']['email']);
|
||||
?> </td><?php
|
||||
endif; ?>
|
||||
<td class="short" onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true);?>';">
|
||||
|
|
|
@ -55,7 +55,7 @@ endif; ?>
|
|||
</dd>
|
||||
<?php
|
||||
endif; ?>
|
||||
<?php if ('true' == Configure::read('CyDefSIG.showowner') || ($isSiteAdmin || ($isAdmin && $me['org'] == $event['Event']['org']))): ?>
|
||||
<?php if ($isSiteAdmin || ($isAdmin && $me['org'] == $event['Event']['org'])): ?>
|
||||
<dt>Email</dt>
|
||||
<dd>
|
||||
<?php echo h($event['User']['email']); ?>
|
||||
|
|
Loading…
Reference in New Issue