Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js re-encryption bug fixes #768

Merged
merged 11 commits into from
May 2, 2023
Merged
3 changes: 3 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,17 @@
['name' => 'share#getPendingRequests', 'url' => '/api/v2/sharing/pending', 'verb' => 'GET'],
['name' => 'share#deleteShareRequest', 'url' => '/api/v2/sharing/decline/{share_request_id}', 'verb' => 'DELETE'],
['name' => 'share#getVaultItems', 'url' => '/api/v2/sharing/vault/{vault_guid}/get', 'verb' => 'GET'],
['name' => 'share#getVaultAclEntries', 'url' => '/api/v2/sharing/vault/{vault_guid}/acl', 'verb' => 'GET'],
['name' => 'share#createPublicShare', 'url' => '/api/v2/sharing/public', 'verb' => 'POST'],
['name' => 'share#getPublicCredentialData', 'url' => '/api/v2/sharing/credential/{credential_guid}/public', 'verb' => 'GET'],
['name' => 'share#unshareCredential', 'url' => '/api/v2/sharing/credential/{item_guid}', 'verb' => 'DELETE'],
['name' => 'share#unshareCredentialFromUser', 'url' => '/api/v2/sharing/credential/{item_guid}/{user_id}', 'verb' => 'DELETE'],
['name' => 'share#getRevisions', 'url' => '/api/v2/sharing/credential/{item_guid}/revisions', 'verb' => 'GET'],
['name' => 'share#getItemAcl', 'url' => '/api/v2/sharing/credential/{item_guid}/acl', 'verb' => 'GET'],
['name' => 'share#uploadFile', 'url' => '/api/v2/sharing/credential/{item_guid}/file', 'verb' => 'POST'],
['name' => 'share#getFile', 'url' => '/api/v2/sharing/credential/{item_guid}/file/{file_guid}', 'verb' => 'GET'],
['name' => 'share#updateSharedCredentialACL', 'url' => '/api/v2/sharing/credential/{item_guid}/acl', 'verb' => 'PATCH'],
['name' => 'share#updateSharedCredentialACLSharedKey', 'url' => '/api/v2/sharing/credential/{item_guid}/acl/shared_key', 'verb' => 'PATCH'],
['name' => 'internal#getAppVersion', 'url' => '/api/v2/version', 'verb' => 'GET'],

//Settings
Expand Down
4 changes: 4 additions & 0 deletions controller/filecontroller.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ public function deleteFiles($file_ids) {
return new JSONResponse(array('ok' => empty($failed_file_ids), 'failed' => $failed_file_ids));
}

/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function updateFile($file_id, $file_data, $filename) {
try {
$file = $this->fileService->getFile($file_id, $this->userId);
Expand Down
76 changes: 73 additions & 3 deletions controller/sharecontroller.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,20 @@ public function getVaultItems($vault_guid) {
}
}

/**
* Obtains the list of acl entries for credentials shared with this vault
*
* @NoAdminRequired
* @NoCSRFRequired
*/
public function getVaultAclEntries($vault_guid) {
try {
return new JSONResponse($this->shareService->getVaultAclList($this->userId->getUID(), $vault_guid));
} catch (\Exception $ex) {
return new NotFoundResponse();
}
}

/**
* @param $share_request_id
* @return JSONResponse
Expand Down Expand Up @@ -476,13 +490,55 @@ public function getFile($item_guid, $file_guid) {
} catch (\Exception $e) {
return new NotFoundJSONResponse();
}

// $this->userId does not exist for anonymous share link downloads
$userId = ($this->userId) ? $this->userId->getUID() : null;
$acl = $this->shareService->getACL($userId, $credential->getGuid());
if (!$acl->hasPermission(SharingACL::FILES)) {

if ($acl->hasPermission(SharingACL::FILES)) {
// get file by guid and check if it is owned by the owner of the shared credential
return $this->fileService->getFileByGuid($file_guid, $credential->getUserId());
}

return new NotFoundJSONResponse();
}

/**
* @param $item_guid
* @param $data
* @param $filename
* @param $mimetype
* @param $size
* @return DataResponse|NotFoundJSONResponse|JSONResponse
* @throws \Exception
* @NoAdminRequired
* @NoCSRFRequired
*/
public function uploadFile($item_guid, $data, $filename, $mimetype, $size) {
try {
$credential = $this->credentialService->getCredentialByGUID($item_guid);
} catch (\Exception $e) {
return new NotFoundJSONResponse();
} else {
return $this->fileService->getFileByGuid($file_guid);
}

// only check acl, if the uploading user is not the credential owner
if ($credential->getUserId() != $this->userId->getUID()) {
$acl = $this->shareService->getACL($this->userId->getUID(), $credential->getGuid());
if (!$acl->hasPermission(SharingACL::FILES)) {
return new DataResponse(['msg' => 'Not authorized'], Http::STATUS_UNAUTHORIZED);
}
}

$file = array(
'filename' => $filename,
'size' => $size,
'mimetype' => $mimetype,
'file_data' => $data,
'user_id' => $credential->getUserId()
);

// save the file with the id of the user that owns the credential
return new JSONResponse($this->fileService->createFile($file, $credential->getUserId()));
}

/**
Expand Down Expand Up @@ -515,4 +571,18 @@ public function updateSharedCredentialACL($item_guid, $user_id, $permission) {

}
}

/**
* @param $item_guid
* @param $shared_key
* @return JSONResponse
* @NoAdminRequired
* @NoCSRFRequired
*/
public function updateSharedCredentialACLSharedKey($item_guid, $shared_key) {
/** @var SharingACL $acl */
$acl = $this->shareService->getACL($this->userId->getUID(), $item_guid);
$acl->setSharedKey($shared_key);
return new JSONResponse($this->shareService->updateCredentialACL($acl)->jsonSerialize());
}
}
1 change: 1 addition & 0 deletions controller/translationcontroller.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public function getLanguageStrings() {
'credential.recovered' => $this->trans->t('Credential recovered'),
'credential.destroyed' => $this->trans->t('Credential destroyed'),
'error.loading.file.perm' => $this->trans->t('Error downloading file, you probably have insufficient permissions'),
'error.general' => $this->trans->t('An error occurred'),

// js/app/controllers/edit_credential.js
'invalid.qr' => $this->trans->t('Invalid QR code'),
Expand Down
82 changes: 47 additions & 35 deletions js/app/controllers/credential.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,18 @@
try {
if (!_credential.shared_key) {
_credential = CredentialService.decryptCredential(angular.copy(_credential));

} else {
var enc_key = EncryptService.decryptString(_credential.shared_key);
_credential = ShareService.decryptSharedCredential(angular.copy(_credential), enc_key);
}
_credential.tags_raw = _credential.tags;
} catch (e) {

NotificationService.showNotification($translate.instant('error.decrypt'), 5000);
console.error(e);
//$rootScope.$broadcast('logout');
//SettingsService.setSetting('defaultVaultPass', null);
//.setSetting('defaultVault', null);
//$location.path('/')

}
_credentials[i] = _credential;
}
Expand Down Expand Up @@ -181,10 +179,10 @@

private_key = ShareService.rsaPrivateKeyFromPEM(private_key);
/** global: forge */
crypted_shared_key = private_key.decrypt(forge.util.decode64(crypted_shared_key));
crypted_shared_key = EncryptService.encryptString(crypted_shared_key);
const decrypted_shared_key = private_key.decrypt(forge.util.decode64(crypted_shared_key));
const vault_key_encrypted_shared_key = EncryptService.encryptString(decrypted_shared_key);

ShareService.saveSharingRequest(share_request, crypted_shared_key).then(function () {
ShareService.saveSharingRequest(share_request, vault_key_encrypted_shared_key).then(function () {
var idx = $scope.incoming_share_requests.indexOf(share_request);
$scope.incoming_share_requests.splice(idx, 1);
var active_share_requests = false;
Expand Down Expand Up @@ -261,54 +259,62 @@
};

var notification;
$scope.deleteCredential = function (credential) {
var _credential = angular.copy(credential);
try {
_credential = CredentialService.decryptCredential(_credential);
} catch (e) {

}
$scope.deleteCredential = function (decrypted_credential) {
let _credential = angular.copy(decrypted_credential);
_credential.delete_time = new Date().getTime() / 1000;
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
$scope.active_vault.credentials[i].delete_time = _credential.delete_time;
}
}

$scope.closeSelected();
if (notification) {
NotificationService.hideNotification(notification);
}
var key = CredentialService.getSharedKeyFromCredential(_credential);
CredentialService.updateCredential(_credential, false, key).then(function () {

const key = CredentialService.getSharedKeyFromCredential(_credential);
CredentialService.updateCredential(_credential, false, key).then(function (response) {
decrypted_credential.delete_time = _credential.delete_time;
for (let i = 0; i < $scope.active_vault.credentials.length; i++) {
if ($scope.active_vault.credentials[i].credential_id === _credential.credential_id) {
$scope.active_vault.credentials[i].delete_time = _credential.delete_time;
}
}
notification = NotificationService.showNotification($translate.instant('credential.deleted'), 5000);
}, function (error) {
if (error.data.msg) {
NotificationService.showNotification(error.data.msg, 5000);
} else {
NotificationService.showNotification($translate.instant('error.general'), 5000);
}
});
};

$scope.recoverCredential = function (credential) {
var _credential = angular.copy(credential);
try {
_credential = CredentialService.decryptCredential(_credential);
} catch (e) {

}
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
$scope.active_vault.credentials[i].delete_time = 0;
}
}
$scope.recoverCredential = function (decrypted_credential) {
let _credential = angular.copy(decrypted_credential);
_credential.delete_time = 0;

$scope.closeSelected();
if (notification) {
NotificationService.hideNotification(notification);
}
var key = CredentialService.getSharedKeyFromCredential(_credential);
CredentialService.updateCredential(_credential, false, key).then(function () {

const key = CredentialService.getSharedKeyFromCredential(_credential);
CredentialService.updateCredential(_credential, false, key).then(function (response) {
decrypted_credential.delete_time = 0;
for (let i = 0; i < $scope.active_vault.credentials.length; i++) {
if ($scope.active_vault.credentials[i].credential_id === _credential.credential_id) {
$scope.active_vault.credentials[i].delete_time = 0;
}
}
NotificationService.showNotification($translate.instant('credential.recovered'), 5000);
}, function (error) {
if (error.data.msg) {
NotificationService.showNotification(error.data.msg, 5000);
} else {
NotificationService.showNotification($translate.instant('error.general'), 5000);
}
});
};

$scope.destroyCredential = function (credential) {
var _credential = angular.copy(credential);
const _credential = angular.copy(credential);
CredentialService.destroyCredential(_credential.guid).then(function () {
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
Expand All @@ -317,6 +323,12 @@
break;
}
}
}, function (error) {
if (error.data.msg) {
NotificationService.showNotification(error.data.msg, 5000);
} else {
NotificationService.showNotification($translate.instant('error.general'), 5000);
}
});
};

Expand Down
Loading