diff --git a/admin/inc/class.admin_mail.inc.php b/admin/inc/class.admin_mail.inc.php index ec09e706db..ccd0a037f9 100644 --- a/admin/inc/class.admin_mail.inc.php +++ b/admin/inc/class.admin_mail.inc.php @@ -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 ? diff --git a/admin/js/app.js b/admin/js/app.js index 76dd871c99..c0b8f8c4c8 100644 --- a/admin/js/app.js +++ b/admin/js/app.js @@ -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(); }, diff --git a/admin/templates/default/mailaccount.xet b/admin/templates/default/mailaccount.xet index 98a0cbb688..fa999b450a 100644 --- a/admin/templates/default/mailaccount.xet +++ b/admin/templates/default/mailaccount.xet @@ -303,24 +303,18 @@ - - - + - - - - - - + + diff --git a/api/src/Mail.php b/api/src/Mail.php index 8cf2e9357c..c4c28dce7a 100644 --- a/api/src/Mail.php +++ b/api/src/Mail.php @@ -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); diff --git a/api/src/Mail/Smime.php b/api/src/Mail/Smime.php index 1ecfc9fa65..ee491b8461 100644 --- a/api/src/Mail/Smime.php +++ b/api/src/Mail/Smime.php @@ -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; + } } diff --git a/api/src/Mailer.php b/api/src/Mailer.php index c8f6f43892..599fe306e7 100644 --- a/api/src/Mailer.php +++ b/api/src/Mailer.php @@ -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( diff --git a/mail/inc/class.mail_compose.inc.php b/mail/inc/class.mail_compose.inc.php index 9744e3b076..3dc5016ce6 100644 --- a/mail/inc/class.mail_compose.inc.php +++ b/mail/inc/class.mail_compose.inc.php @@ -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)) diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index 937f9dc780..bf022999ad 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -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