Skip to content

Commit

Permalink
Merge branch '2.4' of github.com:MISP/MISP into 2.4
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisr3d committed Sep 22, 2023
2 parents 4b6c624 + bffb392 commit a110fb6
Show file tree
Hide file tree
Showing 40 changed files with 762 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature-request-form.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Feature request
description: Suggest an idea for this project
title: "Feature Request: "
labels: ["feature request", "needs triage"]
labels: ["T: feature request", "needs triage"]
body:
- type: textarea
id: motif
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: 'recursive'

Expand Down Expand Up @@ -243,6 +243,13 @@ jobs:
./app/Vendor/bin/parallel-lint --exclude app/Lib/cakephp/ --exclude app/Vendor/ --exclude app/Lib/random_compat/ -e php,ctp app/
sudo -u www-data ./app/Vendor/bin/phpunit app/Test/
- name: Clone test files
uses: actions/checkout@v4
with:
repository: viper-framework/viper-test-files
path: PyMISP/tests/viper-test-files


- name: Run tests
run: |
pushd tests
Expand All @@ -253,6 +260,9 @@ jobs:
. ./venv/bin/activate
pushd PyMISP
ls
ls tests
ls tests/viper-test-files
python tests/testlive_comprehensive.py
python tests/test_mispevent.py
popd
Expand Down
2 changes: 1 addition & 1 deletion PyMISP
2 changes: 1 addition & 1 deletion VERSION.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"major":2, "minor":4, "hotfix":175}
{"major":2, "minor":4, "hotfix":177}
2 changes: 1 addition & 1 deletion app/Config/config.default.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
'user_email_notification_ban_time_threshold' => 120,
'user_email_notification_ban_amount_threshold' => 10,
'user_email_notification_ban_refresh_on_retry' => true,
'warning_for_all' => true,
'warning_for_all' => false,
'enable_synchronisation_filtering_on_type' => false,
),
'GnuPG' => array(
Expand Down
12 changes: 9 additions & 3 deletions app/Console/Command/AdminShell.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,17 @@ public function jobForgot()

public function jobGenerateCorrelation()
{
if (empty($this->args[0])) {
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Generate correlation'] . PHP_EOL);
$jobId = $this->args[0] ?? null;
if (empty($jobId)) {
$jobId = $this->Job->createJob(
'SYSTEM',
Job::WORKER_DEFAULT,
'generate correlation',
'All attributes',
'Job created.'
);
}

$jobId = $this->args[0];
$this->Correlation->generateCorrelation($jobId);
}

Expand Down
119 changes: 118 additions & 1 deletion app/Console/Command/TrainingShell.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
* arg0 = email
* arg1 = new password
*/

App::uses('File', 'Utility');


class TrainingShell extends AppShell {

public $uses = array('User', 'Organisation', 'Server');
public $uses = array('User', 'Organisation', 'Server', 'Authkey');

private $__currentUrl = false;
private $__currentAuthKey = false;
Expand Down Expand Up @@ -115,6 +119,119 @@ public function setup()
$this->__printReport('Setup complete. Please find the modifications below:' . PHP_EOL . PHP_EOL);
}

public function createOrganisationsFromConfig()
{
$rawConfig = file_get_contents(APP . 'Console/Command/config_orgs.json');
$config = json_decode($rawConfig, true);
$createdOrgs = [];
foreach ($config as $org) {
$filepath = APP . 'Console/Command/' . $org['Organisation']['logo_path'];
$file = new File($filepath, false);
if ($file->exists()) {
$org['Organisation']['logo'] = [
'name' => $file->name(),
'type' => $file->mime(),
'tmp_name' => $filepath,
'error' => 0,
'size' => $file->size(),
];
}
$file->close();
$date = date('Y-m-d H:i:s');
$org['Organisation']['date_created'] = $date;
$org['Organisation']['date_modified'] = $date;
$this->Organisation->create();
$this->Organisation->save($org);
$filename = $this->Organisation->id . '.' . ($file->ext() === 'svg' ? 'svg' : 'png');
$file->copy(APP . 'webroot/img/orgs/' . $filename);
$createdOrg = $this->Organisation->find('first', ['conditions' => ['id' => $this->Organisation->id]]);
$createdOrgs[$createdOrg['Organisation']['uuid']] = $createdOrg['Organisation'];
}
return $createdOrgs;
}

public function createUsersFromConfig($createdOrgs)
{
$rawConfig = file_get_contents(APP . 'Console/Command/config_users.json');
$config = json_decode($rawConfig, true);
$createdUsers = [];
foreach ($config as $user) {
$user['org_id'] = $createdOrgs[$user['org_uuid']]['id'];
$existingUser = $this->User->find('first', [
'recursive' => -1,
'conditions' => ['User.email' => $user['email']],
]);
if (empty($existingUser)) {
$this->User->create();
} else {
$user['id'] = $existingUser['User']['id'];
}
$this->User->save($user);
$createdUser = $this->User->find('first', ['id' => $this->User->id]);
$createdUsers[] = $createdUser;
}
return $createdUsers;
}

public function setSettingsFromConfig($createdOrgs)
{
$rawConfig = file_get_contents(APP . 'Console/Command/config_settings.json');
$config = json_decode($rawConfig, true);
$cli_user = ['id' => 0, 'email' => 'SYSTEM', 'Organisation' => ['name' => 'SYSTEM']];
foreach ($config as $setting_name => $value) {
if ($setting_name == 'MISP.host_org_id') {
$value = $createdOrgs[$value]['id'];
}
$setting = $this->Server->getSettingData($setting_name);
if (empty($setting)) {
$this->error(__('Setting change rejected.'));
}
$result = $this->Server->serverSettingsEditValue($cli_user, $setting, $value, true);
if (empty($result)) {
$this->error(__('Setting change rejected.'));
}
}
}

public function createRemoteServersFromConfig($createdOrgs, $createdUsers)
{
$rawConfig = file_get_contents(APP . 'Console/Command/config_syncs.json');
$config = json_decode($rawConfig, true);
$createdServers = [];
foreach ($config as $sync) {
$sync['org_id'] = $createdOrgs[$sync['org_uuid']]['id'];
$sync['remote_org_id'] = $createdOrgs[$sync['remote_org_uuid']]['id'];
$this->Server->create();
$this->Server->save($sync);
$createdServer = $this->User->find('first', ['id' => $this->User->id]);
$createdServers[] = $createdServer;
}
return $createdServers;
}

public function createAllFromConfig()
{
$createdOrgs = $this->createOrganisationsFromConfig();
$createdUsers = $this->createUsersFromConfig($createdOrgs);
$this->setSettingsFromConfig($createdOrgs);
$this->createRemoteServersFromConfig($createdOrgs, $createdUsers);
}

public function WipeAllSyncs()
{
$this->Server->deleteAll(['Server.id !=' => 0]);
}

public function WipeAllUsers()
{
$this->User->deleteAll(['User.email !=' => '[email protected]']);
}

public function WipeAllOrgs()
{
$this->Organisation->deleteAll(['Organisation.name !=' => 'ORGNAME']);
}

private function __createOrgFromBlueprint($id)
{
$org = str_replace('$ID', $id, $this->__config['org_blueprint']);
Expand Down
67 changes: 67 additions & 0 deletions app/Console/Command/UserShell.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ public function getOptionParser()
],
],
]);
$parser->addSubcommand('require_password_change_for_old_passwords', [
'help' => __('Trigger forced password change on next login for users with an old (older than x days) password.'),
'parser' => [
'arguments' => [
'days' => ['help' => __('Amount of days after which a password is considered "old" and needs to be changed.'), 'required' => true]
],
]
]);

$parser->addSubcommand('expire_authkeys_without_ip_allowlist', [
'help' => __('Expire all active authkeys that do not have an IP allowlist set.'),
]);
return $parser;
}

Expand Down Expand Up @@ -431,6 +443,61 @@ public function ip_user()
}
}

public function require_password_change_for_old_passwords()
{
list($days) = $this->args;
if(!is_numeric($days)){
$this->error("The amount of days after which a password change is required (the argument) should be numeric.");
}
$interval = 'P' . $days . 'D';

$current_time = new DateTime();
$time_before_change_required = $current_time->sub(new DateInterval($interval))->getTimestamp();
$users = $this->User->find('all', [
'conditions' => [
'OR' => [
'last_pw_change <' => $time_before_change_required
]
],
'fields' => ['id'],
'recursive' => 0
]);
foreach ($users as $user) {
$user['User']['change_pw'] = true;
$userId = $user['User']['id'];
if (!$this->User->save($user['User'], true, ["change_pw"])) {
$this->out("Could not update user $userId.");
$this->out($this->json($this->User->validationErrors));
$this->_stop(self::CODE_ERROR);
}
}
}

public function expire_authkeys_without_ip_allowlist()
{
$time = time();
$authkeys = $this->User->AuthKey->find('all', [
'conditions' => [
'OR' => [
'AuthKey.expiration >' => $time,
'AuthKey.expiration' => 0
],
'allowed_ips' => NULL
],
'fields' => ['id', 'user_id'],
'recursive' => 0
]);
foreach ($authkeys as $authkey) {
$authkey['AuthKey']['expiration'] = $time;
$authkeyId = $authkey['AuthKey']['id'];
if (!$this->User->AuthKey->save($authkey['AuthKey'])) {
$this->out("Could not update authkey $authkeyId.");
$this->out($this->json($this->User->AuthKey->validationErrors));
$this->_stop(self::CODE_ERROR);
}
}
}

/**
* @param string|int $userId
* @return array
Expand Down
28 changes: 24 additions & 4 deletions app/Controller/AppController.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class AppController extends Controller
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');

private $__queryVersion = '155';
public $pyMispVersion = '2.4.175';
public $pyMispVersion = '2.4.176';
public $phpmin = '7.2';
public $phprec = '7.4';
public $phptoonew = '8.0';
Expand Down Expand Up @@ -962,6 +962,14 @@ protected function _getApiAuthUser($key, &$exception)
return $user;
}

private function __captureParam($data, $param, $value)
{
if ($this->modelClass->checkParam($param)) {
$data[$param] = $value;
}
return $data;
}

/**
* generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params
* @param array $options
Expand All @@ -982,9 +990,21 @@ protected function _harvestParameters($options, &$exception = null, $data = [])
return false;
} else {
if (isset($request->data['request'])) {
$data = array_merge($data, $request->data['request']);
$temp = $request->data['request'];
} else {
$data = array_merge($data, $request->data);
$temp = $request->data;
}
if (empty($options['paramArray'])) {
foreach ($options['paramArray'] as $param => $value) {
$data = $this->__captureParam($data, $param, $value);
}
$data = array_merge($data, $temp);
} else {
foreach ($options['paramArray'] as $param) {
if (isset($temp[$param])) {
$data[$param] = $temp[$param];
}
}
}
}
}
Expand Down Expand Up @@ -1084,7 +1104,7 @@ private function __customAuthentication($server)
{
$result = false;
if (Configure::read('Plugin.CustomAuth_enable')) {
$header = Configure::read('Plugin.CustomAuth_header') ? Configure::read('Plugin.CustomAuth_header') : 'Authorization';
$header = Configure::read('Plugin.CustomAuth_header') ? Configure::read('Plugin.CustomAuth_header') : 'AUTHORIZATION';
$authName = Configure::read('Plugin.CustomAuth_name') ? Configure::read('Plugin.CustomAuth_name') : 'External authentication';
if (
!Configure::check('Plugin.CustomAuth_use_header_namespace') ||
Expand Down
6 changes: 3 additions & 3 deletions app/Controller/Component/ACLComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -484,9 +484,9 @@ class ACLComponent extends Component
'display' => array('*'),
),
'posts' => array(
'add' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'delete' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'edit' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'add' => ['AND' => ['not_read_only_authkey', 'discussion_enabled', 'perm_add']],
'delete' => ['AND' => ['not_read_only_authkey', 'discussion_enabled', 'perm_add']],
'edit' => ['AND' => ['not_read_only_authkey', 'discussion_enabled', 'perm_add']],
'pushMessageToZMQ' => array()
),
'regexp' => array(
Expand Down
2 changes: 1 addition & 1 deletion app/Controller/Component/IndexFilterComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function harvestParameters($paramArray, &$exception = [])
private function __massageData($data, $request, $paramArray)
{
$data = array_filter($data, function($paramName) use ($paramArray) {
return in_array($paramName, $paramArray);
return in_array($paramName, $paramArray, true);
}, ARRAY_FILTER_USE_KEY);

if (!empty($paramArray)) {
Expand Down
4 changes: 2 additions & 2 deletions app/Controller/Component/RestSearchComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ class RestSearchComponent extends Component
'includeProposals', 'returnFormat', 'limit', 'page', 'requested_attributes', 'includeContext', 'headerless',
'includeWarninglistHits', 'attackGalaxy', 'object_relation', 'includeSightings', 'includeCorrelations', 'includeDecayScore',
'decayingModel', 'excludeDecayed', 'modelOverrides', 'includeFullModel', 'score', 'attribute_timestamp', 'first_seen', 'last_seen',
'threat_level_id'
'threat_level_id', 'eventinfo'
),
'Event' => array(
'returnFormat', 'value', 'type', 'category', 'org', 'tags', 'searchall', 'from', 'to', 'last', 'eventid', 'withAttachments',
'metadata', 'uuid', 'publish_timestamp', 'timestamp', 'published', 'enforceWarninglist', 'sgReferenceOnly',
'limit', 'page', 'requested_attributes', 'includeContext', 'headerless', 'includeWarninglistHits', 'attackGalaxy', 'to_ids', 'deleted',
'excludeLocalTags', 'date', 'includeSightingdb', 'tag', 'object_relation', 'threat_level_id'
'excludeLocalTags', 'date', 'includeSightingdb', 'tag', 'object_relation', 'threat_level_id', 'eventinfo'
),
'Object' => array(
'returnFormat', 'value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp',
Expand Down
Loading

0 comments on commit a110fb6

Please sign in to comment.