Merge branch 'develop' of github.com:MISP/MISP into develop

pull/9613/head
Sami Mokaddem 2024-03-07 10:54:44 +01:00
commit aaf3633cb0
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
12 changed files with 136 additions and 49 deletions

View File

@ -16,7 +16,7 @@ class UserShell extends AppShell
'help' => __('Get list of user accounts.'),
'parser' => [
'arguments' => [
'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
'userId' => ['help' => __('User ID or e-mail address to filter.'), 'required' => false],
],
'options' => [
'json' => ['help' => __('Output as JSON.'), 'boolean' => true],
@ -82,6 +82,15 @@ class UserShell extends AppShell
],
],
]);
$parser->addSubcommand('change_role', [
'help' => __('Change user role.'),
'parser' => [
'arguments' => [
'userId' => ['help' => __('User ID or e-mail address.'), 'required' => true],
'new_role' => ['help' => __('Role ID or Role name.'), 'required' => true],
]
],
]);
$parser->addSubcommand('change_authkey', [
'help' => __('Change authkey. When advanced authkeys are enabled, old authkeys will be disabled.'),
'parser' => [
@ -443,6 +452,35 @@ class UserShell extends AppShell
}
}
public function change_role()
{
list($userId, $newRole) = $this->args;
$user = $this->getUser($userId);
if (is_numeric($newRole)) {
$conditions = ['Role.id' => $newRole];
} else {
$conditions = ['Role.name' => $newRole];
}
$newRoleFromDb = $this->User->Role->find('first', [
'conditions' => $conditions,
'fields' => ['Role.id'],
]);
if (empty($newRoleFromDb)) {
$this->error("Role `$newRole` not found.");
}
if ($newRoleFromDb['Role']['id'] == $user['role_id']) {
$this->error("Role `$newRole` is already assigned to {$user['email']}.");
}
$this->User->updateField($user, 'role_id', $newRoleFromDb['Role']['id']);
$this->out("Role changed from `{$user['role_id']}` to `{$newRoleFromDb['Role']['id']}`.");
}
public function user_ips()
{
list($userId) = $this->args;
@ -575,7 +613,7 @@ class UserShell extends AppShell
}
/**
* @param string|int $userId
* @param string|int $userId User ID or User e-mail
* @return array
*/
private function getUser($userId)

View File

@ -2369,7 +2369,13 @@ class EventsController extends AppController
}
$isXml = $ext === 'xml';
$data = FileAccessTool::readFromFile($file['tmp_name'], $file['size']);
$matches = null;
$tmp_name = $file['tmp_name'];
if (preg_match_all('/[\w\/\-\.]*/', $tmp_name, $matches) && file_exists($file['tmp_name'])) {
$data = FileAccessTool::readFromFile($matches[0][0], $file['size']);
} else {
throw new NotFoundException(__('Invalid file.'));
}
} else {
throw new MethodNotAllowedException(__('No file uploaded.'));
}
@ -2378,7 +2384,6 @@ class EventsController extends AppController
&& (isset($this->request->data['Event']['takeownership']) && $this->request->data['Event']['takeownership'] == 1);
$publish = $this->request->data['Event']['publish'] ?? false;
try {
$results = $this->Event->addMISPExportFile($this->Auth->user(), $data, $isXml, $takeOwnership, $publish);
} catch (Exception $e) {

View File

@ -490,8 +490,14 @@ class OrganisationsController extends AppController
$this->Flash->error(__('Invalid file extension, Only PNG and SVG images are allowed.'));
return false;
}
$imgMime = mime_content_type($logo['tmp_name']);
$matches = null;
$tmp_name = $logo['tmp_name'];
if (preg_match_all('/[\w\/\-\.]*/', $tmp_name, $matches) && file_exists($logo['tmp_name'])) {
$tmp_name = $matches[0][0];
$imgMime = mime_content_type($tmp_name);
} else {
throw new NotFoundException(__('Invalid file.'));
}
if ($extension === 'png' && (function_exists('exif_imagetype') && !exif_imagetype($logo['tmp_name']))) {
$this->Flash->error(__('This is not a valid PNG image.'));
return false;
@ -507,8 +513,8 @@ class OrganisationsController extends AppController
return false;
}
if (!empty($logo['tmp_name']) && is_uploaded_file($logo['tmp_name'])) {
return move_uploaded_file($logo['tmp_name'], APP . 'files/img/orgs/' . $filename);
if (!empty($tmp_name) && is_uploaded_file($tmp_name)) {
return move_uploaded_file($tmp_name, APP . 'files/img/orgs/' . $filename);
}
}

View File

@ -820,6 +820,15 @@ class TagsController extends AppController
}
$message = 'Global tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully attached to ' . $objectType . '(' . $object[$objectType]['id'] . ').';
}
$this->loadModel('Log');
$this->Log->createLogEntry(
$this->Auth->user(),
'attachTagToObject',
$objectType,
$object[$objectType]['id'],
$message,
null
);
$successes++;
} else {
$fails[] = __('Failed to attach tag to object.');
@ -896,6 +905,17 @@ class TagsController extends AppController
$result = $this->$objectType->$connectorObject->delete($existingAssociation[$connectorObject]['id']);
if ($result) {
$message = __('%s tag %s (%s) successfully removed from %s(%s).', $local ? __('Local') : __('Global'), $existingTag['Tag']['name'], $existingTag['Tag']['id'], $objectType, $object[$objectType]['id']);
$this->loadModel('Log');
$this->Log->createLogEntry(
$this->Auth->user(),
'removeTagFromObject',
$objectType,
$object[$objectType]['id'],
$message,
__(
'',
)
);
if (!$local) {
if ($objectType === 'Attribute') {
$this->Attribute->touch($object['Attribute']['id']);

View File

@ -217,7 +217,7 @@ class ServerSyncTool
}
/**
* @param array $rules
* @param array $candidates
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException
* @throws HttpSocketJsonException
@ -225,7 +225,7 @@ class ServerSyncTool
public function filterAnalystDataForPush(array $candidates)
{
if (!$this->isSupported(self::PERM_ANALYST_DATA)) {
return [];
throw new RuntimeException("Remote server do not support analyst data");
}
return $this->post('/analyst_data/filterAnalystDataForPush', $candidates);
@ -240,20 +240,23 @@ class ServerSyncTool
public function fetchIndexMinimal(array $rules)
{
if (!$this->isSupported(self::PERM_ANALYST_DATA)) {
return [];
throw new RuntimeException("Remote server do not support analyst data");
}
return $this->post('/analyst_data/indexMinimal', $rules);
}
/**
* @param string $type
* @param array $uuids
* @return HttpSocketResponseExtended
* @throws HttpSocketJsonException
* @throws HttpSocketHttpException
*/
public function fetchAnalystData($type, array $uuids)
{
if (!$this->isSupported(self::PERM_ANALYST_DATA)) {
return [];
throw new RuntimeException("Remote server do not support analyst data");
}
$params = [
@ -264,12 +267,10 @@ class ServerSyncTool
$url .= $this->createParams($params);
$url .= '.json';
return $this->get($url);
// $response = $this->post('/analyst_data/restSearch' , $params);
// return $response->json();
}
/**
/**
* @param string $type
* @param array $analystData
* @return HttpSocketResponseExtended
* @throws HttpSocketHttpException

View File

@ -1007,9 +1007,14 @@ class AnalystData extends AppModel
*
* @param array $user
* @param ServerSyncTool $serverSync
* @return int Number of saved analysis
*/
public function pull(array $user, ServerSyncTool $serverSync)
{
if (!$serverSync->isSupported(ServerSyncTool::PERM_ANALYST_DATA)) {
return 0;
}
$this->Server = ClassRegistry::init('Server');
$this->AnalystData = ClassRegistry::init('AnalystData');
try {
@ -1051,14 +1056,11 @@ class AnalystData extends AppModel
return 0;
}
if ($serverSync->isSupported(ServerSyncTool::PERM_ANALYST_DATA)) {
return $this->pullInChunks($user, $remoteUUIDsToFetch, $serverSync);
}
return $this->pullInChunks($user, $remoteUUIDsToFetch, $serverSync);
}
public function pullInChunks(array $user, array $analystDataUuids, ServerSyncTool $serverSync)
private function pullInChunks(array $user, array $analystDataUuids, ServerSyncTool $serverSync)
{
$uuids = array_keys($analystDataUuids);
$saved = 0;
$serverOrgUUID = $this->Org->find('first', [
'recursive' => -1,

View File

@ -1990,7 +1990,7 @@ class AppModel extends Model
$sqlArray[] = "ALTER TABLE `event_reports` modify `content` mediumtext";
break;
case 117:
$sqlArray[] = "CREATE TABLE `user_login_profiles` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `user_login_profiles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`user_id` int(11) NOT NULL,
@ -2018,7 +2018,7 @@ class AppModel extends Model
$sqlArray[] = "ALTER TABLE `access_logs` MODIFY `action` varchar(191) NOT NULL";
break;
case 121:
$sqlArray[] = "CREATE TABLE `notes` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `notes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`object_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
@ -2026,8 +2026,8 @@ class AppModel extends Model
`authors` text,
`org_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`orgc_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime ON UPDATE CURRENT_TIMESTAMP,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`locked` tinyint(1) NOT NULL DEFAULT 0,
@ -2043,7 +2043,7 @@ class AppModel extends Model
KEY `sharing_group_id` (`sharing_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
$sqlArray[] = "CREATE TABLE `opinions` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `opinions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`object_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
@ -2051,8 +2051,8 @@ class AppModel extends Model
`authors` text,
`org_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`orgc_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime ON UPDATE CURRENT_TIMESTAMP,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`locked` tinyint(1) NOT NULL DEFAULT 0,
@ -2069,7 +2069,7 @@ class AppModel extends Model
KEY `opinion` (`opinion`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
$sqlArray[] = "CREATE TABLE `relationships` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `relationships` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) CHARACTER SET ascii NOT NULL,
`object_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
@ -2077,8 +2077,8 @@ class AppModel extends Model
`authors` text,
`org_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`orgc_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime ON UPDATE CURRENT_TIMESTAMP,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`locked` tinyint(1) NOT NULL DEFAULT 0,
@ -2117,14 +2117,14 @@ class AppModel extends Model
$sqlArray[] = "ALTER TABLE `servers` ADD `pull_analyst_data` tinyint(1) NOT NULL DEFAULT 0 AFTER `push_analyst_data`;";
break;
case 122:
$sqlArray[] = "CREATE TABLE `collections` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `collections` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`org_id` int(10) unsigned NOT NULL,
`orgc_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime ON UPDATE CURRENT_TIMESTAMP,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`distribution` tinyint(4) NOT NULL,
`sharing_group_id` int(10) unsigned,
`name` varchar(191) NOT NULL,
@ -2141,7 +2141,7 @@ class AppModel extends Model
KEY `sharing_group_id` (`sharing_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
$sqlArray[] = "CREATE TABLE `collection_elements` (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `collection_elements` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
`element_uuid` varchar(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,

View File

@ -3466,7 +3466,7 @@ class Event extends AppModel
if ($tagId && !in_array($tagId, $event_tag_ids)) {
$eventTags[] = array(
'tag_id' => $tagId,
'local' => isset($tag['local']) ? $tag['local'] : 0,
'local' => isset($tag['local']) ? $tag['local'] : false,
'relationship_type' => isset($tag['relationship_type']) ? $tag['relationship_type'] : '',
);
$event_tag_ids[] = $tagId;
@ -3482,7 +3482,7 @@ class Event extends AppModel
if ($tag_id && !in_array($tag_id, $event_tag_ids)) {
$eventTags[] = [
'tag_id' => $tag_id,
'local' => isset($tag['local']) ? $tag['local'] : 0,
'local' => isset($tag['local']) ? $tag['local'] : false,
'relationship_type' => isset($tag['relationship_type']) ? $tag['relationship_type'] : '',
];
$event_tag_ids[] = $tag_id;
@ -3560,7 +3560,7 @@ class Event extends AppModel
if ($tagId) {
$attributeTags[] = [
'tag_id' => $tagId,
'local' => isset($tag['local']) ? $tag['local'] : 0,
'local' => isset($tag['local']) ? $tag['local'] : false,
'relationship_type' => isset($tag['relationship_type']) ? $tag['relationship_type'] : '',
];
}
@ -3680,7 +3680,9 @@ class Event extends AppModel
}
if (!empty($event['Event']['Object'])) {
for ($i=0; $i < count($event['Event']['Object']); $i++) {
$event['Event']['Object'][$i] = $this->updatedLockedFieldForAnalystData($event['Event']['Object'][$i]);
if (isset($event['Event']['Object'][$i])) {
$event['Event']['Object'][$i] = $this->updatedLockedFieldForAnalystData($event['Event']['Object'][$i]);
}
if (!empty($event['Event']['Object'][$i])) {
for ($j=0; $j < count($event['Event']['Object'][$i]['Attribute']); $j++) {
$event['Event']['Object'][$i]['Attribute'][$j] = $this->updatedLockedFieldForAnalystData($event['Event']['Object'][$i]['Attribute'][$j]);
@ -5969,8 +5971,8 @@ class Event extends AppModel
} else {
$event = $this->find('first', array(
'recursive' => -1,
'conditions' => array('Event.id' => $eventOrEventId),
'fields' => ['id', 'info'], // info is required because of SysLogLogableBehavior
'conditions' => array('Event.id' => $eventOrEventId)
//'fields' => ['id', 'info'], // info is required because of SysLogLogableBehavior
));
if (empty($event)) {
return false;
@ -6375,7 +6377,7 @@ class Event extends AppModel
unset($data[$dataType . 'Tag'][$k]);
continue;
}
$dataTag['Tag']['local'] = empty($dataTag['local']) ? 0 : 1;
$dataTag['Tag']['local'] = empty($dataTag['local']) ? false : true;
if (!isset($excludeGalaxy) || !$excludeGalaxy) {
if (substr($dataTag['Tag']['name'], 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
$cluster = $this->GalaxyCluster->getCluster($dataTag['Tag']['name'], $user);
@ -7321,7 +7323,7 @@ class Event extends AppModel
foreach ($event['EventTag'] as $etk => $eventTag) {
$tag = $this->__getCachedTag($eventTag['tag_id'], $justExportable);
if ($tag !== null) {
$tag['local'] = empty($eventTag['local']) ? 0 : 1;
$tag['local'] = empty($eventTag['local']) ? false : true;
$tag['relationship_type'] = empty($eventTag['relationship_type']) ? null : $eventTag['relationship_type'];
$event['EventTag'][$etk]['Tag'] = $tag;
} else {
@ -7336,7 +7338,7 @@ class Event extends AppModel
foreach ($attribute['AttributeTag'] as $atk => $attributeTag) {
$tag = $this->__getCachedTag($attributeTag['tag_id'], $justExportable);
if ($tag !== null) {
$tag['local'] = empty($attributeTag['local']) ? 0 : 1;
$tag['local'] = empty($attributeTag['local']) ? false : true;
$tag['relationship_type'] = empty($attributeTag['relationship_type']) ? null : $attributeTag['relationship_type'];
$event['Attribute'][$ak]['AttributeTag'][$atk]['Tag'] = $tag;
} else {

View File

@ -38,6 +38,7 @@ class Log extends AppModel
'add',
'admin_email',
'attachTags',
'attachTagToObject',
'auth',
'auth_fail',
'auth_alert',
@ -78,6 +79,7 @@ class Log extends AppModel
'registration',
'registration_error',
'remove_dead_workers',
'removeTagFromObject',
'request',
'request_delegation',
'reset_auth_key',

View File

@ -580,7 +580,17 @@ class Server extends AppModel
}
return false;
}
$this->__checkIfPulledEventExistsAndAddOrUpdate($event, $eventId, $successes, $fails, $eventModel, $serverSync->server(), $user, $jobId, $force, $response);
try {
$this->__checkIfPulledEventExistsAndAddOrUpdate($event, $eventId, $successes, $fails, $eventModel, $serverSync->server(), $user, $jobId, $force, $response);
} catch (Exception $e) {
$title = __('Pulling an event (#%s) from Server #%s has failed. The sync process was not interrupted.', $eventId, $serverSync->server()['id']);
$this->loadLog()->createLogEntry(
$user,
'error',
'Server',
$serverSync->serverId(),
$title, $e->getMessage());
}
return true;
}

View File

@ -458,7 +458,7 @@ class Oidc
private function getConfig($config, $default = null)
{
$value = Configure::read("OidcAuth.$config");
if (empty($value)) {
if ($value === null) {
if ($default === null) {
throw new RuntimeException("Config option `OidcAuth.$config` is not set.");
}

View File

@ -29,17 +29,18 @@
"ext-redis": "For working background jobs and feed and warninglist caches",
"ext-zip": "Enabling processing feeds that are ZIP compressed",
"ext-zlib": "Allow gzip compression of HTTP responses",
"ext-brotli": "Allow brotli compression of HTTP responses",
"ext-brotli": "Allow brotli compression of HTTP responses and audit logs",
"ext-zstd": "For better and faster compression when fetching data from remote servers",
"ext-intl": "For handling IDN domain names",
"ext-ssdeep": "For ssdeep hashes correlation",
"ext-bcmath": "For faster validating IBAN numbers",
"ext-rdkafka": "Required for publishing events to Kafka broker",
"ext-apcu": "To cache data in memory instead of file system",
"ext-simdjson": "To decode JSON structures faster",
"ext-curl": "For faster remote requests",
"ext-curl": "For faster fetching data from remote servers and feeds",
"elasticsearch/elasticsearch": "For logging to elasticsearch",
"aws/aws-sdk-php": "To upload samples to S3",
"jakub-onderka/openid-connect-php": "For OIDC authentication",
"jakub-onderka/openid-connect-php": "To enable OIDC authentication",
"supervisorphp/supervisor": "For managing background jobs",
"guzzlehttp/guzzle": "Required for supervisorphp/supervisor XML-RPC requests",
"lstrojny/fxmlrpc": "Required for supervisorphp/supervisor XML-RPC requests",