mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 16:48:49 +01:00
S/MIME:
- Store full binary (pkcs12) certificate into credentials - Extract cacert from pkcs12 and feed it into signing process - Implement p12 export
This commit is contained in:
parent
b785766331
commit
3f06a89db5
@ -896,9 +896,7 @@ class admin_mail
|
||||
|
||||
if (!empty($content['acc_smime_password']))
|
||||
{
|
||||
$AB_bo = new addressbook_bo();
|
||||
$smime_cert = $AB_bo->get_smime_keys($content['acc_smime_username']);
|
||||
$content['smime_cert'] = $smime_cert[$content['acc_smime_username']];
|
||||
$readonlys['smime_export_p12'] = false;
|
||||
}
|
||||
}
|
||||
catch(Api\Exception\NotFound $e) {
|
||||
@ -1036,7 +1034,7 @@ class admin_mail
|
||||
$content['called_for'] : $GLOBALS['egw_info']['user']['account_id'];
|
||||
}
|
||||
// SMIME SAVE
|
||||
if (isset($content['smimeKeyUpload']) || $content['smime_cert'] && $content['acc_smime_password'])
|
||||
if (isset($content['smimeKeyUpload']))
|
||||
{
|
||||
$smime = new Mail\Smime;
|
||||
$content['acc_smime_username'] = $smime->getEmailFromKey($content['smime_cert']);
|
||||
@ -1044,10 +1042,10 @@ class admin_mail
|
||||
if (($pkcs12 = file_get_contents($content['smimeKeyUpload']['tmp_name'])) &&
|
||||
$content['smimeKeyUpload']['type'] == 'application/x-pkcs12')
|
||||
{
|
||||
$cert_info = $smime->extractCertPKCS12($pkcs12, $content['smime_pkcs12_password']);
|
||||
$cert_info = Mail\Smime::extractCertPKCS12($pkcs12, $content['smime_pkcs12_password']);
|
||||
if (is_array($cert_info))
|
||||
{
|
||||
$content['acc_smime_password'] = $cert_info['pkey'];
|
||||
$content['acc_smime_password'] = $pkcs12;
|
||||
$content['smime_cert'] = $cert_info['cert'];
|
||||
if ($content['smime_cert'])
|
||||
{
|
||||
@ -1063,10 +1061,6 @@ class admin_mail
|
||||
$tpl->set_validation_error('smimeKeyUpload', lang('Could not extract private key from given p12 file. Either the p12 file is broken or password is wrong!'));
|
||||
}
|
||||
}
|
||||
elseif ($content['smime_cert'] && $content['acc_smime_password'])
|
||||
{
|
||||
$AB_bo->set_smime_keys(array($content['acc_smime_username'] => $content['smime_cert']));
|
||||
}
|
||||
}
|
||||
self::fix_account_id_0($content['account_id'], true);
|
||||
$content = Mail\Account::write($content, $content['called_for'] || !$this->is_admin ?
|
||||
|
@ -1163,29 +1163,16 @@ app.classes.admin = AppJS.extend(
|
||||
|
||||
/**
|
||||
* Export content of given field into relevant file
|
||||
* @param string _field
|
||||
*/
|
||||
smime_exportKey: function (_field)
|
||||
smime_exportCert: function ()
|
||||
{
|
||||
var $a = jQuery(document.createElement('a')).appendTo('body').hide();
|
||||
var widget = {};
|
||||
switch (_field)
|
||||
{
|
||||
case 'privkey':
|
||||
widget = this.et2.getWidgetById('acc_smime_password');
|
||||
$a.attr({
|
||||
download: 'private_key.key',
|
||||
href: 'data:application/x-iwork-keynote-sffkey;charset=utf-8,' + encodeURI(widget.getValue())
|
||||
});
|
||||
break;
|
||||
case 'cert':
|
||||
widget = this.et2.getWidgetById('smime_cert');
|
||||
$a.attr({
|
||||
download: 'cert.crt',
|
||||
href: 'data:application/pkix-cert;charset=utf-8,' + encodeURI(widget.getValue())
|
||||
});
|
||||
break;
|
||||
}
|
||||
var acc_id = this.et2.getArrayMgr("content").getEntry('acc_id');
|
||||
var url = window.egw_webserverUrl+'/index.php?';
|
||||
url += 'menuaction=mail.mail_ui.smimeExportCert';
|
||||
url += '&acc_id='+acc_id;
|
||||
$a.prop('href',url);
|
||||
$a.prop('download',"");
|
||||
$a[0].click();
|
||||
$a.remove();
|
||||
},
|
||||
|
@ -303,24 +303,18 @@
|
||||
<description value="Certificate"/>
|
||||
<hbox>
|
||||
<buttononly label="Generate Certificate" onclick="app.admin.smime_genCertificate" image="add" background_image="1"/>
|
||||
<buttononly label="export private key" onclick="app.admin.smime_exportKey('privkey')" disabled="!@acc_smime_password" image="export" background_image="1"/>
|
||||
<buttononly label="export certificate" onclick="app.admin.smime_exportKey('cert')" disabled="!@smime_cert" image="export" background_image="1"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Certificate file in p12 format"/>
|
||||
<description value="Upload your certificate .p12/.pfx file"/>
|
||||
<vbox>
|
||||
<file id="smimeKeyUpload" accept=".p12,.pfx"/>
|
||||
<passwd id="smime_pkcs12_password" size="32" maxlength="128" blur="Password to unlock encrypted p12" autocomplete="off"/>
|
||||
</vbox>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Paste your private key as text here or upload your .p12 file"/>
|
||||
<textbox multiline="true" id="acc_smime_password" height="130" resize_ratio="0" class="et2_fullWidth"/>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Certificate"/>
|
||||
<textbox multiline="true" id="smime_cert" height="130" resize_ratio="0" class="et2_fullWidth"/>
|
||||
<description value="Current certificate"/>
|
||||
<buttononly id="smime_export_p12" label="export certificate as p12" onclick="app.admin.smime_exportCert" image="export" background_image="1" readonly="true"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
@ -7424,9 +7424,9 @@ class Mail
|
||||
private function _decryptSmimeBody ($_message, $_passphrase = '')
|
||||
{
|
||||
$AB_bo = new \addressbook_bo();
|
||||
$credents = Mail\Credentials::read($this->profileID, Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||
$certkey = $AB_bo->get_smime_keys($credents['acc_smime_username']);
|
||||
if (!$this->smime->verifyPassphrase($credents['acc_smime_password'], $_passphrase))
|
||||
$acc_smime = Mail\Smime::get_acc_smime($this->profileID, $_passphrase);
|
||||
$certkey = $AB_bo->get_smime_keys($acc_smime['acc_smime_username']);
|
||||
if (!$this->smime->verifyPassphrase($acc_smime['pkey'], $_passphrase))
|
||||
{
|
||||
return array (
|
||||
'password_required' => true,
|
||||
@ -7436,8 +7436,8 @@ class Mail
|
||||
|
||||
$params = array (
|
||||
'type' => 'message',
|
||||
'pubkey' => $certkey[$credents['acc_smime_username']],
|
||||
'privkey' => $credents['acc_smime_password'],
|
||||
'pubkey' => $certkey[$acc_smime['acc_smime_username']],
|
||||
'privkey' => $acc_smime['pkey'],
|
||||
'passphrase'=> $_passphrase
|
||||
);
|
||||
return $this->smime->decrypt($_message, $params);
|
||||
|
@ -13,6 +13,7 @@
|
||||
namespace EGroupware\Api\Mail;
|
||||
use Horde_Mime_Part;
|
||||
use Horde_Crypt_Smime;
|
||||
use EGroupware\Api;
|
||||
/**
|
||||
* EMailAdmin generic base class for SMTP
|
||||
*/
|
||||
@ -156,7 +157,7 @@ class Smime extends Horde_Crypt_Smime
|
||||
*
|
||||
* @return boolean|array returns array of certs info or false if not successful
|
||||
*/
|
||||
public function extractCertPKCS12 ($pkcs12, $passphrase = '')
|
||||
public static function extractCertPKCS12 ($pkcs12, $passphrase = '')
|
||||
{
|
||||
$certs = $out = array ();
|
||||
if (openssl_pkcs12_read($pkcs12, $certs, $passphrase))
|
||||
@ -233,4 +234,38 @@ class Smime extends Horde_Crypt_Smime
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to extract smime related info from credential table
|
||||
*
|
||||
* @param type $acc_id acc id of mail account
|
||||
* @param type $passphrase = '' protect private key by passphrase
|
||||
* @return mixed return array of smime info or false if fails
|
||||
*/
|
||||
public static function get_acc_smime($acc_id, $passphrase = '')
|
||||
{
|
||||
if (Api\Cache::getSession('mail', 'smime_passphrase'))
|
||||
{
|
||||
$passphrase = Api\Cache::getSession('mail', 'smime_passphrase');
|
||||
}
|
||||
$acc_smime = Credentials::read(
|
||||
$acc_id,
|
||||
Credentials::SMIME,
|
||||
$GLOBALS['egw_info']['user']['account_id']
|
||||
);
|
||||
foreach ($acc_smime as $key => $val)
|
||||
{
|
||||
// remove other imap stuffs but smime
|
||||
if (!preg_match("/acc_smime/", $key)) unset($acc_smime[$key]);
|
||||
}
|
||||
if ($acc_smime['acc_smime_password'])
|
||||
{
|
||||
$extracted = self::extractCertPKCS12(
|
||||
$acc_smime['acc_smime_password'],
|
||||
$passphrase
|
||||
);
|
||||
return array_merge($acc_smime, is_array($extracted) ? $extracted : array());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1164,7 +1164,7 @@ class Mailer extends Horde_Mime_Mail
|
||||
'privkey' => $params['senderPrivKey'],
|
||||
'passphrase'=> $params['passphrase'],
|
||||
'sigtype' => 'detach',
|
||||
'certs' => ''
|
||||
'certs' => $params['extracerts']
|
||||
);
|
||||
// parameters to pass on for encrypt mime part
|
||||
$encrypt_params = array(
|
||||
|
@ -214,8 +214,8 @@ class mail_compose
|
||||
),
|
||||
|
||||
);
|
||||
$credentials = Mail\Credentials::read($this->mail_bo->profileID, Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||
if ($credentials['acc_smime_password'])
|
||||
$acc_smime = Mail\Smime::get_acc_smime($this->mail_bo->profileID);
|
||||
if ($acc_smime['acc_smime_password'])
|
||||
{
|
||||
$actions = array_merge($actions, array(
|
||||
'smime_sign' => array (
|
||||
@ -3656,12 +3656,8 @@ class mail_compose
|
||||
protected function _encrypt($mail, $type, $recipients, $sender, $passphrase='')
|
||||
{
|
||||
$AB = new addressbook_bo();
|
||||
$params = array (
|
||||
'senderPubKey' => '', // Sender Public key
|
||||
'passphrase' => $passphrase, // passphrase of sender private key
|
||||
'senderPrivKey' => '', // sender private key
|
||||
'recipientsCerts' => array() // Recipients Certificates
|
||||
);
|
||||
// passphrase of sender private key
|
||||
$params['passphrase'] = $passphrase;
|
||||
|
||||
try
|
||||
{
|
||||
@ -3670,9 +3666,9 @@ class mail_compose
|
||||
$sender_cert = $AB->get_smime_keys($sender);
|
||||
if (!$sender_cert) throw new Exception("Encryption failed because no certificate has been found for sender address: " . $sender);
|
||||
$params['senderPubKey'] = $sender_cert[$sender];
|
||||
|
||||
$credents = Mail\Credentials::read($this->mail_bo->profileID, Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||
$params['senderPrivKey'] = $credents['acc_smime_password'];
|
||||
$acc_smime = Mail\Smime::get_acc_smime($this->mail_bo->profileID, $params['passphrase']);
|
||||
$params['senderPrivKey'] = $acc_smime['pkey'];
|
||||
$params['extracerts'] = $acc_smime['extracerts'];
|
||||
}
|
||||
|
||||
if (isset($recipients) && ($type == Mail\Smime::TYPE_ENCRYPT || $type == Mail\Smime::TYPE_SIGN_ENCRYPT))
|
||||
|
@ -56,6 +56,7 @@ class mail_ui
|
||||
'importMessageFromVFS2DraftAndDisplay'=>True,
|
||||
'subscription' => True,
|
||||
'folderManagement' => true,
|
||||
'smimeExportCert' => true
|
||||
);
|
||||
|
||||
/**
|
||||
@ -2267,6 +2268,21 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
|
||||
$response->data($smime->generate_certificate($_data, $ca, null, $passphrase));
|
||||
}
|
||||
|
||||
/**
|
||||
* Export stored smime certificate in database
|
||||
* @return boolean return false if not successful
|
||||
*/
|
||||
function smimeExportCert()
|
||||
{
|
||||
if (empty($_GET['acc_id'])) return false;
|
||||
$acc_smime = Mail\Credentials::read($_GET['acc_id'], Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||
$length = 0;
|
||||
$mime = 'application/x-pkcs12';
|
||||
Api\Header\Content::safe($acc_smime['acc_smime_password'], "certificate.p12", $mime, $length, true, true);
|
||||
echo $acc_smime['acc_smime_password'];
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build actions for display toolbar
|
||||
*/
|
||||
@ -3111,10 +3127,10 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
|
||||
}
|
||||
catch(Mail\Smime\PassphraseMissing $e)
|
||||
{
|
||||
$credentials = Mail\Credentials::read($this->mail_bo->profileID, Mail\Credentials::SMIME, $GLOBALS['egw_info']['user']['account_id']);
|
||||
if (empty($credentials['acc_smime_password']))
|
||||
$acc_smime = Mail\Smime::get_acc_smime($this->mail_bo->profileID);
|
||||
if (empty($acc_smime))
|
||||
{
|
||||
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 certificate in Encryption tab located at Edit Account dialog.'));
|
||||
}
|
||||
Framework::message($e->getMessage());
|
||||
// do NOT include any default CSS
|
||||
|
Loading…
Reference in New Issue
Block a user