You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
roundcubemail/plugins/enigma/bin/import_keys.sh

189 lines
5.6 KiB
Bash

#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| Copyright (C) Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Import keys from Enigma's homedir into database for multihost |
| support. |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/../../../') . '/');
require INSTALL_PATH . 'program/include/clisetup.php';
$rcmail = rcube::get_instance();
// get arguments
$args = rcube_utils::get_opt(array(
'u' => 'user',
'h' => 'host',
'd' => 'dir',
'x' => 'dry-run',
));
if ($_SERVER['argv'][1] == 'help') {
print_usage();
exit;
}
if (empty($args['dir'])) {
rcube::raise_error("--dir argument is required", true);
}
$host = get_host($args);
$dirs = array();
// Read the homedir and iterate over all subfolders (as users)
if (empty($args['user'])) {
if ($dh = opendir($args['dir'])) {
while (($dir = readdir($dh)) !== false) {
if ($dir != '.' && $dir != '..') {
$dirs[$args['dir'] . '/' . $dir] = $dir;
}
}
closedir($dh);
}
}
// a single user
else {
$dirs = array($args['dir'] => $args['user']);
}
foreach ($dirs as $dir => $user) {
echo "Importing keys from $dir\n";
if ($user_id = get_user_id($user, $host)) {
reset_state($user_id, !empty($args['dry-run']));
import_dir($user_id, $dir, !empty($args['dry-run']));
}
}
function print_usage()
{
print "Usage: import.sh [options]\n";
print "Options:\n";
print " --user=username User, if not set --dir subfolders will be iterated\n";
print " --host=host The IMAP hostname or IP the given user is related to\n";
print " --dir=path Location of the gpg homedir\n";
print " --dry-run Do nothing, just list found user/files\n";
}
function get_host($args)
{
global $rcmail;
if (empty($args['host'])) {
$hosts = $rcmail->config->get('default_host', '');
if (is_string($hosts)) {
$args['host'] = $hosts;
}
else if (is_array($hosts) && count($hosts) == 1) {
$args['host'] = reset($hosts);
}
else {
rcube::raise_error("Specify a host name", true);
}
// host can be a URL like tls://192.168.12.44
$host_url = parse_url($args['host']);
if ($host_url['host']) {
$args['host'] = $host_url['host'];
}
}
return $args['host'];
}
function get_user_id($username, $host)
{
global $rcmail;
$db = $rcmail->get_dbh();
// find user in local database
$user = rcube_user::query($username, $host);
if (empty($user)) {
rcube::raise_error("User does not exist: $username");
}
return $user->ID;
}
function reset_state($user_id, $dry_run = false)
{
global $rcmail;
if ($dry_run) {
return;
}
$db = $rcmail->get_dbh();
$db->query("DELETE FROM " . $db->table_name('filestore', true)
. " WHERE `user_id` = ? AND `context` = ?",
$user_id, 'enigma');
}
function import_dir($user_id, $dir, $dry_run = false)
{
global $rcmail;
$db = $rcmail->get_dbh();
$table = $db->table_name('filestore', true);
$db_files = array('pubring.gpg', 'secring.gpg', 'pubring.kbx');
$maxsize = min($db->get_variable('max_allowed_packet', 1048500), 4*1024*1024) - 2000;
foreach (glob("$dir/private-keys-v1.d/*.key") as $file) {
$db_files[] = substr($file, strlen($dir) + 1);
}
foreach ($db_files as $file) {
if ($mtime = @filemtime("$dir/$file")) {
$data = file_get_contents("$dir/$file");
$data = base64_encode($data);
$datasize = strlen($data);
if ($datasize > $maxsize) {
rcube::raise_error(array(
'code' => 605, 'line' => __LINE__, 'file' => __FILE__,
'message' => "Enigma: Failed to save $file. Size exceeds max_allowed_packet."
), true, false);
continue;
}
echo "* $file\n";
if ($dry_run) {
continue;
}
$result = $db->query(
"INSERT INTO $table (`user_id`, `context`, `filename`, `mtime`, `data`)"
. " VALUES(?, 'enigma', ?, ?, ?)",
$user_id, $file, $mtime, $data);
if ($db->is_error($result)) {
rcube::raise_error(array(
'code' => 605, 'line' => __LINE__, 'file' => __FILE__,
'message' => "Enigma: Failed to save $file into database."
), true, false);
}
}
}
}