mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
WIP of SMIME support:
- Implement smime ecryption in compose - Implement passphrase dialog
This commit is contained in:
parent
e1e9ab8f8e
commit
116151a092
16
api/templates/default/password.xet
Normal file
16
api/templates/default/password.xet
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE overlay PUBLIC "-//EGroupware GmbH//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
|
||||||
|
<!-- $Id$ -->
|
||||||
|
<overlay>
|
||||||
|
<template id="etemplate.password" template="" lang="" group="0" version="16.1">
|
||||||
|
<vbox width="250px" class="ui-dialog-content">
|
||||||
|
<label class="et2_fullWidth" id="message"/>
|
||||||
|
<hbox>
|
||||||
|
<image src="password" class="dialog_icon"/>
|
||||||
|
<hbox>
|
||||||
|
<passwd id="value" width="80%" blur="enter your passphrase"/>
|
||||||
|
</hbox>
|
||||||
|
</hbox>
|
||||||
|
</vbox>
|
||||||
|
</template>
|
||||||
|
</overlay>
|
@ -212,13 +212,21 @@ class mail_compose
|
|||||||
'onExecute' => 'javaScript:app.mail.compose_saveDraft2fm',
|
'onExecute' => 'javaScript:app.mail.compose_saveDraft2fm',
|
||||||
'hint' => 'Save the drafted message as eml file into VFS'
|
'hint' => 'Save the drafted message as eml file into VFS'
|
||||||
),
|
),
|
||||||
'sign' => array (
|
'smime_sign' => array (
|
||||||
'caption' => 'Sign',
|
'caption' => 'Sign',
|
||||||
'icon' => 'smimeSignature',
|
'icon' => 'smimeSignature',
|
||||||
'group' => ++$group,
|
'group' => ++$group,
|
||||||
'onExecute' => 'javaScript:app.mail.compose_setToggle',
|
'onExecute' => 'javaScript:app.mail.compose_setToggle',
|
||||||
'checkbox' => true,
|
'checkbox' => true,
|
||||||
'hint' => 'Sign your message with smime certificate'
|
'hint' => 'Sign your message with smime certificate'
|
||||||
|
),
|
||||||
|
'smime_encrypt' => array (
|
||||||
|
'caption' => 'SMIME',
|
||||||
|
'icon' => 'smimeEncryption',
|
||||||
|
'group' => ++$group,
|
||||||
|
'onExecute' => 'javaScript:app.mail.compose_setToggle',
|
||||||
|
'checkbox' => true,
|
||||||
|
'hint' => 'Encrypt your message with smime certificate'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
foreach (self::$priorities as $key => $priority)
|
foreach (self::$priorities as $key => $priority)
|
||||||
@ -2346,61 +2354,60 @@ class mail_compose
|
|||||||
*/
|
*/
|
||||||
if ($_formData['attachments'] && $_formData['filemode'] != Vfs\Sharing::ATTACH && !$_autosaving)
|
if ($_formData['attachments'] && $_formData['filemode'] != Vfs\Sharing::ATTACH && !$_autosaving)
|
||||||
{
|
{
|
||||||
$attachment_links = $this->getAttachmentLinks($_formData['attachments'], $_formData['filemode'],
|
$attachment_links = $this->_getAttachmentLinks($_formData['attachments'], $_formData['filemode'],
|
||||||
$_formData['mimeType'] == 'html',
|
$_formData['mimeType'] == 'html',
|
||||||
array_unique(array_merge((array)$_formData['to'], (array)$_formData['cc'], (array)$_formData['bcc'])),
|
array_unique(array_merge((array)$_formData['to'], (array)$_formData['cc'], (array)$_formData['bcc'])),
|
||||||
$_formData['expiration'], $_formData['password']);
|
$_formData['expiration'], $_formData['password']);
|
||||||
}
|
}
|
||||||
if($_formData['mimeType'] == 'html')
|
switch ($_formData['mimeType'])
|
||||||
{
|
{
|
||||||
$body = $_formData['body'];
|
case 'html':
|
||||||
if ($attachment_links)
|
$body = $_formData['body'];
|
||||||
{
|
if ($attachment_links)
|
||||||
if (strpos($body, '<!-- HTMLSIGBEGIN -->') !== false)
|
|
||||||
{
|
{
|
||||||
$body = str_replace('<!-- HTMLSIGBEGIN -->', $attachment_links.'<!-- HTMLSIGBEGIN -->', $body);
|
if (strpos($body, '<!-- HTMLSIGBEGIN -->') !== false)
|
||||||
|
{
|
||||||
|
$body = str_replace('<!-- HTMLSIGBEGIN -->', $attachment_links.'<!-- HTMLSIGBEGIN -->', $body);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$body .= $attachment_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!empty($signature))
|
||||||
|
{
|
||||||
|
$_mailObject->setBody($this->convertHTMLToText($body, true, true).
|
||||||
|
($disableRuler ? "\r\n" : "\r\n-- \r\n").
|
||||||
|
$this->convertHTMLToText($signature, true, true));
|
||||||
|
|
||||||
|
$body .= ($disableRuler ?'<br>':'<hr style="border:1px dotted silver; width:90%;">').$signature;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$body .= $attachment_links;
|
$_mailObject->setBody($this->convertHTMLToText($body, true, true));
|
||||||
}
|
}
|
||||||
}
|
// convert URL Images to inline images - if possible
|
||||||
if(!empty($signature))
|
if (!$_autosaving) $inline_images = Mail::processURL2InlineImages($_mailObject, $body, $mail_bo);
|
||||||
{
|
if (strpos($body,"<!-- HTMLSIGBEGIN -->")!==false)
|
||||||
$_mailObject->setBody($this->convertHTMLToText($body, true, true).
|
{
|
||||||
($disableRuler ? "\r\n" : "\r\n-- \r\n").
|
$body = str_replace(array('<!-- HTMLSIGBEGIN -->','<!-- HTMLSIGEND -->'),'',$body);
|
||||||
$this->convertHTMLToText($signature, true, true));
|
}
|
||||||
|
$_mailObject->setHtmlBody($body, null, false); // false = no automatic alternative, we called setBody()
|
||||||
|
break;
|
||||||
|
case 'openpgp':
|
||||||
|
$_mailObject->setOpenPgpBody($_formData['body']);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$body = $this->convertHTMLToText($_formData['body'],false);
|
||||||
|
|
||||||
$body .= ($disableRuler ?'<br>':'<hr style="border:1px dotted silver; width:90%;">').$signature;
|
if ($attachment_links) $body .= $attachment_links;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$_mailObject->setBody($this->convertHTMLToText($body, true, true));
|
|
||||||
}
|
|
||||||
// convert URL Images to inline images - if possible
|
|
||||||
if (!$_autosaving) $inline_images = Mail::processURL2InlineImages($_mailObject, $body, $mail_bo);
|
|
||||||
if (strpos($body,"<!-- HTMLSIGBEGIN -->")!==false)
|
|
||||||
{
|
|
||||||
$body = str_replace(array('<!-- HTMLSIGBEGIN -->','<!-- HTMLSIGEND -->'),'',$body);
|
|
||||||
}
|
|
||||||
$_mailObject->setHtmlBody($body, null, false); // false = no automatic alternative, we called setBody()
|
|
||||||
}
|
|
||||||
elseif ($_formData['mimeType'] == 'openpgp')
|
|
||||||
{
|
|
||||||
$_mailObject->setOpenPgpBody($_formData['body']);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$body = $this->convertHTMLToText($_formData['body'],false);
|
|
||||||
|
|
||||||
if ($attachment_links) $body .= $attachment_links;
|
#$_mailObject->Body = $_formData['body'];
|
||||||
|
if(!empty($signature)) {
|
||||||
#$_mailObject->Body = $_formData['body'];
|
$body .= ($disableRuler ?"\r\n":"\r\n-- \r\n").
|
||||||
if(!empty($signature)) {
|
$this->convertHTMLToText($signature,true,true);
|
||||||
$body .= ($disableRuler ?"\r\n":"\r\n-- \r\n").
|
}
|
||||||
$this->convertHTMLToText($signature,true,true);
|
$_mailObject->setBody($body);
|
||||||
}
|
|
||||||
$_mailObject->setBody($body);
|
|
||||||
}
|
}
|
||||||
//error_log(__METHOD__.__LINE__.array2string($_formData['attachments']));
|
//error_log(__METHOD__.__LINE__.array2string($_formData['attachments']));
|
||||||
// add the attachments
|
// add the attachments
|
||||||
@ -2499,7 +2506,7 @@ class mail_compose
|
|||||||
* @param string $password =null
|
* @param string $password =null
|
||||||
* @return string might be empty if no file attachments found
|
* @return string might be empty if no file attachments found
|
||||||
*/
|
*/
|
||||||
protected function getAttachmentLinks(array $attachments, $filemode, $html, $recipients=array(), $expiration=null, $password=null)
|
protected function _getAttachmentLinks(array $attachments, $filemode, $html, $recipients=array(), $expiration=null, $password=null)
|
||||||
{
|
{
|
||||||
if ($filemode == Vfs\Sharing::ATTACH) return '';
|
if ($filemode == Vfs\Sharing::ATTACH) return '';
|
||||||
|
|
||||||
@ -2783,6 +2790,8 @@ class mail_compose
|
|||||||
$this->sessionData['to_infolog'] = $_formData['to_infolog'];
|
$this->sessionData['to_infolog'] = $_formData['to_infolog'];
|
||||||
$this->sessionData['to_tracker'] = $_formData['to_tracker'];
|
$this->sessionData['to_tracker'] = $_formData['to_tracker'];
|
||||||
$this->sessionData['attachments'] = $_formData['attachments'];
|
$this->sessionData['attachments'] = $_formData['attachments'];
|
||||||
|
$this->sessionData['smime_sign'] = $_formData['smime_sign'];
|
||||||
|
$this->sessionData['smime_encrypt'] = $_formData['smime_encrypt'];
|
||||||
|
|
||||||
if (isset($_formData['lastDrafted']) && !empty($_formData['lastDrafted']))
|
if (isset($_formData['lastDrafted']) && !empty($_formData['lastDrafted']))
|
||||||
{
|
{
|
||||||
@ -2966,6 +2975,43 @@ class mail_compose
|
|||||||
#error_log($this->errorInfo);
|
#error_log($this->errorInfo);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// SMIME SIGN/ENCRYPTION
|
||||||
|
if ($_formData['smime_sign'] == 'on' || $_formData['smime_encrypt'] == 'on' )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($_formData['smime_sign'] == 'on')
|
||||||
|
{
|
||||||
|
$smime_part = $this->_encrypt(
|
||||||
|
'',//TODO
|
||||||
|
$_formData['smime_encrypt'] == 'on'? Mail\Smime::TYPE_SIGN_ENCRYPT: Mail\Smime::TYPE_SIGN,
|
||||||
|
$_formData['to'],
|
||||||
|
$identity['ident_email'],
|
||||||
|
$_formData['smime_passphrase']
|
||||||
|
);
|
||||||
|
if ($smime_part['smime_pass_require'])
|
||||||
|
{
|
||||||
|
$response = Api\Json\Response::get();
|
||||||
|
$response->call('app.mail.smimePassDialog');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($_formData['smime_sign'] == 'off' && $_formData['smime_encrypt'] == 'on')
|
||||||
|
{
|
||||||
|
$smime_part = $this->_encrypt(
|
||||||
|
'',//TODO
|
||||||
|
Mail\Smime::TYPE_ENCRYPT,
|
||||||
|
$_formData['to'],
|
||||||
|
$identity['ident_email']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Set signed or encrypted mime part
|
||||||
|
}
|
||||||
|
catch (Exception $ex)
|
||||||
|
{
|
||||||
|
throw new Api\Exception\WrongUserinput($ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set a higher timeout for big messages
|
// set a higher timeout for big messages
|
||||||
@set_time_limit(120);
|
@set_time_limit(120);
|
||||||
@ -3581,30 +3627,35 @@ class mail_compose
|
|||||||
* @return Horde_Mime_Part returns encrypted message
|
* @return Horde_Mime_Part returns encrypted message
|
||||||
* @throws Api\Exception\WrongUserinput if no certificate found
|
* @throws Api\Exception\WrongUserinput if no certificate found
|
||||||
*/
|
*/
|
||||||
function _encrypt(Horde_Mime_part $message, $type, $recipients, $sender)
|
protected function _encrypt(Horde_Mime_part $message, $type, $recipients, $sender, $passphrase='')
|
||||||
{
|
{
|
||||||
$AB = new addressbook_bo();
|
$AB = new addressbook_bo();
|
||||||
|
$smime = new Mail\Smime();
|
||||||
|
|
||||||
if (isset($sender) && ($type == Mail\Smime::TYPE_SIGN || $type == Mail\Smime::TYPE_SIGN_ENCRYPT))
|
if (isset($sender) && ($type == Mail\Smime::TYPE_SIGN || $type == Mail\Smime::TYPE_SIGN_ENCRYPT))
|
||||||
{
|
{
|
||||||
$sender_cert = $AB->get_smime_keys($sender);
|
$sender_cert = $AB->get_smime_keys($sender);
|
||||||
$smime = new Mail\Smime();
|
|
||||||
|
|
||||||
if ($sender_cert)
|
if ($sender_cert)
|
||||||
{
|
{
|
||||||
$senderPubKey = $smime->get_publickey($sender_cert[$sender]);
|
$senderPubKey = $sender_cert[$sender];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Api\Exception\WrongUserinput('no certificate found to sign the messase');
|
throw new Api\Exception\WrongUserinput('no certificate found to sign the messase');
|
||||||
}
|
}
|
||||||
|
$credents = Mail\Credentials::read($this->mail_bo->profileID, Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||||
|
$privkey = $credents['acc_smime_password'];
|
||||||
|
|
||||||
|
if (!$smime->verifyPassphrase($privkey, $passphrase))
|
||||||
|
{
|
||||||
|
return array('smime_pass_require' => true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($recipients) && ($type == Mail\Smime::TYPE_ENCRYPT || $type == Mail\Smime::TYPE_SIGN_ENCRYPT))
|
if (isset($recipients) && ($type == Mail\Smime::TYPE_ENCRYPT || $type == Mail\Smime::TYPE_SIGN_ENCRYPT))
|
||||||
{
|
{
|
||||||
$recipients_certs = $AB->get_smime_keys($recipients);
|
$recipients_certs = $AB->get_smime_keys($recipients);
|
||||||
$recipientsPubKeys = array_Map(array ($smime, 'get_publickey'), $recipients_certs);
|
|
||||||
if (!$recipients_certs) throw new Api\Exception\WrongUserinput('no certificate found from the recipients to sign/encrypt the messase');
|
if (!$recipients_certs) throw new Api\Exception\WrongUserinput('no certificate found from the recipients to sign/encrypt the messase');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3612,15 +3663,15 @@ class mail_compose
|
|||||||
$sign_params = array(
|
$sign_params = array(
|
||||||
'type' => 'signature',
|
'type' => 'signature',
|
||||||
'pubkey' => $senderPubKey,
|
'pubkey' => $senderPubKey,
|
||||||
'prikey' => '',
|
'privkey' => $privkey,
|
||||||
'passphrase'=> '',
|
'passphrase'=> $passphrase,
|
||||||
'sigtype' => 'detach',
|
'sigtype' => 'detach',
|
||||||
'certs' => ''
|
'certs' => ''
|
||||||
);
|
);
|
||||||
// parameters to pass on for encrypt mime part
|
// parameters to pass on for encrypt mime part
|
||||||
$encrypt_params = array(
|
$encrypt_params = array(
|
||||||
'type' => 'message',
|
'type' => 'message',
|
||||||
'pubkey' => $recipientsPubKeys
|
'pubkey' => $recipients_certs
|
||||||
);
|
);
|
||||||
switch ($type)
|
switch ($type)
|
||||||
{
|
{
|
||||||
|
@ -5528,5 +5528,33 @@ app.classes.mail = AppJS.extend(
|
|||||||
url = this.et2.getArrayMgr("content").getEntry('smimeSigUrl');
|
url = this.et2.getArrayMgr("content").getEntry('smimeSigUrl');
|
||||||
}
|
}
|
||||||
window.egw.openPopup(url,'700','400');
|
window.egw.openPopup(url,'700','400');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smime password dialog
|
||||||
|
*/
|
||||||
|
smimePassDialog: function ()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
et2_createWidget("dialog",
|
||||||
|
{
|
||||||
|
callback: function(_button_id, _value)
|
||||||
|
{
|
||||||
|
if (_button_id && _value)
|
||||||
|
{
|
||||||
|
var pass = self.et2.getWidgetById('smime_passphrase');
|
||||||
|
pass.set_value(_value.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: egw.lang('Request for passphrase'),
|
||||||
|
buttons: et2_dialog.BUTTONS_OK_CANCEL,
|
||||||
|
value:{
|
||||||
|
content:{
|
||||||
|
value: '',
|
||||||
|
message: self.egw.lang('Looks like your certificate is password protected. Please enter your passphrase and try to send again.')
|
||||||
|
}},
|
||||||
|
template: egw.webserverUrl+'/api/templates/default/password.xet',
|
||||||
|
resizable: false
|
||||||
|
}, et2_dialog._create_parent('mail'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
<checkbox statustext="check to save as trackerentry on send" id="to_tracker" options="on,off"/>
|
<checkbox statustext="check to save as trackerentry on send" id="to_tracker" options="on,off"/>
|
||||||
<checkbox statustext="check to save as calendar event on send" id="to_calendar" options="on,off"/>
|
<checkbox statustext="check to save as calendar event on send" id="to_calendar" options="on,off"/>
|
||||||
<checkbox statustext="check to recieve a notification when the message is read (note: not all clients support this and/or the reciever may not authorize the notification)" id="disposition" options="on,off"/>
|
<checkbox statustext="check to recieve a notification when the message is read (note: not all clients support this and/or the reciever may not authorize the notification)" id="disposition" options="on,off"/>
|
||||||
|
<checkbox statustext="check to sign the message on send" id="smime_sign" options="on,off"/>
|
||||||
|
<checkbox statustext="check to encrypt the message on send" id="smime_encrypt" options="on,off"/>
|
||||||
|
<passwd id="smime_passphrase"/>
|
||||||
<taglist id="to_integrate_ids"/>
|
<taglist id="to_integrate_ids"/>
|
||||||
<menulist>
|
<menulist>
|
||||||
<menupopup id="priority"/>
|
<menupopup id="priority"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user