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:
Sam Tuke 2013-05-04 16:14:38 +02:00
parent 9605d14a17
commit c8946ea608
10 changed files with 215 additions and 89 deletions

View file

@ -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 {

View file

@ -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>

View file

@ -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;

View file

@ -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 );
}
);
}
}
);

View file

@ -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;

View file

@ -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

View 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' );

View file

@ -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();

View file

@ -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'

View file

@ -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>