You are here

protected function PGPAnalyzer::isSigned in Mailhandler 8

Returns flag whether the message is signed.

Parameters

\Drupal\inmail\MIME\MimeMessageInterface $message: The message to check signature.

\Drupal\inmail\DefaultAnalyzerResult $result: The analyzer result.

array $context: An array to provide context data in case the message is signed.

Return value

bool TRUE if message is signed. Otherwise, FALSE.

1 call to PGPAnalyzer::isSigned()
PGPAnalyzer::analyze in src/Plugin/inmail/Analyzer/PGPAnalyzer.php

File

src/Plugin/inmail/Analyzer/PGPAnalyzer.php, line 69

Class

PGPAnalyzer
An analyzer for PGP signed messages.

Namespace

Drupal\mailhandler\Plugin\inmail\Analyzer

Code

protected function isSigned(MimeMessageInterface $message, DefaultAnalyzerResult $result, array &$context) {

  // Support PGP/MIME signed messages.
  if ($message instanceof MimeMultipartMessage) {
    $parameters = $message
      ->getContentType()['parameters'];

    // As per https://tools.ietf.org/html/rfc2015#section-4, content type must
    // have a protocol parameter with "application/pgp-signature" value.
    if (!empty($parameters['protocol']) && $parameters['protocol'] == 'application/pgp-signature') {
      foreach ($message
        ->getParts() as $index => $part) {

        // Check the subtype of a content type.
        if ($part
          ->getContentType()['subtype'] == 'pgp-signature') {
          $signature = $part
            ->getBody();

          // In order to find a signed text part of the message, we need to
          // skip the signature.
          $message_parts = array_diff(array_keys($message
            ->getParts()), [
            $index,
          ]);
          $signed_text_index = reset($message_parts);
          $signed_text_part = $message
            ->getPart($signed_text_index);

          // Add index of the signed message part to the context.
          $context['signed_text_index'] = $signed_text_index;
          $context_definition = new ContextDefinition('any', $this
            ->t('PGP context'));
          $context_data = [
            'pgp_type' => 'mime',
            // Include headers into the signed text.
            'signed_text' => $signed_text_part
              ->toString(),
            'signature' => $signature,
          ];
          $result
            ->setContext('pgp', new Context($context_definition, $context_data));

          // Update the subject field.
          if ($signed_text_part
            ->getHeader()
            ->hasField('Subject')) {
            $result
              ->setSubject($signed_text_part
              ->getHeader()
              ->getFieldBody('Subject'));
          }
          return TRUE;
        }
      }
    }
  }
  else {

    // Cleartext signed message validation was implemented by following
    // RFC 4880. See https://tools.ietf.org/html/rfc4880#section-7
    $message_body = $message
      ->getBody();
    $starts_with_pgp_header = strpos($message_body, "-----BEGIN PGP SIGNED MESSAGE-----\nHash:") === 0;
    if ($starts_with_pgp_header) {
      $has_pgp_signature = (bool) strpos($message_body, "-----BEGIN PGP SIGNATURE-----\n");
      $pgp_signature_end = '-----END PGP SIGNATURE-----';
      $ends_with_pgp_signature = trim(strstr($message_body, "\n{$pgp_signature_end}")) === $pgp_signature_end;
      if ($has_pgp_signature && $ends_with_pgp_signature) {

        // Add a PGP context.
        $context_definition = new ContextDefinition('any', $this
          ->t('PGP context'));
        $context_data = [
          'pgp_type' => 'inline',
          'signed_text' => $message_body,
          'signature' => FALSE,
        ];
        $result
          ->setContext('pgp', new Context($context_definition, $context_data));
        return TRUE;
      }
    }
  }
  return FALSE;
}