Skip to content

Commit

Permalink
Enigma: Add possibility to export private keys (#5321)
Browse files Browse the repository at this point in the history
  • Loading branch information
alecpl committed Jun 20, 2016
1 parent ded320a commit 88ed121
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ CHANGELOG Roundcube Webmail
- Enigma: Fix keys import from inside of an encrypted message (#5285)
- Enigma: Fix malformed signed messages with force_7bit=true (#5292)
- Enigma: Add possibility to configure gpg binary location (enigma_pgp_binary)
- Enigma: Add possibility to export private keys (#5321)
- Fix searching by email address in contacts with multiple addresses (#5291)
- Fix handling of --delete argument in moduserprefs.sh script (#5296)
- Workaround PHP issue by calling closelog() on script shutdown when using log_driver=syslog (#5289)
Expand Down
43 changes: 41 additions & 2 deletions plugins/enigma/enigma.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,50 @@ rcube_webmail.prototype.enigma_delete = function()
// Export key(s)
rcube_webmail.prototype.enigma_export = function(selected)
{
var keys = selected ? this.keys_list.get_selection().join(',') : '*';
var priv = false,
list = this.keys_list,
keys = selected ? list.get_selection().join(',') : '*',
args = {_a: 'export', _keys: keys};

if (!keys.length)
return;

this.goto_url('plugin.enigmakeys', {_a: 'export', _keys: keys}, false, true);
// find out wether selected keys are private
if (keys == '*')
priv = true;
else
$.each(list.get_selection(), function() {
flags = $(list.rows[this].obj).data('flags');
if (flags && flags.indexOf('p') >= 0) {
priv = true;
return false;
}
});

// ask the user about including private key in the export
if (priv)
return this.show_popup_dialog(
this.get_label('enigma.keyexportprompt'),
this.get_label('enigma.exportkeys'),
[{
text: this.get_label('enigma.onlypubkeys'),
click: function(e) {
rcmail.goto_url('plugin.enigmakeys', args, false, true);
$(this).remove();
}
},
{
text: this.get_label('enigma.withprivkeys'),
click: function(e) {
args._priv = 1;
rcmail.goto_url('plugin.enigmakeys', args, false, true);
$(this).remove();
}
}],
{width: 400}
);

this.goto_url('plugin.enigmakeys', args, false, true);
};

// Submit key(s) import form
Expand Down Expand Up @@ -318,6 +356,7 @@ rcube_webmail.prototype.enigma_add_list_row = function(r)

row.id = 'rcmrow' + r.id;
row.className = css_class;
if (r.flags) $(row).data('flags', r.flags);

col.innerHTML = r.name;
row.appendChild(col);
Expand Down
3 changes: 2 additions & 1 deletion plugins/enigma/lib/enigma_driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,11 @@ abstract function import($content, $isfile = false);
* Key/Cert export.
*
* @param string Key ID
* @param bool Include private key
*
* @return mixed Key content or enigma_error
*/
abstract function export($key);
abstract function export($key, $with_private = false);

/**
* Keys listing.
Expand Down
12 changes: 10 additions & 2 deletions plugins/enigma/lib/enigma_driver_gnupg.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,21 @@ public function import($content, $isfile=false)
* Key export.
*
* @param string Key ID
* @param bool Include private key
*
* @return mixed Key content or enigma_error
*/
public function export($keyid)
public function export($keyid, $with_private = false)
{
try {
return $this->gpg->exportPublicKey($keyid, true);
$key = $this->gpg->exportPublicKey($keyid, true);

if ($with_private) {
$priv = $this->gpg->exportPrivateKey($keyid, true);
$key .= $priv;
}

return $key;
}
catch (Exception $e) {
return $this->get_error_from_exception($e);
Expand Down
4 changes: 4 additions & 0 deletions plugins/enigma/lib/enigma_driver_phpssl.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public function import($content, $isfile=false)
{
}

public function export($key, $with_private = false)
{
}

public function list_keys($pattern='')
{
}
Expand Down
5 changes: 3 additions & 2 deletions plugins/enigma/lib/enigma_engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -1126,13 +1126,14 @@ function import_key($content, $isfile=false)
*
* @param string Key ID
* @param resource Optional output stream
* @param bool Include private key
*
* @return mixed Key content or enigma_error
*/
function export_key($key, $fp = null)
function export_key($key, $fp = null, $include_private = false)
{
$this->load_pgp_driver();
$result = $this->pgp_driver->export($key, $fp);
$result = $this->pgp_driver->export($key, $include_private);

if ($result instanceof enigma_error) {
rcube::raise_error(array(
Expand Down
14 changes: 14 additions & 0 deletions plugins/enigma/lib/enigma_key.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ function is_expired()
return false;
}

/**
* Returns true if any of subkeys is a private key
*/
function is_private()
{
$now = time();

foreach ($this->subkeys as $subkey)
if ($subkey->has_private)
return true;

return false;
}

/**
* Get key ID by user email
*/
Expand Down
14 changes: 10 additions & 4 deletions plugins/enigma/lib/enigma_ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ function tpl_keys_list($attrib)
$this->rc->output->include_script('list.js');

// add some labels to client
$this->rc->output->add_label('enigma.keyremoveconfirm', 'enigma.keyremoving');
$this->rc->output->add_label('enigma.keyremoveconfirm', 'enigma.keyremoving',
'enigma.keyexportprompt', 'enigma.withprivkeys', 'enigma.onlypubkeys', 'enigma.exportkeys'
);

return $out;
}
Expand Down Expand Up @@ -259,8 +261,11 @@ private function key_list()

// Add rows
foreach ($list as $key) {
$this->rc->output->command('enigma_add_list_row',
array('name' => rcube::Q($key->name), 'id' => $key->id));
$this->rc->output->command('enigma_add_list_row', array(
'name' => rcube::Q($key->name),
'id' => $key->id,
'flags' => $key->is_private() ? 'p' : ''
));
}
}

Expand Down Expand Up @@ -462,6 +467,7 @@ private function key_export()
$this->rc->request_security_check(rcube_utils::INPUT_GET);

$keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_GPC);
$priv = rcube_utils::get_input_value('_priv', rcube_utils::INPUT_GPC);
$engine = $this->enigma->load_engine();
$list = $keys == '*' ? $engine->list_keys() : explode(',', $keys);

Expand All @@ -477,7 +483,7 @@ private function key_export()

if ($fp = fopen('php://output', 'w')) {
foreach ($list as $key) {
$engine->export_key(is_object($key) ? $key->id : $key, $fp);
$engine->export_key(is_object($key) ? $key->id : $key, $fp, (bool) $priv);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions plugins/enigma/localization/en_US.inc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ $labels['enterkeypass'] = 'A passphrase is needed to unlock the secret key ($key
$labels['arialabelkeyexportoptions'] = 'Keys export options';
$labels['attachpubkeymsg'] = 'Attach my public key';

$labels['keyexportprompt'] = 'Do you want to include secret keys in the saved OpenPGP keys file?';
$labels['onlypubkeys'] = 'Export Public Keys Only';
$labels['withprivkeys'] = 'Export Secret Keys';

$messages = array();
$messages['sigvalid'] = 'Verified signature from $sender.';
$messages['sigvalidpartial'] = 'Verified signature from $sender, but part of the body was not signed.';
Expand Down

0 comments on commit 88ed121

Please sign in to comment.