Skip to content

Commit

Permalink
Header backup and restore functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
imgrant committed Nov 10, 2015
1 parent 866a86f commit 8fba137
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 9 deletions.
5 changes: 3 additions & 2 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
openmediavault-luksencryption (1.0.6) UNRELEASED; urgency=medium
openmediavault-luksencryption (1.1.0) UNRELEASED; urgency=medium

* Update dependencies (require OpenMediaVault>=2.1.19).
* Code formatting (e.g. tabs to spaces, 4-space indent etc.).
* Increase width of UI windows slightly.
* Auto-mount known filesystems when unlocking (use OMV_LUKS_MOUNT_ON_UNLOCK to disable).
* Added header backup and restore functionality.

-- OpenMediaVault Plugin Developers <[email protected]> Tue, 10 Nov 2015 11:21:33 +0000
-- OpenMediaVault Plugin Developers <[email protected]> Tue, 10 Nov 2015 16:07:48 +0000

openmediavault-luksencryption (1.0.2) unstable; urgency=low

Expand Down
Empty file modified debian/control
100755 → 100644
Empty file.
Empty file modified usr/share/openmediavault/engined/module/luks.inc
100755 → 100644
Empty file.
118 changes: 118 additions & 0 deletions usr/share/openmediavault/engined/rpc/luks.inc
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class OMVRpcServiceLuksMgmt extends OMVRpcServiceAbstract {
$this->registerMethod("addContainerPassphrase");
$this->registerMethod("changeContainerPassphrase");
$this->registerMethod("removeContainerPassphrase");
$this->registerMethod("backupContainerHeader");
$this->registerMethod("restoreContainerHeader");
}

/**
Expand Down Expand Up @@ -110,6 +112,7 @@ class OMVRpcServiceLuksMgmt extends OMVRpcServiceAbstract {
* array. An exception will be thrown in case of an error.
*/
function getContainersList($params, $context) {
global $xmlConfig;
// Validate the RPC caller context.
$this->validateMethodContext($context, array(
"role" => OMV_ROLE_ADMINISTRATOR
Expand Down Expand Up @@ -609,6 +612,121 @@ class OMVRpcServiceLuksMgmt extends OMVRpcServiceAbstract {
$luks->getLastError()));
}
}

/**
* Backup the container header.
* @param params An array containing the following fields:
* \em devicefile The device file of the container to modify.
* @param context The context of the caller.
* @return An array with the following keys:
* \em filename Filename of the header backup being downloaded.
* \em filepath Location of the temporary file.
* \em unlink Whether to delete the temporary file after downloading.
* @throw E_MISC_FAILURE
* @throw E_EXEC_FAILED
*/
public function backupContainerHeader($params, $context) {
// Validate the RPC caller context.
$this->validateMethodContext($context, array(
"role" => OMV_ROLE_ADMINISTRATOR
));
// Validate the parameters of the RPC service method.
$this->validateMethodParams($params, '{
"type":"object",
"properties":{
"devicefile":{'.$GLOBALS['OMV_JSONSCHEMA_DEVICEFILE'].'}
}
}');
// Check if container exists.
$luks = new OMVLuksContainer($params['devicefile']);
if (FALSE === $luks->exists()) {
throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
sprintf("No encryption found on '%s'",
$params['devicefile']));
}
// Extract the header to a temporary location and modify the
// file mode/owner to allow the WebGUI PHP backend to unlink it.
$tmpFilePath = sys_get_temp_dir()."/".uniqid("luksHeader");
$params['backupfile'] = $tmpFilePath;
if (!$luks->backupHeader($params)) {
throw new OMVException(OMVErrorMsg::E_EXEC_MISC, sprintf(
gettext("Failed to extract the LUKS header from ".
"the encrypted device: %s"),
$luks->getLastError()));
}
// Adjust header backup temporary file permissions and ownership so
// that the WebGUI can delete it after downloading.
chmod($tmpFilePath, 0600);
chgrp($tmpFilePath, $GLOBALS['OMV_WEBGUI_FILE_OWNERGROUP_NAME']);
chown($tmpFilePath, $GLOBALS['OMV_WEBGUI_FILE_OWNERGROUP_NAME']);
// Return values required by generic download RPC implementation.
return array(
"filename" => "LUKS_header_".$luks->getUuid().".bak",
"filepath" => $tmpFilePath,
"contenttype" => "application/octet-stream",
"unlink" => TRUE
);
}

/**
* Restore the container header.
* @param params An array containing the following fields:
* \em devicefile The device file of the container to modify.
* \em filename The original name of the file.
* \em filepath The path to the uploaded file.
* @param context The context of the caller.
* @return None
* @throw E_MISC_DEVICE_NOT_FOUND
* @throw E_MISC_FAILURE
* @throw E_EXEC_FAILED
*/
public function restoreContainerHeader($params, $context) {
print_r($params);
// Validate the RPC caller context.
$this->validateMethodContext($context, array(
"role" => OMV_ROLE_ADMINISTRATOR
));
// Validate the parameters of the RPC service method.
$this->validateMethodParams($params, '{
"type":"object",
"properties":{
"devicefile":{'.$GLOBALS['OMV_JSONSCHEMA_DEVICEFILE'].'},
"filename":{"type":"string"},
"filepath":{"type":"string"}
}
}');
// Get the storage device object.
$sd = OMVStorageDeviceFactory::get($params['devicefile']);
if (is_null($sd) || !$sd->exists()) {
throw new OMVException(OMVErrorMsg::E_MISC_DEVICE_NOT_FOUND,
$params['devicefile']);
}
// Get the storage device backend of the given device.
$sdb = OMVStorageDevices::getBackend($sd->getDeviceFile());
if (is_null($sdb)) {
throw new OMVException(OMVErrorMsg::E_MISC_FAILURE, sprintf(
"No storage device backend exists for device %s",
$sd->getDeviceFile()));
}
// Validate the new header
$cmd = sprintf("export LANG=C; cryptsetup isLuks %s 2>&1",
$params['filepath']);
@OMVUtil::exec($cmd, $output, $result);
if ($result !== 0) {
throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
sprintf("%s is not a valid LUKS header backup file",
$params['filename']));
}
// Write the header to the device
$luks = new OMVLuksContainer($params['devicefile']);
if (!$luks->restoreHeader($params)) {
throw new OMVException(OMVErrorMsg::E_EXEC_MISC, sprintf(
gettext("Failed to restore the LUKS header to ".
"device %s: %s"),
$params['devicefile'],
$luks->getLastError()));
}
}
}

// Register the RPC service.
Expand Down
48 changes: 46 additions & 2 deletions usr/share/php/openmediavault/luks.inc
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@ class OMVLuksContainer extends OMVStorageDeviceAbstract {
* Open (unlock) the container.
* @param passphrase A passphrase that will unlock the LUKS device.
* @return TRUE if successful, otherwise FALSE.
* TODO: change from using [dev]-crypt as the mapper name to the UUID of
* container instead (unique, probably will be needed for crypttab)
*/
public function open($passphrase) {
$cmd = sprintf("export LANG=C; echo -n %s ".
Expand Down Expand Up @@ -544,6 +546,48 @@ class OMVLuksContainer extends OMVStorageDeviceAbstract {
$this->refresh();
return TRUE;
}

/**
* Backup the header for the container.
* @param params An array containing the following fields:
* \em devicefile The device file representing the LUKS container.
* \em backupfile The filename to write the header backup to.
* @return TRUE if successful, otherwise FALSE.
*/
public function backupHeader($params) {
$cmd = sprintf("export LANG=C; cryptsetup luksHeaderBackup ".
"%s --header-backup-file %s 2>&1",
escapeshellarg($params['devicefile']),
escapeshellarg($params['backupfile']));
@OMVUtil::exec($cmd, $output, $result);
if($result !== 0) {
$this->setLastError($output);
return FALSE;
}
return TRUE;
}

/**
* Restore the header for the container from a backup.
* @param params An array containing the following fields:
* \em devicefile The device file representing the LUKS container.
* \em filename The original name of the header file as uploaded.
* \em filepath The path to the header backup file.
* @return TRUE if successful, otherwise FALSE.
*/
public function restoreHeader($params) {
$cmd = sprintf("export LANG=C; cryptsetup luksHeaderRestore -q ".
"%s --header-backup-file %s 2>&1",
escapeshellarg($params['devicefile']),
escapeshellarg($params['filepath']));
@OMVUtil::exec($cmd, $output, $result);
if($result !== 0) {
$this->setLastError($output);
return FALSE;
}
$this->refresh();
return TRUE;
}
}


Expand Down Expand Up @@ -582,7 +626,7 @@ class OMVStorageDeviceLUKS extends OMVStorageDeviceDM {
*/
public function getLuksEncryptedDeviceName($canonical = FALSE) {
$deviceName = str_replace("/dev/", "", !$canonical ?
$this->getLuksEncryptedDeviceFile() :
$this->getLuksEncryptedDeviceFile() :
$this->getCanonicalLuksEncryptedDeviceFile());
return $deviceName;
}
Expand Down Expand Up @@ -664,4 +708,4 @@ class OMVStorageDeviceBackendLUKS extends OMVStorageDeviceBackendDM {
///////////////////////////////////////////////////////////////////////////////
// Register new storage device backend.
///////////////////////////////////////////////////////////////////////////////
OMVStorageDevices::registerBackend(new OMVStorageDeviceBackendLUKS());
OMVStorageDevices::registerBackend(new OMVStorageDeviceBackendLUKS());
Loading

0 comments on commit 8fba137

Please sign in to comment.