Added support for user-specified password for adminRecovery account in admin settings page
Made encryptAll() (file migration for unencrypted + legacy encrypted files) run only on first login for each user (status stored in DB) Made recoveryAdmin user member of 'admin' user group automatically Set recoveryadmin settings to only display on user settings if enabled by an admin Updated encryption db xml schema
This commit is contained in:
parent
9605d14a17
commit
c8946ea608
10 changed files with 215 additions and 89 deletions
|
@ -34,6 +34,9 @@ if (
|
|||
// Create new recoveryAdmin user
|
||||
\OC_User::createUser( $recoveryAdminUid, $_POST['recoveryPassword'] );
|
||||
|
||||
// Make recovery user an administrator
|
||||
\OC_Group::addToGroup ( $recoveryAdminUid, 'admin' );
|
||||
|
||||
$doSetup = true;
|
||||
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,13 @@
|
|||
<default>0</default>
|
||||
<comments>Whether encryption key recovery is enabled</comments>
|
||||
</field>
|
||||
<field>
|
||||
<name>migrationStatus</name>
|
||||
<type>boolean</type>
|
||||
<notnull>true</notnull>
|
||||
<default>0</default>
|
||||
<comments>Whether encryption migration has been performed</comments>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
</database>
|
|
@ -69,43 +69,52 @@ class Hooks {
|
|||
$session = new Session( $view );
|
||||
|
||||
$session->setPrivateKey( $privateKey, $params['uid'] );
|
||||
|
||||
//FIXME: disabled because it gets called each time a user do an operation on iPhone
|
||||
//FIXME: we need a better place doing this and maybe only one time or by user
|
||||
/*$view1 = new \OC_FilesystemView( '/' . $params['uid'] );
|
||||
|
||||
// Set legacy encryption key if it exists, to support
|
||||
// depreciated encryption system
|
||||
if (
|
||||
$view1->file_exists( 'encryption.key' )
|
||||
&& $encLegacyKey = $view1->file_get_contents( 'encryption.key' )
|
||||
) {
|
||||
// Check if first-run file migration has already been performed
|
||||
$migrationCompleted = $util->getMigrationStatus();
|
||||
|
||||
$plainLegacyKey = Crypt::legacyDecrypt( $encLegacyKey, $params['password'] );
|
||||
// If migration not yet done
|
||||
if ( ! $migrationCompleted ) {
|
||||
|
||||
$view1 = new \OC_FilesystemView( '/' . $params['uid'] );
|
||||
|
||||
$session->setLegacyKey( $plainLegacyKey );
|
||||
// Set legacy encryption key if it exists, to support
|
||||
// depreciated encryption system
|
||||
if (
|
||||
$view1->file_exists( 'encryption.key' )
|
||||
&& $encLegacyKey = $view1->file_get_contents( 'encryption.key' )
|
||||
) {
|
||||
|
||||
$plainLegacyKey = Crypt::legacyDecrypt( $encLegacyKey, $params['password'] );
|
||||
|
||||
$session->setLegacyKey( $plainLegacyKey );
|
||||
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
|
||||
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Encrypt existing user files:
|
||||
// This serves to upgrade old versions of the encryption
|
||||
// app (see appinfo/spec.txt)
|
||||
if (
|
||||
$util->encryptAll( $publicKey, '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
|
||||
) {
|
||||
|
||||
\OC_Log::write(
|
||||
'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
|
||||
, \OC_Log::INFO
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Register successful migration in DB
|
||||
$util->setMigrationStatus( 1 );
|
||||
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
|
||||
|
||||
\OC_FileProxy::$enabled = false;*/
|
||||
|
||||
// Encrypt existing user files:
|
||||
// This serves to upgrade old versions of the encryption
|
||||
// app (see appinfo/spec.txt)
|
||||
/*if (
|
||||
$util->encryptAll( $publicKey, '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
|
||||
) {
|
||||
|
||||
\OC_Log::write(
|
||||
'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" started at login'
|
||||
, \OC_Log::INFO
|
||||
);
|
||||
|
||||
}*/
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -19,14 +19,24 @@ $(document).ready(function(){
|
|||
function() {
|
||||
|
||||
var recoveryStatus = $( this ).val();
|
||||
var recoveryPassword = $( '#recoveryPassword' ).val();
|
||||
|
||||
$.post(
|
||||
OC.filePath( 'files_encryption', 'ajax', 'adminrecovery.php' )
|
||||
, { adminEnableRecovery: recoveryStatus, recoveryPassword: 'password' }
|
||||
, function( data ) {
|
||||
alert( data );
|
||||
}
|
||||
);
|
||||
if ( '' == recoveryPassword ) {
|
||||
|
||||
// FIXME: add proper OC notification
|
||||
alert( 'You must set a recovery account password first' );
|
||||
|
||||
} else {
|
||||
|
||||
$.post(
|
||||
OC.filePath( 'files_encryption', 'ajax', 'adminrecovery.php' )
|
||||
, { adminEnableRecovery: recoveryStatus, recoveryPassword: recoveryPassword }
|
||||
, function( data ) {
|
||||
alert( data );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -57,23 +57,23 @@ class Session {
|
|||
// our app.php is being executed 18 times per page load
|
||||
// , causing 18 new keypairs and huge performance hit.
|
||||
|
||||
$keypair = Crypt::createKeypair();
|
||||
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Save public key
|
||||
|
||||
if (!$view->is_dir('/public-keys')) {
|
||||
$view->mkdir('/public-keys');
|
||||
}
|
||||
|
||||
$this->view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] );
|
||||
|
||||
// Encrypt private key empthy passphrase
|
||||
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' );
|
||||
|
||||
// Save private key
|
||||
$this->view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey );
|
||||
// $keypair = Crypt::createKeypair();
|
||||
//
|
||||
// \OC_FileProxy::$enabled = false;
|
||||
//
|
||||
// // Save public key
|
||||
//
|
||||
// if (!$view->is_dir('/public-keys')) {
|
||||
// $view->mkdir('/public-keys');
|
||||
// }
|
||||
//
|
||||
// $this->view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] );
|
||||
//
|
||||
// // Encrypt private key empthy passphrase
|
||||
// $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' );
|
||||
//
|
||||
// // Save private key
|
||||
// $this->view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey );
|
||||
|
||||
\OC_FileProxy::$enabled = true;
|
||||
|
||||
|
|
|
@ -859,8 +859,6 @@ class Util {
|
|||
// Make sure users are capable of sharing
|
||||
$filteredUids = $this->filterShareReadyUsers( $users );
|
||||
|
||||
// trigger_error( print_r($filteredUids, 1) );
|
||||
|
||||
if ( ! empty( $filteredUids['unready'] ) ) {
|
||||
|
||||
// Notify user of unready userDir
|
||||
|
@ -913,10 +911,21 @@ class Util {
|
|||
public function getSharingUsersArray( $sharingEnabled, $filePath, $currentUserId = false ) {
|
||||
|
||||
// Check if key recovery is enabled
|
||||
$recoveryEnabled = $this->recoveryEnabledForUser();
|
||||
if (
|
||||
\OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' )
|
||||
&& $this->recoveryEnabledForUser()
|
||||
) {
|
||||
|
||||
$recoveryEnabled = true;
|
||||
|
||||
} else {
|
||||
|
||||
$recoveryEnabled = false;
|
||||
|
||||
}
|
||||
|
||||
// Make sure that a share key is generated for the owner too
|
||||
list($owner, $ownerPath) = $this->getUidAndFilename($filePath);
|
||||
list( $owner, $ownerPath ) = $this->getUidAndFilename( $filePath );
|
||||
|
||||
if ( $sharingEnabled ) {
|
||||
|
||||
|
@ -928,18 +937,21 @@ class Util {
|
|||
// If recovery is enabled, add the
|
||||
// Admin UID to list of users to share to
|
||||
if ( $recoveryEnabled ) {
|
||||
|
||||
// FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB?
|
||||
$adminUid = 'recoveryAdmin';
|
||||
|
||||
$userIds[] = $adminUid;
|
||||
|
||||
// Find recoveryAdmin user ID
|
||||
$recoveryAdminUid = \OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminUid' );
|
||||
|
||||
// Add recoveryAdmin to list of users sharing
|
||||
$userIds[] = $recoveryAdminUid;
|
||||
|
||||
}
|
||||
|
||||
// add current user if given
|
||||
if($currentUserId != false) {
|
||||
$userIds[] = $currentUserId;
|
||||
}
|
||||
// add current user if given
|
||||
if ( $currentUserId != false ) {
|
||||
|
||||
$userIds[] = $currentUserId;
|
||||
|
||||
}
|
||||
|
||||
// Remove duplicate UIDs
|
||||
$uniqueUserIds = array_unique ( $userIds );
|
||||
|
@ -947,6 +959,77 @@ class Util {
|
|||
return $uniqueUserIds;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set file migration status for user
|
||||
*/
|
||||
public function setMigrationStatus( $status ) {
|
||||
|
||||
$sql = 'UPDATE
|
||||
*PREFIX*encryption
|
||||
SET
|
||||
migrationStatus = ?
|
||||
WHERE
|
||||
uid = ?';
|
||||
|
||||
$args = array( $status, $this->userId );
|
||||
|
||||
$query = \OCP\DB::prepare( $sql );
|
||||
|
||||
if ( $query->execute( $args ) ) {
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether pwd recovery is enabled for a given user
|
||||
* @return 1 = yes, 0 = no, false = no record
|
||||
* @note If records are not being returned, check for a hidden space
|
||||
* at the start of the uid in db
|
||||
*/
|
||||
public function getMigrationStatus() {
|
||||
|
||||
$sql = 'SELECT
|
||||
migrationStatus
|
||||
FROM
|
||||
`*PREFIX*encryption`
|
||||
WHERE
|
||||
uid = ?';
|
||||
|
||||
$args = array( $this->userId );
|
||||
|
||||
$query = \OCP\DB::prepare( $sql );
|
||||
|
||||
$result = $query->execute( $args );
|
||||
|
||||
$migrationStatus = array();
|
||||
|
||||
while( $row = $result->fetchRow() ) {
|
||||
|
||||
$migrationStatus[] = $row['migrationStatus'];
|
||||
|
||||
}
|
||||
|
||||
// If no record is found
|
||||
if ( empty( $migrationStatus ) ) {
|
||||
|
||||
return false;
|
||||
|
||||
// If a record is found
|
||||
} else {
|
||||
|
||||
return $migrationStatus[0];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get uid of the owners of the file and the path to the file
|
||||
|
|
|
@ -21,6 +21,7 @@ $recoveryAdminUid = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminUi
|
|||
$tmpl->assign( 'blacklist', $blackList );
|
||||
$tmpl->assign( 'encryption_mode', \OC_Appconfig::getValue( 'files_encryption', 'mode', 'none' ) );
|
||||
$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
|
||||
$tmpl->assign( 'recoveryAdminUid', $recoveryAdminUid );
|
||||
|
||||
\OCP\Util::addscript( 'files_encryption', 'settings-admin' );
|
||||
\OCP\Util::addscript( 'core', 'multiselect' );
|
||||
|
|
|
@ -25,11 +25,13 @@ $user = \OCP\USER::getUser();
|
|||
$view = new \OC_FilesystemView( '/' );
|
||||
$util = new \OCA\Encryption\Util( $view, $user );
|
||||
|
||||
$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
|
||||
$recoveryEnabledForUser = $util->recoveryEnabledForUser();
|
||||
|
||||
\OCP\Util::addscript( 'files_encryption', 'settings-personal' );
|
||||
|
||||
$tmpl->assign( 'recoveryEnabled', $recoveryEnabledForUser );
|
||||
$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
|
||||
$tmpl->assign( 'recoveryEnabledForUser', $recoveryEnabledForUser );
|
||||
$tmpl->assign( 'blacklist', $blackList );
|
||||
|
||||
return $tmpl->fetchPage();
|
||||
|
|
|
@ -18,8 +18,17 @@
|
|||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<?php p($l->t( "Enable encryption passwords recovery account (allow sharing to recovery account):" )); ?>
|
||||
<strong>
|
||||
<?php p($l->t( "Enable encryption passwords recovery account (allow sharing to recovery account):" )); ?>
|
||||
<br />
|
||||
</strong>
|
||||
<?php p($l->t( "To perform a recovery log in using the 'recoveryAdmin' account and the specified password" )); ?>
|
||||
<br />
|
||||
<?php if ( empty( $_['recoveryAdminUid'] ) ): ?>
|
||||
<input type="password" name="recoveryPassword" id="recoveryPassword" />
|
||||
<label for="recoveryPassword">Recovery account password</label>
|
||||
<br />
|
||||
<?php endif; ?>
|
||||
<input
|
||||
type='radio'
|
||||
name='adminEnableRecovery'
|
||||
|
|
|
@ -21,24 +21,26 @@
|
|||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<p>
|
||||
<?php p($l->t( "Enable password recovery by sharing all files with administrator:" )); ?>
|
||||
<br />
|
||||
<input
|
||||
type='radio'
|
||||
name='userEnableRecovery'
|
||||
value='1'
|
||||
<?php echo ( $_["recoveryEnabled"] == 1 ? 'checked="checked"' : '' ); ?> />
|
||||
<?php p($l->t( "Enabled" )); ?>
|
||||
<br />
|
||||
|
||||
<input
|
||||
type='radio'
|
||||
name='userEnableRecovery'
|
||||
value='0'
|
||||
<?php echo ( $_["recoveryEnabled"] == 0 ? 'checked="checked"' : '' ); ?> />
|
||||
<?php p($l->t( "Disabled" )); ?>
|
||||
</p>
|
||||
<?php if ( $_["recoveryEnabled"] ): ?>
|
||||
<p>
|
||||
<?php p($l->t( "Enable password recovery by sharing all files with administrator:" )); ?>
|
||||
<br />
|
||||
<input
|
||||
type='radio'
|
||||
name='userEnableRecovery'
|
||||
value='1'
|
||||
<?php echo ( $_["recoveryEnabledForUser"] == 1 ? 'checked="checked"' : '' ); ?> />
|
||||
<?php p($l->t( "Enabled" )); ?>
|
||||
<br />
|
||||
|
||||
<input
|
||||
type='radio'
|
||||
name='userEnableRecovery'
|
||||
value='0'
|
||||
<?php echo ( $_["recoveryEnabledForUser"] == 0 ? 'checked="checked"' : '' ); ?> />
|
||||
<?php p($l->t( "Disabled" )); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
Loading…
Reference in a new issue