W.I.P. SMIME:

- Override verify method in order to pass certs bundle for verification
- Catch exception if decryption fails because encrypted message perhaps is not encrypted by receiver public key
- Define different states for signature verification
This commit is contained in:
Hadi Nategh 2017-07-25 17:13:49 +02:00
parent c6bf51180f
commit 91fb816bb2
8 changed files with 128 additions and 16 deletions

View File

@ -5611,7 +5611,7 @@ class Mail
if (is_object($mail)) if (is_object($mail))
{ {
$structure = $mail->getStructure(); $structure = $mail->getStructure();
$isSmime = Mail\Smime::isSmime($structure->getType()); $isSmime = Mail\Smime::isSmime($structure->getType()) || Mail\Smime::isSmimeSignatureOnly($structure->getType());
if ($isSmime) if ($isSmime)
{ {
return $this->resolveSmimeMessage($structure, array( return $this->resolveSmimeMessage($structure, array(
@ -7349,13 +7349,19 @@ class Mail
$message = $this->getMessageRawBody($params['uid'], null, $params['mailbox']); $message = $this->getMessageRawBody($params['uid'], null, $params['mailbox']);
if (!Mail\Smime::isSmimeSignatureOnly($params['mimeType'])) if (!Mail\Smime::isSmimeSignatureOnly($params['mimeType']))
{ {
$message = $this->_decryptSmimeBody($message, $params['passphrase'] !='' ? try{
$params['passphrase'] : Api\Cache::getSession('mail', 'smime_passphrase')); $message = $this->_decryptSmimeBody($message, $params['passphrase'] !='' ?
$params['passphrase'] : Api\Cache::getSession('mail', 'smime_passphrase'));
}
catch(\Horde_Crypt_Exception $e)
{
throw new Mail\Smime\PassphraseMissing(lang('Could not decrypt S/MIME data. This message may not be encrypted by your public key.'));
}
$metadata['encrypted'] = true; $metadata['encrypted'] = true;
} }
try { try {
$cert = $this->smime->verify($message); $cert = $this->smime->verifySignature($message);
} catch (\Exception $ex) { } catch (\Exception $ex) {
// passphrase is required to decrypt the message // passphrase is required to decrypt the message
if (isset($message['password_required'])) if (isset($message['password_required']))

View File

@ -39,6 +39,7 @@ class Smime extends Horde_Crypt_Smime
static $SMIME_SIGNATURE_ONLY_TYPES = array ( static $SMIME_SIGNATURE_ONLY_TYPES = array (
'application/x-pkcs7-signature', 'application/x-pkcs7-signature',
'application/pkcs7-signature', 'application/pkcs7-signature',
'multipart/signed'
); );
/** /**
@ -180,4 +181,20 @@ class Smime extends Horde_Crypt_Smime
return Horde_Mime_Part::parseMessage(parent::extractSignedContents($data), array('forcemime' => true)); return Horde_Mime_Part::parseMessage(parent::extractSignedContents($data), array('forcemime' => true));
} }
/**
* Verify a signature
*
* @param type $message
* @return type
*/
public function verifySignature($message)
{
$cert_locations = openssl_get_cert_locations();
$certs = array();
foreach (scandir($cert_locations['default_cert_dir']) as &$file)
{
if (!is_dir($cert_locations['default_cert_dir'].'/'.$file)) $certs[]= $cert_locations['default_cert_dir'].'/'.$file;
}
return $this->verify($message, $certs);
}
} }

View File

@ -3070,7 +3070,12 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
{ {
if ($smimePassphrase) if ($smimePassphrase)
{ {
Api\Cache::setSession('mail', 'smime_passphrase', $smimePassphrase); if ($this->mail_bo->mailPreferences['smime_pass_exp'] != $_POST['smime_pass_exp'])
{
$GLOBALS['egw']->preferences->add('mail', 'smime_pass_exp', $_POST['smime_pass_exp']);
$GLOBALS['egw']->preferences->save_repository();
}
Api\Cache::setSession('mail', 'smime_passphrase', $smimePassphrase, $_POST['smime_pass_exp'] * 60);
} }
$structure = $this->mail_bo->getStructure($uid, $partID, $mailbox, false); $structure = $this->mail_bo->getStructure($uid, $partID, $mailbox, false);
if (($smime = $structure->getMetadata('X-EGroupware-Smime'))) if (($smime = $structure->getMetadata('X-EGroupware-Smime')))
@ -3092,7 +3097,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
{ {
self::callWizard($e->getMessage().' '.lang('Please configure your S/MIME private key in Encryption tab located at Edit Account dialog.')); self::callWizard($e->getMessage().' '.lang('Please configure your S/MIME private key in Encryption tab located at Edit Account dialog.'));
} }
Framework::message($e->getMessage());
// do NOT include any default CSS // do NOT include any default CSS
$smimeHtml = $this->get_email_header(). $smimeHtml = $this->get_email_header().
'<div class="smime-message">'.lang("This message is smime encrypted and password protected.").'</div>'. '<div class="smime-message">'.lang("This message is smime encrypted and password protected.").'</div>'.
@ -3102,7 +3107,10 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
'<input type="password" placeholder="'.lang("Please enter password").'" name="smime_passphrase"/>'. '<input type="password" placeholder="'.lang("Please enter password").'" name="smime_passphrase"/>'.
'<input type="submit" value="'.lang("submit").'"/>'. '<input type="submit" value="'.lang("submit").'"/>'.
'</div>'. '</div>'.
'</form>'; '<div style="top:47%;margin-left:-15px;">'.
lang("Remember the password for ").'<input name="smime_pass_exp" type="number" max="60" min="1" placeholder="10" value="'.$this->mail_bo->mailPreferences['smime_pass_exp'].'"/> '.lang("minutes.").
'</div>'.
'</form>';
return $smimeHtml; return $smimeHtml;
} }
$calendar_part = null; $calendar_part = null;

View File

@ -998,8 +998,10 @@ app.classes.mail = AppJS.extend(
default: default:
widget.set_disabled(true); widget.set_disabled(true);
} }
this.smime_clear_flags([jQuery(widget.getDOMNode())]);
} }
this.smime_clear_flags([jQuery('#mail-index_mailPreviewContainer')]);
// Blank first, so we don't show previous email while loading // Blank first, so we don't show previous email while loading
var IframeHandle = this.et2.getWidgetById('messageIFRAME'); var IframeHandle = this.et2.getWidgetById('messageIFRAME');
IframeHandle.set_src('about:blank'); IframeHandle.set_src('about:blank');
@ -5815,12 +5817,36 @@ app.classes.mail = AppJS.extend(
if (attachmentArea) attachmentArea.getDOMNode().classList.remove('loading'); if (attachmentArea) attachmentArea.getDOMNode().classList.remove('loading');
var smime_signature = this.et2.getWidgetById('smime_signature'); var smime_signature = this.et2.getWidgetById('smime_signature');
var smime_encryption = this.et2.getWidgetById('smime_encryption'); var smime_encryption = this.et2.getWidgetById('smime_encryption');
var $mail_container = egw(window).is_popup() ?
jQuery('.mailDisplayContainer'):
jQuery(this.et2.getWidgetById('mailPreviewContainer').getDOMNode());
smime_signature.set_disabled(!_data.signed);
smime_encryption.set_disabled(!_data.encrypted);
if (!_data.signed)
{
this.smime_clear_flags([$mail_container]);
}
else if (_data.verify)
{
$mail_container.addClass('smime_cert_verified');
smime_signature.set_class('smime_cert_verified');
}
else if (!_data.verify)
{
$mail_container.addClass('smime_cert_notverified');
smime_signature.set_class('smime_cert_notverified');
smime_signature.set_statustext(_data.msg);
}
},
smime_clear_flags: function (_nodes)
{
for(var i=0;i<_nodes.length;i++)
{
var smime_classes = 'smime_cert_verified smime_cert_notverified';
_nodes[i].removeClass(smime_classes);
}
smime_signature.set_disabled(!_data.signed);
smime_encryption.set_disabled(!_data.encrypted);
if (!_data.verify)
{
smime_signature.set_statustext(_data.msg);
}
} }
}); });

View File

@ -911,4 +911,23 @@ div.mailComposeHeaderSection>table {
#mail-compose_mailaccount {max-width: 100% !important;} #mail-compose_mailaccount {max-width: 100% !important;}
.header_row_right.vertical_splitter {float:left;} .header_row_right.vertical_splitter {float:left;}
.header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox {margin-right: 0;} .header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox {margin-right: 0;}
div.smime_cert_notverified {
border-top: 4px solid lightgreen !important;
}
img.smime_cert_notverified {
background: lightgreen !important;
}
div.smime_cert_verified {
border-top: 4px solid green;
}
img.smime_cert_verified {
background: green;
}
div.smime_cert_notvalid {
border-top: 4px solid red;
}
img.smime_cert_notvalid {
background: red;
}

View File

@ -901,6 +901,24 @@ div.mailComposeHeaderSection > table {
.header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox { .header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox {
margin-right: 0; margin-right: 0;
} }
div.smime_cert_notverified {
border-top: 4px solid lightgreen !important;
}
img.smime_cert_notverified {
background: lightgreen !important;
}
div.smime_cert_verified {
border-top: 4px solid green;
}
img.smime_cert_verified {
background: green;
}
div.smime_cert_notvalid {
border-top: 4px solid red;
}
img.smime_cert_notvalid {
background: red;
}
#popupMainDiv { #popupMainDiv {
padding: 5px; padding: 5px;
} }

View File

@ -889,6 +889,24 @@ div.mailComposeHeaderSection > table {
.header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox { .header_row_right.vertical_splitter div#mail-index_mail-index-vacationnotice .et2_vbox {
margin-right: 0; margin-right: 0;
} }
div.smime_cert_notverified {
border-top: 4px solid lightgreen !important;
}
img.smime_cert_notverified {
background: lightgreen !important;
}
div.smime_cert_verified {
border-top: 4px solid green;
}
img.smime_cert_verified {
background: green;
}
div.smime_cert_notvalid {
border-top: 4px solid red;
}
img.smime_cert_notvalid {
background: red;
}
#popupMainDiv { #popupMainDiv {
padding: 5px; padding: 5px;
} }

View File

@ -76,7 +76,7 @@ body {
select {margin-top: 9px;} select {margin-top: 9px;}
} // Ende Filter } // Ende Filter
} // Ende Header } // Ende Header
// Bilder in den Listen // Bilder in den Listen
tr.mail td img { tr.mail td img {
max-height: 50px; max-height: 50px;