mirror of https://github.com/MISP/MISP
new: [internal] Simplication of the push functionality
parent
b65dce32f7
commit
fe3fc13fbd
|
@ -1608,4 +1608,20 @@ class AppModel extends Model
|
|||
$request = $this->addHeaders($request);
|
||||
return $request;
|
||||
}
|
||||
|
||||
public function addHeaders($request)
|
||||
{
|
||||
$version = $this->checkMISPVersion();
|
||||
$version = implode('.', $version);
|
||||
try {
|
||||
$commit = trim(shell_exec('git log --pretty="%H" -n1 HEAD'));
|
||||
} catch (Exception $e) {
|
||||
$commit = false;
|
||||
}
|
||||
$request['header']['MISP-version'] = $version;
|
||||
if ($commit) {
|
||||
$request['header']['commit'] = $commit;
|
||||
}
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -858,42 +858,8 @@ class Event extends AppModel
|
|||
return $error;
|
||||
}
|
||||
|
||||
public function uploadEventToServer($event, $server, $HttpSocket = null)
|
||||
private function __executeRestfulEventToServer($event, $server, $resourceId, &$newLocation, &$newTextBody, $HttpSocket)
|
||||
{
|
||||
$this->Server = ClassRegistry::init('Server');
|
||||
$push = $this->Server->checkVersionCompatibility($server['Server']['id'], false, $HttpSocket);
|
||||
if (!isset($push['canPush'])) {
|
||||
$test = $this->Server->checkLegacyServerSyncPrivilege($server['Server']['id'], $HttpSocket);
|
||||
} else {
|
||||
if (!$push['canPush']) {
|
||||
return 'The remote user is not a sync user - the upload of the event has been blocked.';
|
||||
}
|
||||
}
|
||||
$deletedAttributes = false;
|
||||
if (($push['version'][0] > 2) ||
|
||||
($push['version'][0] == 2 && $push['version'][1] > 4) ||
|
||||
($push['version'][0] == 2 && $push['version'][1] == 4 && $push['version'][2] > 42)) {
|
||||
$deletedAttributes = true;
|
||||
}
|
||||
if (isset($event['Attribute']) && !$deletedAttributes) {
|
||||
foreach ($event['Attribute'] as $k => $v) {
|
||||
if ($v['deleted']) {
|
||||
unset($event['Attribute'][$k]);
|
||||
}
|
||||
}
|
||||
$event['Attribute'] = array_values($event['Attribute']);
|
||||
}
|
||||
if (!isset($push['canPush']) || !$push['canPush']) {
|
||||
return 'Trying to push to an outdated instance.';
|
||||
}
|
||||
if (isset($server['Server']['unpublish_event'])) {
|
||||
$unpublish_event = $server['Server']['unpublish_event'];
|
||||
if ($unpublish_event) {
|
||||
$event['Event']['published'] = 0;
|
||||
}
|
||||
}
|
||||
$updated = null;
|
||||
$newLocation = $newTextBody = '';
|
||||
$result = $this->restfulEventToServer($event, $server, null, $newLocation, $newTextBody, $HttpSocket);
|
||||
if (is_numeric($result)) {
|
||||
$error = $this->__resolveErrorCode($result, $event, $server);
|
||||
|
@ -901,60 +867,47 @@ class Event extends AppModel
|
|||
return $error . ' Error code: ' . $result;
|
||||
}
|
||||
}
|
||||
if (strlen($newLocation) || $result) { // HTTP/1.1 200 OK or 302 Found and Location: http://<newLocation>
|
||||
if (strlen($newLocation)) { // HTTP/1.1 302 Found and Location: http://<newLocation>
|
||||
$result = $this->restfulEventToServer($event, $server, $newLocation, $newLocation, $newTextBody, $HttpSocket);
|
||||
if (is_numeric($result)) {
|
||||
$error = $this->__resolveErrorCode($result, $event, $server);
|
||||
if ($error) {
|
||||
return $error . ' Error code: ' . $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
$uploadFailed = false;
|
||||
try {
|
||||
$json = json_decode($newTextBody, true);
|
||||
} catch (Exception $e) {
|
||||
$uploadFailed = true;
|
||||
}
|
||||
if (!is_array($json) || $uploadFailed) {
|
||||
return $this->__logUploadResult($server, $event, $newTextBody);
|
||||
}
|
||||
// get the remote event_id
|
||||
foreach ($json as $jsonEvent) {
|
||||
if (is_array($jsonEvent)) {
|
||||
foreach ($jsonEvent as $key => $value) {
|
||||
if ($key == 'id') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $this->__logUploadResult($server, $event, $newTextBody);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function uploadEventToServer($event, $server, $HttpSocket = null)
|
||||
{
|
||||
$this->Server = ClassRegistry::init('Server');
|
||||
$push = $this->Server->checkVersionCompatibility($server['Server']['id'], false, $HttpSocket);
|
||||
if (empty($push['canPush'])) {
|
||||
return 'The remote user is not a sync user - the upload of the event has been blocked.';
|
||||
}
|
||||
if (!empty($server['Server']['unpublish_event'])) {
|
||||
$event['Event']['published'] = 0;
|
||||
}
|
||||
$updated = null;
|
||||
$newLocation = $newTextBody = '';
|
||||
$result = $this->__executeRestfulEventToServer($event, $server, null, $newLocation, $newTextBody, $HttpSocket);
|
||||
if ($result !== true) {
|
||||
return $result;
|
||||
}
|
||||
if (strlen($newLocation)) { // HTTP/1.1 302 Found and Location: http://<newLocation>
|
||||
$result = $this->restfulEventToServer($event, $server, $newLocation, $newLocation, $newTextBody, $HttpSocket);
|
||||
if (is_numeric($result)) {
|
||||
$error = $this->__resolveErrorCode($result, $event, $server);
|
||||
if ($error) {
|
||||
return $error . ' Error code: ' . $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
$uploadFailed = false;
|
||||
try {
|
||||
$json = json_decode($newTextBody, true);
|
||||
} catch (Exception $e) {
|
||||
$uploadFailed = true;
|
||||
}
|
||||
if (!is_array($json) || $uploadFailed) {
|
||||
return $this->__logUploadResult($server, $event, $newTextBody);
|
||||
}
|
||||
return 'Success';
|
||||
}
|
||||
|
||||
public function addHeaders($request)
|
||||
{
|
||||
$version = $this->checkMISPVersion();
|
||||
$version = implode('.', $version);
|
||||
try {
|
||||
$commit = trim(shell_exec('git log --pretty="%H" -n1 HEAD'));
|
||||
} catch (Exception $e) {
|
||||
$commit = false;
|
||||
}
|
||||
$request['header']['MISP-version'] = $version;
|
||||
if ($commit) {
|
||||
$request['header']['commit'] = $commit;
|
||||
}
|
||||
return $request;
|
||||
}
|
||||
|
||||
// Uploads the event and the associated Attributes to another Server
|
||||
public function restfulEventToServer($event, $server, $urlPath, &$newLocation, &$newTextBody, $HttpSocket = null)
|
||||
{
|
||||
private function __prepareForPushToServer($event, $server) {
|
||||
if ($event['Event']['distribution'] == 4) {
|
||||
if (!empty($event['SharingGroup']['SharingGroupServer'])) {
|
||||
$found = false;
|
||||
|
@ -979,17 +932,20 @@ class Event extends AppModel
|
|||
} else {
|
||||
return 403;
|
||||
}
|
||||
$url = $server['Server']['url'];
|
||||
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
|
||||
$request = $this->setupSyncRequest($server);
|
||||
$uri = $url . '/events';
|
||||
if (isset($urlPath)) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
private function __getLastUrlPathComponent($urlPath)
|
||||
{
|
||||
if (!empty($urlPath)) {
|
||||
$pieces = explode('/', $urlPath);
|
||||
$uri .= '/' . end($pieces);
|
||||
return '/' . end($pieces);
|
||||
}
|
||||
$data = json_encode($event);
|
||||
// LATER validate HTTPS SSL certificate
|
||||
$response = $HttpSocket->post($uri, $data, $request);
|
||||
return '';
|
||||
}
|
||||
|
||||
private function __handleRestfulEventToServerResponse($response, &$newLocation, &$newTextBody)
|
||||
{
|
||||
switch ($response->code) {
|
||||
case '200': // 200 (OK) + entity-action-result
|
||||
if ($response->isOk()) {
|
||||
|
@ -1002,11 +958,7 @@ class Event extends AppModel
|
|||
} catch (Exception $e) {
|
||||
return true;
|
||||
}
|
||||
if (strpos($jsonArray['name'], "Event already exists")) { // strpos, so i can piggyback some value if needed.
|
||||
return true;
|
||||
} else {
|
||||
return $jsonArray['name'];
|
||||
}
|
||||
return $jsonArray['name'];
|
||||
}
|
||||
case '302': // Found
|
||||
$newLocation = $response->headers['Location'];
|
||||
|
@ -1023,6 +975,20 @@ class Event extends AppModel
|
|||
}
|
||||
}
|
||||
|
||||
// Uploads the event and the associated Attributes to another Server
|
||||
public function restfulEventToServer($event, $server, $urlPath, &$newLocation, &$newTextBody, $HttpSocket = null)
|
||||
{
|
||||
$event = $this->__prepareForPushToServer($event, $server);
|
||||
if (is_numeric($event)) return $event;
|
||||
$url = $server['Server']['url'];
|
||||
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
|
||||
$request = $this->setupSyncRequest($server);
|
||||
$uri = $url . '/events' . $this->__getLastUrlPathComponent($urlPath);
|
||||
$data = json_encode($event);
|
||||
$response = $HttpSocket->post($uri, $data, $request);
|
||||
return $this->__handleRestfulEventToServerResponse($response, $newLocation, $newTextBody);
|
||||
}
|
||||
|
||||
private function __updateEventForSync($event, $server)
|
||||
{
|
||||
// rearrange things to be compatible with the Xml::fromArray()
|
||||
|
|
|
@ -3318,31 +3318,6 @@ class Server extends AppModel
|
|||
return array('success' => $success, 'response' => $response, 'canPush' => $canPush, 'version' => $remoteVersion);
|
||||
}
|
||||
|
||||
/* This is a fallback for legacy remote instances that don't report back the current user's sync permission.
|
||||
*
|
||||
* The idea is simple: If we have no way of determining the perm_sync flag from the remote instance, request
|
||||
* /servers/testConnection from the remote. This API is used to check the remote connectivity and expects an ID to be passed
|
||||
* In this case however we are not passing an ID so ideally it will return 404, meaning that the instance is invalid.
|
||||
* We are abusing the fact that only sync users can use this functionality, if we don't have sync permission we'll get a 403
|
||||
* instead of the 404. It's hacky but it works fine and serves the purpose.
|
||||
*/
|
||||
public function checkLegacyServerSyncPrivilege($id, $HttpSocket = false)
|
||||
{
|
||||
$server = $this->find('first', array('conditions' => array('Server.id' => $id)));
|
||||
$uri = $server['Server']['url'] . '/servers/testConnection';
|
||||
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
|
||||
$request = $this->setupSyncRequest($server);
|
||||
try {
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
if ($response->code == '404') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isJson($string)
|
||||
{
|
||||
return (json_last_error() == JSON_ERROR_NONE);
|
||||
|
|
Loading…
Reference in New Issue