* EMail/sMime: allow non-admin users to upload their keys

This commit is contained in:
Ralf Becker 2018-04-10 13:15:09 +02:00
parent 269e068acb
commit 9fff809d90
6 changed files with 102 additions and 44 deletions

View File

@ -1,13 +1,12 @@
<?php
/**
* EGroupware EMailAdmin: Wizard to create mail Api\Accounts
* EGroupware EMailAdmin: Wizard to create mail accounts
*
* @link http://www.stylite.de
* @link http://www.egroupware.org
* @package emailadmin
* @author Ralf Becker <rb@stylite.de>
* @copyright (c) 2013-16 by Ralf Becker <rb@stylite.de>
* @author Ralf Becker <rb@egroupware.org>
* @copyright (c) 2013-18 by Ralf Becker <rb@egroupware.org>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
use EGroupware\Api;
@ -1031,30 +1030,7 @@ class admin_mail
// SMIME SAVE
if (isset($content['smimeKeyUpload']))
{
$smime = new Mail\Smime;
$content['acc_smime_username'] = $smime->getEmailFromKey($content['smime_cert']);
$AB_bo = new addressbook_bo();
if (($pkcs12 = file_get_contents($content['smimeKeyUpload']['tmp_name'])))
{
$cert_info = Mail\Smime::extractCertPKCS12($pkcs12, $content['smime_pkcs12_password']);
if (is_array($cert_info))
{
$content['acc_smime_password'] = $pkcs12;
$content['smime_cert'] = $cert_info['cert'];
if ($content['smime_cert'])
{
$content['acc_smime_username'] = $smime->getEmailFromKey($content['smime_cert']);
$AB_bo = new addressbook_bo();
$AB_bo->set_smime_keys(array(
$content['acc_smime_username'] => $content['smime_cert']
));
}
}
else
{
$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!'));
}
}
self::save_smime_key($content, $tpl, $content['called_for']);
}
self::fix_account_id_0($content['account_id'], true);
$content = Mail\Account::write($content, $content['called_for'] || !$this->is_admin ?
@ -1117,6 +1093,11 @@ class admin_mail
$content['mailForwardingAddress'],
$content['forwardOnly'] ? null : 'yes');
}
// smime (private) key uploaded by user himself
if (!empty($content['smimeKeyUpload']))
{
self::save_smime_key($content, $tpl);
}
}
}
catch (Horde_Imap_Client_Exception $e)
@ -1167,7 +1148,7 @@ class admin_mail
}
// SMIME UPLOAD/DELETE/EXPORT control
$content['hide_smime_upload'] = false;
if (!empty($content['acc_smime_password']))
if (isset($content['acc_smime_password']))
{
if (!empty($content['smime_delete_p12']) &&
Mail\Credentials::delete (
@ -1181,6 +1162,9 @@ class admin_mail
}
else
{
// do NOT send smime private key to client side, it's unnecessary and binary blob breaks json encoding
$content['acc_smime_password'] = '';
$content['hide_smime_upload'] = true;
}
}
@ -1203,8 +1187,10 @@ class admin_mail
$readonlys['button[cancel]'] = false;
// allow to edit notification-folders
$readonlys['button[save]'] = $readonlys['button[apply]'] =
$readonlys['notify_folders'] = $readonlys['notify_use_default'] =
$readonlys['smimeKeyUpload'] = $readonlys['smime_pkcs12_password']= false;
$readonlys['notify_folders'] = $readonlys['notify_use_default'] = false;
// allow to edit sMime stuff
$readonlys['smimeGenerate'] = $readonlys['smimeKeyUpload'] = $readonlys['smime_pkcs12_password'] =
$readonlys['smime_export_p12'] = $readonlys['smime_delete_p12'] = false;
}
$sel_options['acc_imap_ssl'] = $sel_options['acc_sieve_ssl'] =
@ -1379,6 +1365,38 @@ class admin_mail
$tpl->exec(static::APP_CLASS.'edit', $content, $sel_options, $readonlys, $content, 2);
}
/**
* Saves the smime key
*
* @param array $content
* @param Etemplate $tpl
* @param int $account_id =null account to save smime key for, default current user
*/
private static function save_smime_key(array $content, Etemplate $tpl, $account_id=null)
{
if (($pkcs12 = file_get_contents($content['smimeKeyUpload']['tmp_name'])))
{
$cert_info = Mail\Smime::extractCertPKCS12($pkcs12, $content['smime_pkcs12_password']);
if (is_array($cert_info) && !empty($cert_info['cert']))
{
// save public key
$smime = new Mail\Smime;
$email = $smime->getEmailFromKey($cert_info['cert']);
$AB_bo = new addressbook_bo();
$AB_bo->set_smime_keys(array(
$email => $cert_info['cert']
));
// save private key
if (!isset($account_id)) $account_id = $GLOBALS['egw_info']['user']['account_id'];
Mail\Credentials::write($content['acc_id'], $email, $pkcs12, Mail\Credentials::SMIME, $account_id);
}
else
{
$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!'));
}
}
}
/**
* Replace 0 with '' or back
*

View File

@ -1269,7 +1269,7 @@ app.classes.admin = AppJS.extend(
content:{
value: ''
}},
template: egw.webserverUrl+'/mail/templates/default/smimeCertGen.xet',
template: egw.webserverUrl+'/mail/templates/default/smimeCertGen.xet?'+Date.now(),
resizable: false,
position: 'left top'
}, et2_dialog._create_parent('mail'));

View File

@ -297,19 +297,21 @@
</columns>
<rows>
<row>
<description value="S/MIME"/>
<description value="S/MIME" span="all"/>
</row>
<row>
<!-- disabled, because not working/fully implemented
<row disabled="@hide_smime_upload">
<description value="Certificate"/>
<hbox>
<buttononly label="Generate Certificate" onclick="app.admin.smime_genCertificate" image="add" background_image="1"/>
<buttononly id="smimeGenerate" label="Generate Certificate" onclick="app.admin.smime_genCertificate" image="add" background_image="1"/>
</hbox>
</row>
<row disabled="@hide_smime_upload">
-->
<row disabled="@hide_smime_upload" valign="top">
<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"/>
<passwd id="smime_pkcs12_password" size="48" maxlength="128" blur="Password to unlock encrypted p12" autocomplete="off"/>
</vbox>
</row>
<row disabled="!@hide_smime_upload">

View File

@ -0,0 +1,39 @@
<?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="mail.smimeCertGen" template="" lang="" group="0" version="17.1">
<grid width="100%">
<columns>
<column/>
</columns>
<rows>
<row>
<groupbox>
<caption label="Certificate details"/>
<vbox>
<textbox id="countryName" class="et2_fullWidth" blur="Country name"/>
<textbox id="stateOrProvinceName" class="et2_fullWidth" blur="State or province name"/>
<textbox id="localityName" class="et2_fullWidth" blur="Locality name"/>
<textbox id="organizationName" class="et2_fullWidth" blur="Organization name"/>
<textbox id="organizationalUnitName" class="et2_fullWidth" blur="Organizational unit name"/>
<textbox id="commonName" class="et2_fullWidth" blur="Common name"/>
<textbox id="emailAddress" class="et2_fullWidth" blur="Email address"/>
<textbox id="validation" type="integer" label="Certificate validation in days" blur="365"/>
</vbox>
</groupbox>
</row>
<row>
<groupbox>
<caption label="passphrase"/>
<description value="Enter a passphrase if you would like to protect your private key by password."/>
<vbox>
<passwd id="passphrase" blur="Enter a passphrase" class="et2_fullWidth"/>
<passwd id="passphraseConf" blur="Repeat the passphrase" class="et2_fullWidth"/>
</vbox>
</groupbox>
</row>
</rows>
</grid>
</template>
</overlay>

View File

@ -2261,14 +2261,14 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
$smime = new Mail\Smime();
$response = Api\Json\Response::get();
// fields need to be excluded from data
$discards = array ('passphrase', 'passphraseConf', 'ca');
$discards = array ('passphrase', 'passphraseConf', 'ca', 'validity');
$ca = $_data['ca'];
$passphrase = $_data['passphrase'];
foreach ($_data as $key => $val)
foreach (array_keys($_data) as $key)
{
if (empty($_data[$key]) || in_array($key, $discards)) unset($_data[$key]);
}
$response->data($smime->generate_certificate($_data, $ca, null, $passphrase));
$response->data($smime->generate_certificate($_data, $ca, null, $passphrase, $_data['validity']));
}
/**

View File

@ -1,6 +1,5 @@
<?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="mail.smimeCertGen" template="" lang="" group="0" version="17.1">
<grid width="100%">
@ -12,14 +11,14 @@
<groupbox>
<caption label="Certificate details"/>
<vbox>
<textbox id="countryName" class="et2_fullWidth" blur="Country name"/>
<textbox id="countryName" class="et2_fullWidth" blur="Country name (2 letter code, eg. DE)" maxlength="2"/>
<textbox id="stateOrProvinceName" class="et2_fullWidth" blur="State or province name"/>
<textbox id="localityName" class="et2_fullWidth" blur="Locality name"/>
<textbox id="organizationName" class="et2_fullWidth" blur="Organization name"/>
<textbox id="organizationalUnitName" class="et2_fullWidth" blur="Organizational unit name"/>
<textbox id="commonName" class="et2_fullWidth" blur="Common name"/>
<textbox id="emailAddress" class="et2_fullWidth" blur="Email address"/>
<textbox id="validation" type="integer" label="Certificate validation in days" blur="365"/>
<textbox id="validity" type="integer" label="Certificate validity in days" blur="3650"/>
</vbox>
</groupbox>
</row>