Beispiel #1
0
 /**
  * Verify a integrity of a signed message
  *
  * @return array
  */
 public static function verifyIntegrity($msg, $path)
 {
     $return = array();
     if (!empty($msg)) {
         // creates temporary files
         $temporary_files = array();
         $msgTempFile = self::generateTempFilename($temporary_files, $path);
         if (!self::writeTo($msgTempFile, $msg)) {
             $return['success'] = false;
             $return['msgs'] = array("Coudn't write temporary files!");
         }
         // do verification
         $result = openssl_pkcs7_verify($msgTempFile, PKCS7_NOVERIFY);
         if ($result === -1 || !$result) {
             // error
             $return['success'] = false;
             $return['msgs'] = self::getOpensslErrors();
         } else {
             $return['success'] = true;
             $return['msgs'] = array("Verification Successful");
         }
         self::removeTempFiles($temporary_files);
         return $return;
     } else {
         return array('success' => false, 'msgs' => array("Empty message"));
     }
 }
Beispiel #2
0
function smime_validate($message, $cacerts, &$signer_pem)
{
    $signer_pem = NULL;
    $decoded = json_decode($message, true);
    if (!is_null($decoded)) {
        /* Decoding succeeded, so not smime encoded. */
        /* smime_debug("smime_validate: no smime detected."); */
        return $message;
    } else {
        smime_debug("smime_validate: smime detected.");
    }
    $msg_file = writeDataToTempFile($message, "smime-msg-");
    $flags = 0;
    $signer_cert_file = tempnam(sys_get_temp_dir(), "smime-signer-");
    /* This is ugly, but it is what it is. There is no way to get the
       contents of the signed mssage without extracerts specified. And
       there is no way to pass a NULL to extacerts, or to have
       extracerts be an empty file. Sooo, put the first CA into that
       file. Ugly. */
    $extracerts_contents = file_get_contents($cacerts[0]);
    $extracerts_file = writeDataToTempFile($extracerts_contents, "smime-extra-");
    $content_file = tempnam(sys_get_temp_dir(), "smime-content-");
    $result = openssl_pkcs7_verify($msg_file, $flags, $signer_cert_file, $cacerts, $extracerts_file, $content_file);
    /* Note the triple equals, requiring the *same type*. Two equal
       signs will match the boolean TRUE result, causing programmer
       confusion. */
    if ($result === -1) {
        /* An error occurred. */
        error_log("An error occurred trying to verify the message.");
        /* Print out as many errors as openssl can offer. */
        while ($msg = openssl_error_string()) {
            error_log("openssl_error: {$msg}");
        }
        $message = NULL;
    } else {
        if ($result) {
            smime_debug("smime_validate: successful verification.");
            $message = file_get_contents($content_file);
            $signer_pem = file_get_contents($signer_cert_file);
        } else {
            /* Verification failed. */
            error_log("The message failed to verify.");
            $message = NULL;
        }
    }
    unlink($msg_file);
    unlink($signer_cert_file);
    unlink($extracerts_file);
    unlink($content_file);
    return $message;
}
Beispiel #3
0
function test_openssl_pkcs7_sign()
{
    $privkey = openssl_pkey_new();
    VERIFY($privkey != null);
    $csr = openssl_csr_new(null, $privkey);
    VERIFY($csr != null);
    $scert = openssl_csr_sign($csr, null, $privkey, 365);
    $pubkey = openssl_csr_get_public_key($csr);
    VERIFY($pubkey != null);
    $data = "some secret data";
    $infile = tempnam('/tmp', 'invmtestopenssl');
    $outfile = tempnam('/tmp', 'outvmtestopenssl');
    unlink($infile);
    unlink($outfile);
    file_put_contents($infile, $data);
    VERIFY(openssl_pkcs7_sign($infile, $outfile, $scert, $privkey, array("To" => "*****@*****.**", "From" => "*****@*****.**")));
    $tmp = tempnam('/tmp', 'x509vmtestopenssl');
    unlink($tmp);
    VS(file_get_contents($tmp), false);
    VERIFY(openssl_x509_export_to_file($scert, $tmp));
    VS(openssl_pkcs7_verify($outfile, 0, $infile, (array) $tmp), true);
    unlink($infile);
    unlink($outfile);
    unlink($tmp);
}
Beispiel #4
0
 /**
  * Takes a message with an S/MIME signature and verifies it if possible
  * 
  * @param array &$info       The array of information about a message
  * @param array $structure
  * @param array $smime_pair  An associative array containing an S/MIME certificate file
  * @return boolean  If the message was verified
  */
 private static function handleSMIMEVerification(&$info, $structure, $smime_pair)
 {
     $certificates_file = tempnam('', '__fMailbox_');
     $ciphertext_file = tempnam('', '__fMailbox_');
     file_put_contents($ciphertext_file, $info['raw_message']);
     $result = openssl_pkcs7_verify($ciphertext_file, PKCS7_NOINTERN | PKCS7_NOVERIFY, $certificates_file, array(), $smime_pair['certificate']->getPath());
     unlink($ciphertext_file);
     unlink($certificates_file);
     if (!$result || $result === -1) {
         return FALSE;
     }
     $info['verified'] = TRUE;
     return TRUE;
 }
 protected function assertValidVerify($expected, Swift_ByteStream_TemporaryFileByteStream $messageStream)
 {
     $actual = $messageStream->getContent();
     // File is UNIX encoded so convert them to correct line ending
     $expected = str_replace("\n", "\r\n", $expected);
     $actual = trim(self::getBodyOfMessage($actual));
     if (!$this->assertRegExp('%^' . $expected . '$\\s*%m', $actual)) {
         return false;
     }
     $opensslOutput = new Swift_ByteStream_TemporaryFileByteStream();
     $verify = openssl_pkcs7_verify($messageStream->getPath(), null, $opensslOutput->getPath(), array($this->samplesDir . 'smime/ca.crt'));
     if (false === $verify) {
         $this->fail('Verification of the message failed.');
         return false;
     } elseif (-1 === $verify) {
         $this->fail(sprintf('Verification of the message failed. Internal error "%s".', openssl_error_string()));
         return false;
     }
     return true;
 }
 function verify($struct, $message)
 {
     // use common temp dir
     $temp_dir = $this->rc->config->get('temp_dir');
     $msg_file = tempnam($temp_dir, 'rcmMsg');
     $cert_file = tempnam($temp_dir, 'rcmCert');
     $fh = fopen($msg_file, "w");
     if ($struct->mime_id) {
         $message->get_part_body($struct->mime_id, false, 0, $fh);
     } else {
         $this->rc->storage->get_raw_body($message->uid, $fh);
     }
     fclose($fh);
     // @TODO: use stored certificates
     // try with certificate verification
     $sig = openssl_pkcs7_verify($msg_file, 0, $cert_file);
     $validity = true;
     if ($sig !== true) {
         // try without certificate verification
         $sig = openssl_pkcs7_verify($msg_file, PKCS7_NOVERIFY, $cert_file);
         $validity = enigma_error::UNVERIFIED;
     }
     if ($sig === true) {
         $sig = $this->parse_sig_cert($cert_file, $validity);
     } else {
         $errorstr = $this->get_openssl_error();
         $sig = new enigma_error(enigma_error::INTERNAL, $errorstr);
     }
     // remove temp files
     @unlink($msg_file);
     @unlink($cert_file);
     return $sig;
 }
 /**
  * Verify a integrity of a signed message
  *
  * @return array
  */
 public static function verify($rawHeaders, $rawBody, $fromEmail, $smime)
 {
     $return = array();
     $path = Tinebase_Core::getTempDir();
     $translate = Tinebase_Translation::getTranslation('Expressomail');
     $ret_type = False;
     if (!empty($rawHeaders) && !empty($rawBody)) {
         $msg = $rawHeaders . $rawBody;
         $ret_type = null;
         if ($smime == Expressomail_Smime::TYPE_ENVELOPED_DATA_VALUE || $smime == Expressomail_Smime::TYPE_SIGNED_DATA_VALUE) {
             $ret_type = self::verify_p7m($rawBody);
             // Encrypted Message ??
             if ($ret_type == 'cipher') {
                 $return['success'] = false;
                 $return['msgs'] = array("Encrypted Message.");
                 $return['ret_type'] = $ret_type;
                 // return raw msg to others process.
                 $return['content'] = $msg;
                 return $return;
             }
         }
         $config = Tinebase_Config::getInstance()->get('modssl');
         // creates temporary files
         $temporary_files = array();
         $msgTempFile = self::generateTempFilename($temporary_files, $path);
         if (!self::writeTo($msgTempFile, $msg)) {
             $return['success'] = false;
             $return['msgs'] = array("Coudn't write temporary files!");
         }
         $certificateTempFile = self::generateTempFilename($temporary_files, $path);
         $contentTempFile = self::generateTempFilename($temporary_files, $path);
         // do verification
         $result = openssl_pkcs7_verify($msgTempFile, 0, $certificateTempFile, array($config->casfile), $config->casfile, $contentTempFile);
         if (is_file($certificateTempFile)) {
             $aux_certificate = file_get_contents($certificateTempFile);
         } else {
             $aux_certificate = '';
         }
         if ($aux_certificate != '') {
             // E-mail validation is unskipable, we always verify chain and crls
             $certificate = Custom_Auth_ModSsl_Certificate_Factory::buildCertificate($aux_certificate, TRUE);
         } else {
             // try get certificate from message (other way) ....
             $certificate = self::pullCertificateFromMessage($msgTempFile);
         }
         if ($result === -1 || !$result) {
             // error on openssl_pkcs7_verify() call
             $return['success'] = false;
             $return['msgs'] = self::getOpensslErrors();
             if ($certificate) {
                 $return['certificate'] = $certificate->toArray();
             }
         } else {
             $mailMismatch = $fromEmail !== $certificate->getEmail();
             if ($certificate->isValid()) {
                 if (!$mailMismatch) {
                     $return['success'] = true;
                     $return['msgs'] = array('Message Verification Successful');
                 }
                 // If certificate is valid store it in database
                 $controller = Addressbook_Controller_Certificate::getInstance();
                 try {
                     $controller->create(new Addressbook_Model_Certificate($certificate));
                 } catch (Tinebase_Exception_Duplicate $e) {
                     // Fail silently if certificate already exists
                 }
             } else {
                 $return['success'] = false;
                 $return['msgs'] = $certificate->getStatusErrors();
                 if ($mailMismatch) {
                     $return['msgs'][] = $translate->_('Sender\'s email is different from Digital Certificate\'s email');
                 }
             }
             $return['certificate'] = $certificate->toArray();
         }
         if (is_file($contentTempFile)) {
             // get original msg
             $return['content'] = file_get_contents($contentTempFile);
         }
         if ($ret_type) {
             $return['ret_type'] = $ret_type;
         }
         self::removeTempFiles($temporary_files);
         return $return;
     } else {
         return array('success' => false, 'msgs' => array("Empty message"));
     }
 }
Beispiel #8
0
 /**
  * @fn string _load_signed_file(string $filename)
  * @brief A function which loads the data from SMIME siggned file.
  *
  * This function loads the data from SMIME (PKCS7) signed file, verify file sign for validity of
  * SmartPPC6 system.
  *
  * @param $filename a string which contains name of the SMIME signed file.
  * @return a string which contains contents of SMIME signed file if sign is valid and sign was made
  *         with valid SmartPPC6 cerificate or FALSE on failures.
  */
 function _load_signed_file($filename)
 {
     if (!file_exists($filename)) {
         return false;
     }
     // check CA certificate for validity of smartppc6
     $x509 = $this->_load_CA();
     if ($x509 === false) {
         return false;
     }
     openssl_x509_free($x509);
     // check signer certificate for validity of smartppc6
     $x509 = $this->_load_cert();
     if ($x509 === false) {
         return false;
     }
     openssl_x509_free($x509);
     $signer_cert_out = tempnam('/tmp', 'smartppc6');
     $content_out = tempnam('/tmp', 'smartppc6');
     $result_content = false;
     $phpversion = phpversion();
     if (version_compare($phpversion, "5.1.0", "<")) {
         $cmd = sprintf('openssl smime -signer %s -verify -in %s -nointern -nochain -CAfile %s -certfile %s -out %s 2> /dev/null', escapeshellcmd($signer_cert_out), escapeshellcmd($filename), escapeshellcmd(SSL_CA_FILE), escapeshellcmd(SSL_CERT_FILE), escapeshellcmd($content_out));
         system($cmd, $retval);
         if ($retval == 0) {
             $result = true;
         }
     } else {
         $result = openssl_pkcs7_verify($filename, PKCS7_NOVERIFY, $signer_cert_out, array(SSL_CA_FILE), SSL_CERT_FILE, $content_out);
     }
     if ($result === true) {
         $result_content = file_get_contents($content_out);
     }
     if (file_exists($signer_cert_out)) {
         unlink($signer_cert_out);
     }
     if (file_exists($content_out)) {
         unlink($content_out);
     }
     return $result_content;
 }
Beispiel #9
0
 public function verifyx509($fin, $fout, $c = array(), $p = null, $o = null, $f = PKCS7_TEXT)
 {
     openssl_pkcs7_verify($fin, $f, $fout, $c, $p, $o);
     return $fout;
 }
Beispiel #10
0
 /**
  * @param string $mime
  * @param $chain
  *
  * @return bool
  */
 public function verify(string $mime, $chain) : bool
 {
     $inputFileName = new TempFile('smime_signed_');
     $inputFileName->setContent($mime);
     $status = openssl_pkcs7_verify($inputFileName, $this->getFlags(), '/dev/null', [], $chain);
     if (!is_bool($status)) {
         throw new RuntimeException(OpenSSL::getLastError());
     }
     return $status;
 }
Beispiel #11
0
 /**
  * __checkSignatureAndGetSigner - Checks the signature and extracts the signer certificate and it's serialnumber
  * #params     string    Base64 encoded signature
  * #params     string    verification of the message that should have been signed
  * #params     string    location of Certificate Authority file that should be used during verificaton
  * @return     boolean   
  */
 private function __checkSignatureAndGetSigner($signature, $message, $cafile)
 {
     assert('is_string($signature)');
     assert('is_string($message)');
     assert('is_string($cafile)');
     /* Check for provided file existence */
     if (!file_exists($cafile)) {
         trigger_error('mobileid::__checkSignatureAndGetSigner: file not found ' . $cafile, E_USER_WARNING);
     }
     /* Define temporary files */
     $tmpfile = tempnam(sys_get_temp_dir(), '_mid_');
     $file_sig = $tmpfile . '.sig';
     $file_sig_cert = $tmpfile . '.crt';
     $file_sig_msg = $tmpfile . '.msg';
     /* Chunk spliting the signature */
     $signature = chunk_split($signature, 64, "\n");
     /* This because the openssl_pkcs7_verify() function needs some mime headers to make it work */
     $signature = "MIME-Version: 1.0\nContent-Disposition: attachment;\n        filename=\"dummy.p7m\"\nContent-Type: application/x-pkcs7-mime;\n        name=\"dummy.p7m\"\nContent-Transfer-Encoding: base64\n\n" . $signature;
     /* Write the signature into temp files */
     file_put_contents($file_sig, $signature);
     /* Signature checks must explicitly succeed */
     $ok = false;
     /* Get the signer certificate */
     $status = openssl_pkcs7_verify($file_sig, PKCS7_NOVERIFY, $file_sig_cert);
     if ($status == true && file_exists($file_sig_cert)) {
         /* Get the signer certificate and details */
         $this->mid_certificate = file_get_contents($file_sig_cert);
         $certificate = openssl_x509_parse($this->mid_certificate);
         $this->mid_serialnumber = $certificate['subject']['serialNumber'];
         /* Verify message has been signed */
         $data = '';
         $status = openssl_pkcs7_verify($file_sig, PKCS7_NOVERIFY, $file_sig_cert, array($cafile), $file_sig_cert, $file_sig_msg);
         if (file_exists($file_sig_msg)) {
             $data = file_get_contents($file_sig_msg);
             if ($data === $message) {
                 $ok = true;
             }
         } else {
             trigger_error('mobileid::__checkSignatureAndGetSigner: signed message ' . openssl_error_string(), E_USER_NOTICE);
         }
         /* Verify signer issued by trusted CA */
         $status = openssl_x509_checkpurpose($this->mid_certificate, X509_PURPOSE_SSL_CLIENT, array($cafile));
         if ($status != true) {
             $ok = false;
             trigger_error('mobileid::__checkSignatureAndGetSigner: certificate check ' . openssl_error_string(), E_USER_NOTICE);
         }
     } else {
         trigger_error('mobileid::__checkSignatureAndGetSigner: signer certificate ' . openssl_error_string(), E_USER_NOTICE);
     }
     /* Cleanup of temporary files */
     if (file_exists($tmpfile)) {
         unlink($tmpfile);
     }
     if (file_exists($file_sig)) {
         unlink($file_sig);
     }
     if (file_exists($file_sig_cert)) {
         unlink($file_sig_cert);
     }
     if (file_exists($file_sig_msg)) {
         unlink($file_sig_msg);
     }
     /* Signature checks failed? */
     if (!$ok) {
         $this->statuscode = '503';
         $this->statusmessage = 'INVALID_SIGNATURE';
     }
     return $ok;
 }
 public function actionVerify($params)
 {
     $response['success'] = true;
     $params['email'] = strtolower($params['email']);
     //if file was already stored somewhere after decryption
     if (!empty($params['cert_id'])) {
         $cert = \GO\Smime\Model\PublicCertificate::model()->findByPk($params['cert_id']);
         $certData = $cert->cert;
     } else {
         //			if (!empty($params['filepath'])) {
         //				$srcFile = new \GO\Base\Fs\File(\GO::config()->tmpdir.$params['filepath']);
         if (!empty($params['account_id'])) {
             $account = \GO\Email\Model\Account::model()->findByPk($params['account_id']);
             $imapMessage = \GO\Email\Model\ImapMessage::model()->findByUid($account, $params['mailbox'], $params['uid']);
             $srcFile = \GO\Base\Fs\File::tempFile();
             if (!$imapMessage->saveToFile($srcFile->path())) {
                 throw new \Exception("Could not fetch message from IMAP server");
             }
             $this->_decryptFile($srcFile, $account);
         }
         //			throw new \Exception($srcFile->path());
         $pubCertFile = \GO\Base\Fs\File::tempFile();
         //Command line:
         //openssl smime -verify -in msg.txt
         $valid = openssl_pkcs7_verify($srcFile->path(), null, $pubCertFile->path(), $this->_getRootCertificates());
         //Adding the PKCS7_NOVERIFY flag was used for testing some messages that could not be verified by openssl but did in Mozilla thunderbird.
         //Error msg: error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error
         //
         //			$valid = openssl_pkcs7_verify($srcFile->path(), PKCS7_NOVERIFY, $pubCertFile->path(), $this->_getRootCertificates());
         //			throw new \Exception($srcFile->path());
         $srcFile->delete();
         if ($valid) {
             if ($pubCertFile->exists()) {
                 $certData = $pubCertFile->getContents();
                 $arr = openssl_x509_parse($certData);
                 $senderEmailStr = !empty($arr['extensions']['subjectAltName']) ? $arr['extensions']['subjectAltName'] : $arr['subject']['emailAddress'];
                 $senderEmails = explode(',', $senderEmailStr);
                 $emails = array();
                 foreach ($senderEmails as $emailRaw) {
                     $email = strtolower(\GO\Base\Util\String::get_email_from_string($emailRaw));
                     if ($email) {
                         $emails[] = $email;
                     }
                 }
                 $pubCertFile->delete();
                 $this->_savePublicCertificate($certData, $emails);
             } else {
                 throw new \Exception('Certificate appears to be valid but could not get certificate from signature. SSL Error: ' . openssl_error_string());
             }
             if (empty($certData)) {
                 throw new \Exception('Certificate appears to be valid but could not get certificate from signature.');
             }
         }
     }
     if (!isset($arr) && isset($certData)) {
         $arr = openssl_x509_parse($certData);
         $senderEmailStr = !empty($arr['extensions']['subjectAltName']) ? $arr['extensions']['subjectAltName'] : $arr['subject']['emailAddress'];
         $emails = array();
         foreach ($senderEmails as $emailRaw) {
             $email = strtolower(\GO\Base\Util\String::get_email_from_string($emailRaw));
             if ($email) {
                 $emails[] = $email;
             }
         }
     } else {
         if (empty($emails)) {
             $emails = array('unknown');
         }
     }
     $response['html'] = '';
     $response['cls'] = '';
     $response['text'] = '';
     if (isset($params['account_id'])) {
         if (!$valid) {
             $response['cls'] = 'smi-invalid';
             $response['text'] = \GO::t('invalidCert', 'smime');
             $response['html'] .= '<h1 class="smi-invalid">' . \GO::t('invalidCert', 'smime') . '</h1>';
             $response['html'] .= '<p>';
             while ($msg = openssl_error_string()) {
                 $response['html'] .= $msg . "<br />\n";
             }
             $response['html'] .= '</p>';
         } else {
             if (!in_array($params['email'], $emails)) {
                 $response['cls'] = 'smi-certemailmismatch';
                 $response['text'] = \GO::t('certEmailMismatch', 'smime');
                 $response['html'] .= $response['short_html'] = '<h1 class="smi-certemailmismatch">' . \GO::t('certEmailMismatch', 'smime') . '</h1>';
             } else {
                 $response['cls'] = 'smi-valid';
                 $response['text'] = \GO::t('validCert', 'smime');
                 $response['html'] .= $response['short_html'] = '<h1 class="smi-valid">' . \GO::t('validCert', 'smime') . '</h1>';
             }
         }
     }
     if (!isset($params['account_id']) || $valid) {
         $response['html'] .= '<table>';
         $response['html'] .= '<tr><td width="100">' . \GO::t('name') . ':</td><td>' . $arr['name'] . '</td></tr>';
         $response['html'] .= '<tr><td width="100">' . \GO::t('email', 'smime') . ':</td><td>' . implode(', ', $emails) . '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('hash', 'smime') . ':</td><td>' . $arr['hash'] . '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('serial_number', 'smime') . ':</td><td>' . $arr['serialNumber'] . '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('version', 'smime') . ':</td><td>' . $arr['version'] . '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('issuer', 'smime') . ':</td><td>';
         foreach ($arr['issuer'] as $skey => $svalue) {
             if (is_array($svalue)) {
                 foreach ($svalue as $sv) {
                     $response['html'] .= $skey . ':' . $sv . '; ';
                 }
             } else {
                 $response['html'] .= $skey . ':' . $svalue . '; ';
             }
         }
         $response['html'] .= '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('valid_from', 'smime') . ':</td><td>' . \GO\Base\Util\Date::get_timestamp($arr['validFrom_time_t']) . '</td></tr>';
         $response['html'] .= '<tr><td>' . \GO::t('valid_to', 'smime') . ':</td><td>' . \GO\Base\Util\Date::get_timestamp($arr['validTo_time_t']) . '</td></tr>';
         $response['html'] .= '</table>';
     }
     return $response;
 }
Beispiel #13
-1
 public static function toOutputArray(array &$response, \GO\Email\Model\ImapMessage $imapMessage)
 {
     if ($imapMessage->content_type == 'application/x-pkcs7-mime') {
         $imapMessage->content_type = 'application/pkcs7-mime';
     }
     if ($imapMessage->content_type == 'application/pkcs7-mime' && isset($imapMessage->content_type_attributes['smime-type']) && $imapMessage->content_type_attributes['smime-type'] == 'signed-data') {
         //signed data but not in clear text. Outlook has this option.
         $outfile = \GO\Base\Fs\File::tempFile();
         $imapMessage->getImapConnection()->save_to_file($imapMessage->uid, $outfile->path());
         $verifyOutfile = \GO\Base\Fs\File::tempFile();
         //			$cmd = '/usr/bin/openssl smime -verify -in ' . $outfile->path() . ' -out ' . $verifyOutfile->path();
         //			exec($cmd);
         //
         //PHP can't output the verified data without the signature without
         //suppling the extracerts option. We generated a dummy certificate for
         //this.
         openssl_pkcs7_verify($outfile->path(), null, "/dev/null", array(), GO::config()->root_path . "modules/smime/dummycert.pem", $verifyOutfile->path());
         $message = \GO\Email\Model\SavedMessage::model()->createFromMimeData($verifyOutfile->getContents());
         //remove temp files
         $outfile->delete();
         $verifyOutfile->delete();
         $newResponse = $message->toOutputArray(true);
         unset($newResponse['to']);
         unset($newResponse['cc']);
         foreach ($newResponse as $key => $value) {
             if (!empty($value) || $key == 'attachments') {
                 $response[$key] = $value;
             }
         }
         //			$response['path'] = $outfile->stripTempPath();
         return;
     }
     if ($imapMessage->content_type == 'application/pkcs7-mime') {
         $encrypted = !isset($imapMessage->content_type_attributes['smime-type']) || $imapMessage->content_type_attributes['smime-type'] != 'signed-data';
         if ($encrypted) {
             GO::debug("Message is encrypted");
             $cert = Model\Certificate::model()->findByPk($imapMessage->account->id);
             if (!$cert || empty($cert->cert)) {
                 GO::debug('SMIME: No private key at all found for this account');
                 $response['htmlbody'] = GO::t('noPrivateKeyForDecrypt', 'smime');
                 return false;
             }
             if (isset($_REQUEST['password'])) {
                 GO::session()->values['smime']['passwords'][$imapMessage->account->id] = $_REQUEST['password'];
             }
             if (!isset(GO::session()->values['smime']['passwords'][$imapMessage->account->id])) {
                 $response['askPassword'] = true;
                 GO::debug("Need to ask for password");
                 return false;
             }
         }
         $attachments = $imapMessage->getAttachments();
         $att = array_shift($attachments);
         //			array (
         //      'type' => 'application',
         //      'subtype' => 'pkcs7-mime',
         //      'smime-type' => 'enveloped-data',
         //      'name' => 'smime.p7m',
         //      'id' => false,
         //      'encoding' => 'base64',
         //      'size' => '2302',
         //      'md5' => false,
         //      'disposition' => false,
         //      'language' => false,
         //      'location' => false,
         //      'charset' => false,
         //      'lines' => false,
         //      'number' => 1,
         //      'extension' => 'p7m',
         //      'human_size' => '2,2 KB',
         //      'tmp_file' => false,
         //    )
         $infile = \GO\Base\Fs\File::tempFile();
         $outfile = \GO\Base\Fs\File::tempFile();
         //$outfilerel = $reldir . 'unencrypted.txt';
         if ($encrypted) {
             GO::debug('Message is encrypted');
             //				$imapMessage->getImapConnection()->save_to_file($imapMessage->uid, $infile->path(), 'TEXT', 'base64');
             //				throw new \Exception($infile->path());
             if (!$imapMessage->saveToFile($infile->path())) {
                 throw new \Exception("Could not save IMAP message to file for decryption");
             }
             $password = GO::session()->values['smime']['passwords'][$imapMessage->account->id];
             openssl_pkcs12_read($cert->cert, $certs, $password);
             if (empty($certs)) {
                 //password invalid
                 $response['askPassword'] = true;
                 GO::debug("Invalid password");
                 return false;
             }
             $return = openssl_pkcs7_decrypt($infile->path(), $outfile->path(), $certs['cert'], array($certs['pkey'], $password));
             $infile->delete();
             if (!$return || !$outfile->exists() || !$outfile->size()) {
                 $response['htmlbody'] = GO::t('decryptionFailed', 'smime') . '<br />';
                 while ($str = openssl_error_string()) {
                     $response['htmlbody'] .= '<br />' . $str;
                 }
                 GO::debug("Decryption failed");
                 return false;
             } else {
                 //check if also signed
                 $data = $outfile->getContents();
                 if (strpos($data, 'signed-data')) {
                     $verifyOutfile = \GO\Base\Fs\File::tempFile();
                     openssl_pkcs7_verify($outfile->path(), null, "/dev/null", array(), GO::config()->root_path . "modules/smime/dummycert.pem", $verifyOutfile->path());
                     $outfile = $verifyOutfile;
                 }
                 $message = \GO\Email\Model\SavedMessage::model()->createFromMimeData($outfile->getContents());
                 $newResponse = $message->toOutputArray(true);
                 unset($newResponse['to']);
                 unset($newResponse['to_string']);
                 unset($newResponse['cc']);
                 foreach ($newResponse as $key => $value) {
                     if (!empty($value) || $key == 'attachments') {
                         $response[$key] = $value;
                     }
                 }
                 $response['smime_encrypted'] = true;
                 //$response['path']=$outfile->stripTempPath();
                 $outfile->delete();
             }
         } else {
             GO::debug('Message is NOT encrypted');
         }
     }
 }
Beispiel #14
-1
 /**
  * Verify a signature using via S/MIME.
  *
  * @param string $text  The multipart/signed data to be verified.
  * @param mixed $certs  Either a single or array of root certificates.
  *
  * @return stdClass  Object with the following elements:
  * <pre>
  * cert - (string) The certificate of the signer stored in the message (in
  *        PEM format).
  * email - (string) The email of the signing person.
  * msg - (string) Status string.
  * verify - (boolean) True if certificate was verified.
  * </pre>
  * @throws Horde_Crypt_Exception
  */
 public function verify($text, $certs)
 {
     /* Check for availability of OpenSSL PHP extension. */
     $this->checkForOpenSSL();
     /* Create temp files for input/output. */
     $input = $this->_createTempFile('horde-smime');
     $output = $this->_createTempFile('horde-smime');
     /* Write text to file */
     file_put_contents($input, $text);
     unset($text);
     $root_certs = array();
     if (!is_array($certs)) {
         $certs = array($certs);
     }
     foreach ($certs as $file) {
         if (file_exists($file)) {
             $root_certs[] = $file;
         }
     }
     $ob = new stdClass();
     if (!empty($root_certs) && openssl_pkcs7_verify($input, 0, $output, $root_certs) === true) {
         /* Message verified */
         $ob->msg = Horde_Crypt_Translation::t("Message verified successfully.");
         $ob->verify = true;
     } else {
         /* Try again without verfying the signer's cert */
         $result = openssl_pkcs7_verify($input, PKCS7_NOVERIFY, $output);
         if ($result === -1) {
             throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - an unknown error has occurred."));
         } elseif ($result === false) {
             throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - this message may have been tampered with."));
         }
         $ob->msg = Horde_Crypt_Translation::t("Message verified successfully but the signer's certificate could not be verified.");
         $ob->verify = false;
     }
     $ob->cert = file_get_contents($output);
     $ob->email = $this->getEmailFromKey($ob->cert);
     return $ob;
 }