Beispiel #1
0
        /// <summary>
        /// Enumerate all files listed as active, checking for status changes and take appropriate actions such as updating status
        /// in the FileSystemState, re-encrypting or deleting temporary plaintext copies.
        /// </summary>
        /// <param name="_fileSystemState">The FileSystemState to enumerate and possibly update.</param>
        /// <param name="mode">Under what circumstances is the FileSystemState.Changed event raised.</param>
        /// <param name="progress">The ProgressContext to provide visual progress feedback via.</param>
        public virtual async Task CheckActiveFiles(IProgressContext progress)
        {
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                progress.AddTotal(Resolve.FileSystemState.ActiveFileCount);
                await Resolve.FileSystemState.ForEach(async (ActiveFile activeFile) =>
                {
                    try
                    {
                        activeFile = await CheckActiveFile(activeFile, progress).Free();
                        if (activeFile.Status == ActiveFileStatus.NotDecrypted && !activeFile.EncryptedFileInfo.IsAvailable)
                        {
                            activeFile = null;
                        }
                        return(activeFile);
                    }
                    finally
                    {
                        progress.AddCount(1);
                    }
                }).Free();
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
        }
Beispiel #2
0
        public virtual async Task RemoveRecentFiles(IEnumerable <IDataStore> encryptedPaths, IProgressContext progress)
        {
            if (encryptedPaths == null)
            {
                throw new ArgumentNullException("encryptedPaths");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                progress.AddTotal(encryptedPaths.Count());
                foreach (IDataStore encryptedPath in encryptedPaths)
                {
                    ActiveFile activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(encryptedPath.FullName);
                    if (activeFile != null)
                    {
                        Resolve.FileSystemState.RemoveActiveFile(activeFile);
                    }
                    progress.AddCount(1);
                }
                await Resolve.FileSystemState.Save().Free();
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
        }
        public virtual async Task EncryptFoldersUniqueWithBackupAndWipeAsync(IEnumerable <IDataContainer> containers, EncryptionParameters encryptionParameters, IProgressContext progress)
        {
            if (containers == null)
            {
                throw new ArgumentNullException("containers");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                List <IDataStore> files = new List <IDataStore>();
                foreach (IDataContainer container in containers)
                {
                    files.AddRange(await container.ListEncryptableWithWarningAsync(containers, New <UserSettings>().FolderOperationMode.Policy()));
                }

                progress.AddTotal(files.Count());
                foreach (IDataStore file in files)
                {
                    await EncryptFileUniqueWithBackupAndWipeAsync(file, encryptionParameters, progress);

                    progress.AddCount(1);
                    progress.Totals.AddFileCount(1);
                }
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
        }
Beispiel #4
0
        /// <summary
        /// Instantiates a worker group with specified maximum concurrency and external progress reporting. Progress
        /// will be reported on the thread instantiating the ProgressContext used.
        /// </summary>
        /// <param name="maxConcurrent">The maximum number of worker threads active at any one time</param>
        /// <param name="progress">The ProgressContext that receives progress notifications</param>
        public WorkerGroup(int maxConcurrent, IProgressContext progress)
        {
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            _concurrencyControlSemaphore = Resolve.Portable.Semaphore(maxConcurrent, maxConcurrent);
            _maxConcurrencyCount         = maxConcurrent;
            _singleThread = Resolve.Portable.SingleThread();
            FirstError    = new FileOperationContext(String.Empty, ErrorStatus.Success);
            progress.NotifyLevelStart();
            Progress = new WorkerGroupProgressContext(progress, _singleThread);
        }
        public virtual async Task EncryptFileWithBackupAndWipeAsync(IDataStore sourceStore, FileLock destinationStore, EncryptionParameters encryptionParameters, IProgressContext progress)
        {
            if (sourceStore == null)
            {
                throw new ArgumentNullException("sourceStore");
            }
            if (destinationStore == null)
            {
                throw new ArgumentNullException("destinationStore");
            }
            if (encryptionParameters == null)
            {
                throw new ArgumentNullException("encryptionParameters");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                using (FileLock sourceFileLock = New <FileLocker>().Acquire(sourceStore))
                {
                    using (Stream activeFileStream = sourceStore.OpenRead())
                    {
                        await EncryptToFileWithBackupAsync(destinationStore, (Stream destination) =>
                        {
                            Encrypt(sourceStore, destination, encryptionParameters, AxCryptOptions.EncryptWithCompression, progress);
                            return(Constant.CompletedTask);
                        }, progress);

                        if (sourceStore.IsWriteProtected)
                        {
                            destinationStore.DataStore.IsWriteProtected = true;
                        }
                    }
                    if (sourceStore.IsWriteProtected)
                    {
                        sourceStore.IsWriteProtected = false;
                    }
                    Wipe(sourceFileLock, progress);
                }
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
        }
Beispiel #6
0
        /// <summary>
        /// Try do delete files that have been decrypted temporarily, if the conditions are met for such a deletion,
        /// i.e. it is apparently not locked or in use etc.
        /// </summary>
        /// <param name="_fileSystemState">The instance of FileSystemState where active files are recorded.</param>
        /// <param name="progress">The context where progress may be reported.</param>
        public virtual async Task PurgeActiveFiles(IProgressContext progress)
        {
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                await Resolve.FileSystemState.ForEach(async (ActiveFile activeFile) =>
                {
                    if (activeFile.Status.HasMask(ActiveFileStatus.Exception))
                    {
                        return(activeFile);
                    }
                    if (New <FileLocker>().IsLocked(activeFile.DecryptedFileInfo))
                    {
                        if (Resolve.Log.IsInfoEnabled)
                        {
                            Resolve.Log.LogInfo("Not deleting '{0}' because it is marked as locked.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
                        }
                        return(activeFile);
                    }
                    if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable))
                    {
                        activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable);
                    }
                    using (FileLock encryptedFileLock = New <FileLocker>().Acquire(activeFile.EncryptedFileInfo))
                    {
                        using (FileLock decryptedFileLock = New <FileLocker>().Acquire(activeFile.DecryptedFileInfo))
                        {
                            activeFile = await CheckIfTimeToUpdate(activeFile, encryptedFileLock, decryptedFileLock, progress).Free();
                            if (activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
                            {
                                activeFile = await TryDelete(activeFile, decryptedFileLock, progress).Free();
                            }
                        }
                    }
                    return(activeFile);
                }).Free();
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
        }
        public Task <FileOperationContext> DecryptFileUniqueWithWipeOfOriginalAsync(IDataStore sourceStore, LogOnIdentity logOnIdentity, IProgressContext progress)
        {
            if (sourceStore == null)
            {
                throw new ArgumentNullException("sourceStore");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            if (sourceStore.IsWriteProtected)
            {
                return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.CannotWriteDestination)));
            }

            progress.NotifyLevelStart();
            try
            {
                using (IAxCryptDocument document = New <AxCryptFile>().Document(sourceStore, logOnIdentity, progress))
                {
                    if (!document.PassphraseIsValid)
                    {
                        return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.Canceled)));
                    }

                    IDataStore destinationStore = New <IDataStore>(Resolve.Portable.Path().Combine(Resolve.Portable.Path().GetDirectoryName(sourceStore.FullName), document.FileName));
                    using (FileLock lockedDestination = destinationStore.FullName.CreateUniqueFile())
                    {
                        DecryptFile(document, lockedDestination.DataStore.FullName, progress);
                    }
                }
                using (FileLock sourceFileLock = New <FileLocker>().Acquire(sourceStore))
                {
                    Wipe(sourceFileLock, progress);
                }
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
            return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.Success)));
        }
Beispiel #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProgressStream"/> class.
        /// </summary>
        /// <param name="stream">The stream. Will be disposed of when this instance is disposed.</param>
        /// <param name="progress">The progress.</param>
        /// <exception cref="System.ArgumentNullException">
        /// stream
        /// or
        /// progress
        /// </exception>
        public ProgressStream(Stream stream, IProgressContext progress)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }
            WrappedStream = stream;
            _progress     = progress;

            _progress.NotifyLevelStart();
            if (stream.CanSeek)
            {
                _progress.AddTotal(WrappedStream.Length - WrappedStream.Position);
            }
        }
 private Task <bool> IntegrityCheckOperationAsync()
 {
     _progress.NotifyLevelStart();
     try
     {
         Stream stream = _eventArgs.AxCryptFile.OpenRead();
         using (FormatIntegrityChecker integrityChecker = new FormatIntegrityChecker(stream, _eventArgs.OpenFileFullName))
         {
             integrityChecker.Verify();
         }
     }
     catch (AxCryptException ace)
     {
         New <IReport>().Exception(ace);
         _eventArgs.Status = new FileOperationContext(_eventArgs.OpenFileFullName, ace.ErrorStatus);
         return(Task.FromResult(false));
     }
     finally
     {
         _progress.NotifyLevelFinished();
     }
     _eventArgs.Status = new FileOperationContext(_eventArgs.OpenFileFullName, ErrorStatus.Success);
     return(Task.FromResult(true));
 }
        /// <summary>
        /// Changes the encryption for all encrypted files in the provided containers, using the original identity to decrypt
        /// and the provided encryption parameters for the new encryption.
        /// </summary>
        /// <remarks>
        /// If a file is already encrypted with the appropriate parameters, nothing happens.
        /// </remarks>
        /// <param name="containers">The containers.</param>
        /// <param name="identity">The identity.</param>
        /// <param name="encryptionParameters">The encryption parameters.</param>
        /// <param name="progress">The progress.</param>
        /// <exception cref="System.ArgumentNullException">
        /// containers
        /// or
        /// progress
        /// </exception>
        public virtual async Task ChangeEncryptionAsync(IEnumerable <IDataContainer> containers, LogOnIdentity identity, EncryptionParameters encryptionParameters, IProgressContext progress)
        {
            if (containers == null)
            {
                throw new ArgumentNullException("containers");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            progress.NotifyLevelStart();
            try
            {
                IEnumerable <IDataStore> files = containers.SelectMany((folder) => folder.ListEncrypted(containers, New <UserSettings>().FolderOperationMode.Policy()));
                await ChangeEncryptionAsync(files, identity, encryptionParameters, progress);
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
            await Resolve.SessionNotify.NotifyAsync(new SessionNotification(SessionNotificationType.ActiveFileChange));
        }
        public virtual void Wipe(FileLock store, IProgressContext progress)
        {
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            if (store == null)
            {
                throw new ArgumentNullException("store");
            }
            if (!store.DataStore.IsAvailable)
            {
                return;
            }
            if (Resolve.Log.IsInfoEnabled)
            {
                Resolve.Log.LogInfo("Wiping '{0}'.".InvariantFormat(store.DataStore.Name));
            }
            progress.Cancel = false;
            bool cancelPending = false;

            progress.NotifyLevelStart();
            try
            {
                string randomName;
                do
                {
                    randomName = GenerateRandomFileName(store.DataStore.FullName);
                } while (New <IDataStore>(randomName).IsAvailable);
                IDataStore moveToFileInfo = New <IDataStore>(store.DataStore.FullName);
                moveToFileInfo.MoveTo(randomName);
                moveToFileInfo.IsWriteProtected = false;
                using (Stream stream = moveToFileInfo.OpenUpdate())
                {
                    long length = stream.Length + OS.Current.StreamBufferSize - stream.Length % OS.Current.StreamBufferSize;
                    progress.AddTotal(length);
                    for (long position = 0; position < length; position += OS.Current.StreamBufferSize)
                    {
                        byte[] random = Resolve.RandomGenerator.Generate(OS.Current.StreamBufferSize);
                        stream.Write(random, 0, random.Length);
                        stream.Flush();
                        try
                        {
                            progress.AddCount(random.Length);
                        }
                        catch (OperationCanceledException)
                        {
                            cancelPending = true;
                            progress.AddCount(random.Length);
                        }
                    }
                }

                moveToFileInfo.Delete();
            }
            finally
            {
                progress.NotifyLevelFinished();
            }
            if (cancelPending)
            {
                throw new OperationCanceledException("Delayed cancel during wipe.");
            }
        }
        private async Task HandleNotificationInternalAsync(SessionNotification notification, IProgressContext progress)
        {
            if (Resolve.Log.IsInfoEnabled)
            {
                Resolve.Log.LogInfo("Received notification type '{0}'.".InvariantFormat(notification.NotificationType));
            }
            EncryptionParameters encryptionParameters;

            switch (notification.NotificationType)
            {
            case SessionNotificationType.WatchedFolderAdded:
            case SessionNotificationType.WatchedFolderOptionsChanged:
                progress.NotifyLevelStart();
                try
                {
                    foreach (string fullName in notification.FullNames)
                    {
                        WatchedFolder watchedFolder = _fileSystemState.WatchedFolders.First(wf => wf.Path == fullName);

                        encryptionParameters = new EncryptionParameters(Resolve.CryptoFactory.Default(New <ICryptoPolicy>()).CryptoId, notification.Identity);
                        await encryptionParameters.AddAsync(await watchedFolder.KeyShares.ToAvailableKnownPublicKeysAsync(notification.Identity));

                        IDataContainer container = New <IDataContainer>(watchedFolder.Path);
                        progress.Display = container.Name;
                        IDataContainer[] dc = new IDataContainer[] { container };
                        await _axCryptFile.EncryptFoldersUniqueWithBackupAndWipeAsync(dc, encryptionParameters, progress);
                    }
                }
                finally
                {
                    progress.NotifyLevelFinished();
                }
                progress.Totals.ShowNotification();
                break;

            case SessionNotificationType.WatchedFolderRemoved:
                foreach (string fullName in notification.FullNames)
                {
                    IDataContainer removedFolderInfo = New <IDataContainer>(fullName);
                    progress.Display = removedFolderInfo.Name;
                    if (removedFolderInfo.IsAvailable)
                    {
                        await _axCryptFile.DecryptFilesInsideFolderUniqueWithWipeOfOriginalAsync(removedFolderInfo, notification.Identity, _statusChecker, progress).Free();
                    }
                }
                break;

            case SessionNotificationType.SignIn:
                await EncryptWatchedFoldersIfSupportedAsync(notification.Identity, notification.Capabilities, progress);

                break;

            case SessionNotificationType.SignOut:
                New <IInternetState>().Clear();
                New <ICache>().RemoveItem(CacheKey.RootKey);
                New <UserPublicKeyUpdateStatus>().Clear();
                break;

            case SessionNotificationType.EncryptPendingFiles:
                await _activeFileAction.ClearExceptionState();

                await _activeFileAction.PurgeActiveFiles(progress);

                if (_knownIdentities.DefaultEncryptionIdentity != LogOnIdentity.Empty)
                {
                    await EncryptWatchedFoldersIfSupportedAsync(_knownIdentities.DefaultEncryptionIdentity, notification.Capabilities, progress);
                }
                break;

            case SessionNotificationType.UpdateActiveFiles:
                await _fileSystemState.UpdateActiveFiles(notification.FullNames);

                break;

            case SessionNotificationType.ActiveFileChange:
            case SessionNotificationType.SessionStart:
            case SessionNotificationType.WatchedFolderChange:
            case SessionNotificationType.ProcessExit:
            case SessionNotificationType.KnownKeyChange:
            case SessionNotificationType.SessionChange:
            case SessionNotificationType.WorkFolderChange:
                await _activeFileAction.CheckActiveFiles(progress);

                break;

            case SessionNotificationType.LicensePolicyChanged:
            case SessionNotificationType.RefreshLicensePolicy:
                break;

            default:
                throw new InvalidOperationException("Unhandled notification received");
            }
        }
Beispiel #13
0
 public void NotifyLevelStart()
 {
     _progress.NotifyLevelStart();
 }
 public void NotifyLevelStart()
 {
     ThrowIfCancelled();
     _progress.NotifyLevelStart();
 }