Exemplo n.º 1
0
 /**
  * Execute the command
  *
  * @return void
  */
 public function handle()
 {
     Log::info('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Queued worker is starting the processing of email file: ' . $this->filename);
     $filesystem = new Filesystem();
     $rawEmail = $filesystem->get($this->filename);
     $parsedMail = new MimeParser();
     $parsedMail->setText($rawEmail);
     // Sanity checks
     if (empty($parsedMail->getHeader('from')) || empty($parsedMail->getMessageBody())) {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Missing e-mail headers from and/or empty body: ' . $this->filename);
         $this->alertAdmin();
         return;
     }
     // Ignore email from our own notification address to prevent mail loops
     if (preg_match('/' . Config::get('main.notifications.from_address') . '/', $parsedMail->getHeader('from'))) {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Loop prevention: Ignoring email from self ' . Config::get('main.notifications.from_address'));
         $this->alertAdmin();
         return;
     }
     // Start with detecting valid ARF e-mail
     $attachments = $parsedMail->getAttachments();
     $arfMail = [];
     foreach ($attachments as $attachment) {
         if ($attachment->contentType == 'message/feedback-report') {
             $arfMail['report'] = $attachment->getContent();
         }
         if ($attachment->contentType == 'message/rfc822') {
             $arfMail['evidence'] = utf8_encode($attachment->getContent());
         }
         if ($attachment->contentType == 'text/plain') {
             $arfMail['message'] = $attachment->getContent();
         }
     }
     /*
      * Sometimes the mime header does not set the main message correctly. This is ment as a fallback and will
      * use the original content body (which is basicly the same mime element). But only fallback if we actually
      * have a RFC822 message with a feedback report.
      */
     if (empty($arfMail['message']) && isset($arfMail['report']) && isset($arfMail['evidence'])) {
         $arfMail['message'] = $parsedMail->getMessageBody();
     }
     // If we do not have a complete e-mail, then we empty the perhaps partially filled arfMail
     // which is useless, hence reset to false
     if (!isset($arfMail['report']) || !isset($arfMail['evidence']) || !isset($arfMail['message'])) {
         $arfMail = false;
     }
     // Asking ParserFactory for an object based on mappings, or die trying
     $parser = ParserFactory::create($parsedMail, $arfMail);
     if ($parser !== false) {
         $parserResult = $parser->parse();
     } else {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . ': No parser available to handle message from : ' . $parsedMail->getHeader('from') . ' with subject: ' . $parsedMail->getHeader('subject'));
         $this->alertAdmin();
         return;
     }
     if ($parserResult !== false && $parserResult['errorStatus'] === true) {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($parser) . ': ' . ': Parser has ended with fatal errors ! : ' . $parserResult['errorMessage']);
         $this->alertAdmin();
         return;
     } else {
         Log::info('(JOB ' . getmypid() . ') ' . get_class($parser) . ': ' . ': Parser completed with ' . $parserResult['warningCount'] . ' warnings and collected ' . count($parserResult['data']) . ' events to save');
     }
     if ($parserResult['warningCount'] !== 0 && Config::get('main.emailparser.notify_on_warnings') === true) {
         Log::error('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Configuration has warnings set as critical and ' . $parserResult['warningCount'] . ' warnings were detected. Sending alert to administrator');
         $this->alertAdmin();
         return;
     }
     if (count($parserResult['data']) !== 0) {
         // Call validator
         $validator = new EventsValidate();
         $validatorResult = $validator->check($parserResult['data']);
         if ($validatorResult['errorStatus'] === true) {
             Log::error('(JOB ' . getmypid() . ') ' . get_class($validator) . ': ' . 'Validator has ended with errors ! : ' . $validatorResult['errorMessage']);
             $this->alertAdmin();
             return;
         } else {
             Log::info('(JOB ' . getmypid() . ') ' . get_class($validator) . ': ' . 'Validator has ended without errors');
         }
         /**
          * save evidence into table
          **/
         $evidence = new Evidence();
         $evidence->filename = $this->filename;
         $evidence->sender = $parsedMail->getHeader('from');
         $evidence->subject = $parsedMail->getHeader('subject');
         $evidence->save();
         /**
          * call saver
          **/
         $saver = new EventsSave();
         $saverResult = $saver->save($parserResult['data'], $evidence->id);
         /**
          * We've hit a snag, so we are gracefully killing ourselves
          * after we contact the admin about it. EventsSave should never
          * end with problems unless the mysql died while doing transactions
          **/
         if ($saverResult['errorStatus'] === true) {
             Log::error('(JOB ' . getmypid() . ') ' . get_class($saver) . ': ' . 'Saver has ended with errors ! : ' . $saverResult['errorMessage']);
             $this->alertAdmin();
             return;
         } else {
             Log::info('(JOB ' . getmypid() . ') ' . get_class($saver) . ': ' . 'Saver has ended without errors');
         }
     } else {
         Log::warning('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Parser did not return any events therefore skipping validation and saving a empty event set');
     }
     Log::info('(JOB ' . getmypid() . ') ' . get_class($this) . ': ' . 'Queued worker has ended the processing of email file: ' . $this->filename);
 }
Exemplo n.º 2
0
 /**
  * Execute the command
  *
  * @return boolean
  */
 public function handle()
 {
     Log::info(get_class($this) . ': ' . 'Queued worker is starting the collector: ' . $this->collector);
     $collector = collectorFactory::create($this->collector);
     if (!$collector) {
         Log::error("The requested collector {$this->collector} could not be started check logs for PID:" . getmypid());
         $this->exception();
     }
     $collectorResult = $collector->parse();
     if ($collectorResult['errorStatus'] == true) {
         Log::error("The requested collector {$this->collector} returned an error. check logs for PID:" . getmypid());
         $this->exception();
     }
     if (count($collectorResult['data']) !== 0) {
         // Call validator
         $validator = new EventsValidate();
         $validatorResult = $validator->check($collectorResult['data']);
         if ($validatorResult['errorStatus'] === true) {
             Log::error(get_class($validator) . ': ' . 'Validator has ended with errors ! : ' . $validatorResult['errorMessage']);
             $this->exception();
             return;
         } else {
             Log::info(get_class($validator) . ': ' . 'Validator has ended without errors');
         }
         /**
          * save evidence onto disk
          */
         $filesystem = new Filesystem();
         $datefolder = Carbon::now()->format('Ymd');
         $path = storage_path() . '/mailarchive/' . $datefolder . '/';
         $file = Uuid::generate(4) . '.eml';
         $filename = $path . $file;
         if (!$filesystem->isDirectory($path)) {
             // If a datefolder does not exist, then create it or die trying
             if (!$filesystem->makeDirectory($path)) {
                 Log::error(get_class($this) . ': ' . 'Unable to create directory: ' . $path);
                 $this->exception();
             }
             chown($path, 'abuseio');
             chgrp($path, 'abuseio');
         }
         if ($filesystem->isFile($filename)) {
             Log::error(get_class($this) . ': ' . 'File aready exists: ' . $filename);
             $this->exception();
         }
         if ($filesystem->put($filename, json_encode(['collectorName' => $this->collector, 'collectorData' => $collectorResult])) === false) {
             Log::error(get_class($this) . ': ' . 'Unable to write file: ' . $filename);
             $this->exception();
         }
         chown($path . $filename, 'abuseio');
         chgrp($path . $filename, 'abuseio');
         /**
          * save evidence into table
          **/
         $evidence = new Evidence();
         $evidence->filename = $filename;
         $evidence->sender = 'abuse@localhost';
         $evidence->subject = "CLI Collector {$this->collector}";
         $evidence->save();
         /**
          * call saver
          **/
         $saver = new EventsSave();
         $saverResult = $saver->save($collectorResult['data'], $evidence->id);
         /**
          * We've hit a snag, so we are gracefully killing ourselves
          * after we contact the admin about it. EventsSave should never
          * end with problems unless the mysql died while doing transactions
          **/
         if ($saverResult['errorStatus'] === true) {
             Log::error(get_class($saver) . ': ' . 'Saver has ended with errors ! : ' . $saverResult['errorMessage']);
             $this->exception();
             return;
         } else {
             Log::info(get_class($saver) . ': ' . 'Saver has ended without errors');
         }
     } else {
         Log::warning(get_class($this) . ': ' . 'Collector did not return any events therefore skipping validation and saving a empty event set');
     }
     Log::info(get_class($this) . ': ' . 'Queued worker has ended the processing of collector: ' . $this->collector);
 }