/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public AuditItem(AuditLevel level, FileSystemTask context, AuditEvent eventId, string message) { Timestamp = SystemTime.Now(); Level = level; Context = context; EventId = eventId; Message = message; }
public static void SecureAction(IAuditor auditor, FileSystemTask context, Action action, Func <string> errorMessage) { //TODO replace wrapper once SecureFunc is properly implemented Func <bool> func = () => { action(); return(true); }; SecureFunc(auditor, context, () => func, errorMessage); }
/// <summary> /// Checks whether a folder resource at a given path exists or not. /// </summary> /// <param name="virtualFolderPath">A path to the requested folder.</param> /// <returns>True if a matching folder was found.</returns> /// <exception cref="ResourceAccessException">In case of invalid or prohibited /// resource access.</exception> public override bool IsFolderAvailable(string virtualFolderPath) { string actionUri = Uris.IsFolderAvailableUri; actionUri = actionUri.ConstructUri(Uris.PatternFolderPath, virtualFolderPath); Func <string> errorMessage = () => String.Format("Could not check whether folder [{0}] is available.", virtualFolderPath); const FileSystemTask context = FileSystemTask.CheckFolderAvailability; return(SecureGet <Wrapped <bool> >(context, actionUri, errorMessage).Value); }
/// <summary> /// Deletes a given file from the file system. /// </summary> /// <param name="virtualFilePath">The qualified path of the file to be created.</param> /// <exception cref="ArgumentNullException">If <paramref name="virtualFilePath"/> /// is a null reference.</exception> /// <exception cref="ResourceAccessException">In case of invalid or prohibited /// resource access.</exception> /// <exception cref="VirtualResourceNotFoundException">If the /// file does not exist.</exception> public override void DeleteFile(string virtualFilePath) { string actionUri = Uris.DeleteFileUri; actionUri = actionUri.ConstructUri(Uris.PatternFilePath, virtualFilePath); Func <string> errorMessage = () => String.Format("Could not delete file [{0}] from file system.", virtualFilePath); const FileSystemTask context = FileSystemTask.FileDeleteRequest; SecureDelete(context, actionUri, errorMessage); }
/// <summary> /// Reads a block via a streaming channel, which enables a more resource friendly /// data transmission (compared to sending the whole data of the block at once). /// </summary> /// <param name="transferId">Identifies the transfer and resource.</param> /// <param name="blockNumber">The number of the requested block.</param> /// <returns>A data block which contains the data as an in-memory buffer /// (<see cref="BufferedDataBlock.Data"/>).</returns> public StreamedDataBlock ReadBlockStreamed(string transferId, long blockNumber) { string actionUri = Uris.GetDataBlockStreamedUri; actionUri = actionUri.ConstructUri(Uris.PatternTransferId, transferId); actionUri = actionUri.ConstructUri(Uris.PatternBlockNumber, blockNumber.ToString(CultureInfo.InvariantCulture)); Func <string> errorMessage = () => String.Format("Could not read streamed block [{0}] on transfer [{1}].", blockNumber, transferId); const FileSystemTask context = FileSystemTask.DataBlockDownloadRequest; return(SecureFunc(context, () => GetStreamedBlockImpl(actionUri, transferId, blockNumber), errorMessage)); }
/// <summary> /// Audits a successful file system operation for a given resource. /// </summary> public static void AuditResourceOperation <T>(IAuditor auditor, FileSystemTask context, AuditEvent eventId, IVirtualResourceItem <T> resource) where T : VirtualResourceInfo { if (!AuditHelper.IsInfoEnabledFor(auditor, context)) { return; } string msg = String.Format("Successfully performed file system operation '{0}' for resource [{1}].\n\n{2}", context, resource.ResourceInfo.Name, AuditHelper.CreateResourceInfoString(resource)); auditor.Audit(AuditLevel.Info, context, eventId, msg); }
/// <summary> /// Audits a successful file system operation that involves a source and a target resource (move / copy). /// </summary> public static void AuditResourceOperation <T>(IAuditor auditor, FileSystemTask context, AuditEvent eventId, IVirtualResourceItem <T> sourceFolder, IVirtualResourceItem <T> targetFolder) where T : VirtualResourceInfo { if (!AuditHelper.IsInfoEnabledFor(auditor, context)) { return; } string msg = String.Format("Successfully performed file system operation '{0}'.\n\nSource:\n{1}\n\nTarget:\n{2}", context, AuditHelper.CreateResourceInfoString(sourceFolder), AuditHelper.CreateResourceInfoString(targetFolder)); auditor.Audit(AuditLevel.Info, context, eventId, msg); }
/// <summary> /// Requests a download token for a given resource. /// </summary> /// <param name="virtualFilePath">Identifies the resource to be downloaded.</param> /// <param name="includeFileHash">Whether a file hash for the /// requested resource should be calculated and assigned to the /// <see cref="DownloadToken.Md5FileHash"/> property of the returned /// <see cref="DownloadToken"/>.</param> /// <returns>A token that represents a granted resource download, optionally /// limited to a given time frame (<see cref="TransferToken.ExpirationTime"/>).</returns> /// <exception cref="VirtualResourceNotFoundException">If the submitted <paramref name="virtualFilePath"/> /// does not match an existing resource.</exception> /// <exception cref="ResourceAccessException">If the request was not authorized.</exception> /// <exception cref="ResourceLockedException">If a lock to access the /// resource was not granted.</exception> public DownloadToken RequestDownloadToken(string virtualFilePath, bool includeFileHash) { string actionUri = Uris.GetDownloadTokenUri; actionUri = actionUri.ConstructUri(Uris.PatternFilePath, virtualFilePath); actionUri = actionUri.ConstructUri(Uris.PatternIncludeFileHash, Convert.ToString(includeFileHash).ToLowerInvariant()); Func <string> errorMessage = () => String.Format("Download token request for file [{0}] failed.", virtualFilePath); const FileSystemTask context = FileSystemTask.DownloadTokenRequest; return(SecureGet <DownloadToken>(context, actionUri, errorMessage)); }
/// <summary> /// Audits a denied request for a folder's contents. /// </summary> public static void AuditDeniedFolderContentsRequest(IAuditor auditor, FileSystemTask context, IVirtualFolderItem parentFolder) { if (!AuditHelper.IsWarnEnabledFor(auditor, context)) { return; } string msg = "Denied access to contents of folder [{0}]. Folder details:\n\n{1}"; msg = String.Format(msg, parentFolder.ResourceInfo.Name, AuditHelper.CreateResourceInfoString(parentFolder)); auditor.Audit(AuditLevel.Warning, context, AuditEvent.ListFolderContentsDenied, msg); }
/// <summary> /// Audits a request for a folder's files and sub folders. /// </summary> public static void AuditFolderContentsRequest(this IAuditor auditor, FileSystemTask context, IVirtualFolderItem parentFolder) { if (!auditor.IsInfoEnabledFor(context)) { return; } string msg = "Delivered contents of folder [{0}]. Folder details:\n\n{1}"; msg = String.Format(msg, parentFolder.ResourceInfo.Name, parentFolder.CreateResourceInfoString()); auditor.Audit(AuditLevel.Info, context, AuditEvent.FolderContentsRequested, msg); }
/// <summary> /// Audits a successful file system operation that occurred in the context of a given transfer. /// </summary> public static void AuditTransferOperation <T>(this IAuditor auditor, FileSystemTask context, AuditEvent eventId, string transferId, IVirtualResourceItem <T> resource) where T : VirtualResourceInfo { if (!auditor.IsInfoEnabledFor(context)) { return; } string msg = "Successfully performed file system operation [{0}] during transfer [{1}] for resource [{2}].\n\n{3}"; msg = String.Format(msg, context, transferId, resource.ResourceInfo.Name, resource.CreateResourceInfoString()); auditor.Audit(AuditLevel.Info, context, eventId, msg); }
/// <summary> /// Audits a check for file or folder availability along with the returned result. /// </summary> public static void AuditResourceAvailabilityCheck(IAuditor auditor, FileSystemTask context, string resourcePath, bool isAvailable) { if (!AuditHelper.IsInfoEnabledFor(auditor, context)) { return; } string msg = "Checked availability of resource (file or folder) [{0}]. Available: {1}."; msg = String.Format(msg, resourcePath, isAvailable); auditor.Audit(AuditLevel.Info, context, AuditEvent.FileInfoRequested, msg); }
/// <summary> /// Copies a given file to a new destination. /// </summary> /// <param name="virtualFilePath">A qualified name (corresponding to /// <see cref="VirtualResourceInfo.FullName"/> that identifies the resource /// in the file system.</param> /// <param name="destinationPath">The new path of the resource. Can be another name /// for the resource itself.</param> /// <returns>A <see cref="VirtualFileInfo"/> object that represents the new /// file in the file system.</returns> /// <exception cref="ArgumentNullException">If any of the parameters is a /// null reference.</exception> /// <exception cref="ResourceAccessException">In case of invalid or prohibited /// resource access, or if the operation is not possible (e.g. a resource being /// moved/copied to itself).</exception> /// <exception cref="VirtualResourceNotFoundException">If the resource that /// should be moved does not exist in the file system.</exception> /// <exception cref="ResourceOverwriteException">If a resource that matches the /// submitted <paramref name="destinationPath"/> already exists.</exception> public override VirtualFileInfo CopyFile(string virtualFilePath, string destinationPath) { string actionUri = Uris.CopyFileUri; actionUri = actionUri.ConstructUri(Uris.PatternFilePath, virtualFilePath); actionUri = actionUri.ConstructUri(Uris.PatternDestinationPath, destinationPath); Func <string> errorMessage = () => String.Format("Could not copy file [{0}] to destination [{1}].", virtualFilePath, destinationPath); const FileSystemTask context = FileSystemTask.FileCopyRequest; return(SecurePost <VirtualFileInfo>(context, actionUri, HttpContent.CreateEmpty(), errorMessage)); }
/// <summary> /// Moves a given folder and all its contents to a new destination. /// </summary> /// <param name="virtualFolderPath">A qualified name (corresponding to /// <see cref="VirtualResourceInfo.FullName"/> that identifies the resource /// in the file system.</param> /// <param name="destinationPath">The new path of the resource. Can be another name /// for the resource itself.</param> /// <returns>A <see cref="VirtualFolderInfo"/> object that represents the new /// directory in the file system.</returns> /// <exception cref="ArgumentNullException">If any of the parameters is a /// null reference.</exception> /// <exception cref="ResourceAccessException">In case of invalid or prohibited /// resource access, or if the operation is not possible (e.g. a resource being /// moved/copied to itself).</exception> /// <exception cref="VirtualResourceNotFoundException">If the resource that /// should be moved does not exist in the file system.</exception> /// <exception cref="ResourceOverwriteException">If a resource that matches the /// submitted <paramref name="destinationPath"/> already exists.</exception> public override VirtualFolderInfo MoveFolder(string virtualFolderPath, string destinationPath) { string actionUri = Uris.MoveFolderUri; actionUri = actionUri.ConstructUri(Uris.PatternFolderPath, virtualFolderPath); actionUri = actionUri.ConstructUri(Uris.PatternDestinationPath, destinationPath); Func <string> errorMessage = () => String.Format("Could not move folder [{0}] to destination [{1}].", virtualFolderPath, destinationPath); const FileSystemTask context = FileSystemTask.FolderMoveRequest; return(SecurePost <VirtualFolderInfo>(context, actionUri, HttpContent.CreateEmpty(), errorMessage)); }
/// <summary> /// Creates a new folder in the file system. /// </summary> /// <param name="virtualFolderPath">The qualified path of the folder to be created.</param> /// <returns>A <see cref="VirtualFileInfo"/> instance which represents /// the created folder.</returns> /// <exception cref="ArgumentNullException">If <paramref name="virtualFolderPath"/> /// is a null reference.</exception> /// <exception cref="ResourceAccessException">In case of invalid or prohibited /// resource access.</exception> /// <exception cref="VirtualResourceNotFoundException">If the designated parent /// folder does not exist.</exception> /// <exception cref="ResourceOverwriteException">If the folder already exists on the file /// system.</exception> public override VirtualFolderInfo CreateFolder(string virtualFolderPath) { string actionUri = Uris.CreateFolderUri; actionUri = actionUri.ConstructUri(Uris.PatternFolderPath, virtualFolderPath); Func <string> errorMessage = () => String.Format("Could not create folder [{0}] on file system.", virtualFolderPath); const FileSystemTask context = FileSystemTask.FolderCreateRequest; HttpContent content = HttpContent.CreateEmpty(); return(SecurePost <VirtualFolderInfo>(context, actionUri, content, errorMessage)); }
/// <summary> /// Creates a qualified name that can be used as an identifier /// for a given folder of the file system. /// </summary> /// <param name="parentFolder">The qualified name of the parent /// folder.</param> /// <param name="folderName">The name of the child folder.</param> /// <returns>An qualified path name for the submitted /// <paramref name="folderName"/>.</returns> public override string CreateFolderPath(string parentFolder, string folderName) { string actionUri = Uris.CreateFolderPathUri; actionUri = actionUri.ConstructUri(Uris.PatternParentFolderPath, parentFolder); actionUri = actionUri.ConstructUri(Uris.PatternFolderName, folderName); Func <string> errorMessage = () => String.Format("Could not get a folder path for parent folder [{0}] and folder name [{1}].", parentFolder, folderName); const FileSystemTask context = FileSystemTask.CreateFolderPathRequest; return(SecureGet <Wrapped <string> >(context, actionUri, errorMessage).Value); }
/// <summary> /// Audits that a folder was created on the file system. /// </summary> public static void AuditFolderCreation(IAuditor auditor, IVirtualFolderItem folder) { const FileSystemTask context = FileSystemTask.FolderCreateRequest; if (!AuditHelper.IsInfoEnabledFor(auditor, context)) { return; } string msg = "Created folder [{0}] on the file system.\n\n{1}"; msg = String.Format(msg, folder.ResourceInfo.Name, AuditHelper.CreateResourceInfoString(folder)); auditor.Audit(AuditLevel.Info, context, AuditEvent.FolderCreated, msg); }
/// <summary> /// Called to indicate a folder was created /// </summary> /// <param name="relativePath">The relative path to the newly created folder</param> /// <param name="sparseFoldersUpdated"> /// true when the folder is successfully added to the sparse list because it is in the projection but currently excluded. /// false when the folder was not excluded or there was a failure adding to the sparse list. /// </param> public void OnFolderCreated(string relativePath, out bool sparseFoldersUpdated) { sparseFoldersUpdated = false; GitIndexProjection.PathSparseState pathProjectionState = this.GitIndexProjection.GetFolderPathSparseState(relativePath); if (pathProjectionState == GitIndexProjection.PathSparseState.Excluded) { if (this.GitIndexProjection.TryAddSparseFolder(relativePath)) { sparseFoldersUpdated = true; return; } } this.AddToNewlyCreatedList(relativePath, isFolder: true); this.backgroundFileSystemTaskRunner.Enqueue(FileSystemTask.OnFolderCreated(relativePath)); }
private UploadToken GetTransferForResourceImpl(string virtualFilePath) { const FileSystemTask context = FileSystemTask.UploadTransferByResourceQuery; const AuditEvent eventId = AuditEvent.ResourceUploadQuery; var token = TransferStore.GetRunningTransfersForResource(virtualFilePath) .Select(t => t.Token) .SingleOrDefault(); string msg = "Queried upload transfer for resource [{0}]. Token found: [{1}]."; msg = String.Format(msg, virtualFilePath, token != null); Auditor.Audit(AuditLevel.Info, context, eventId, msg); return(token); }
private void InvalidateState(bool invalidateProjection, bool invalidateModifiedPaths) { if (invalidateProjection) { this.GitIndexProjection.InvalidateProjection(); } if (invalidateModifiedPaths) { this.GitIndexProjection.InvalidateModifiedFiles(); this.backgroundFileSystemTaskRunner.Enqueue(FileSystemTask.OnIndexWriteRequiringModifiedPathsValidation()); } this.InvalidateGitStatusCache(); this.newlyCreatedFileAndFolderPaths.Clear(); }
/// <summary> /// Audits a successful file system operation for a given resource. /// </summary> public static void AuditResourceOperation <T>(this IAuditor auditor, FileSystemTask context, AuditEvent eventId, IVirtualResourceItem <T> resource, string message) where T : VirtualResourceInfo { if (!auditor.IsInfoEnabledFor(context)) { return; } string msg = String.Format("Successfully performed file system operation '{0}' for resource [{1}].\n\n{2}", context, resource.ResourceInfo.Name, resource.CreateResourceInfoString()); if (!String.IsNullOrEmpty(message)) { msg = String.Format("{0}\n{1}", msg, message); } auditor.Audit(AuditLevel.Info, context, eventId, msg); }
/// <summary> /// Audits a file system operation that was blocked as a warning. /// </summary> public static void AuditDeniedOperation <T>(IAuditor auditor, FileSystemTask context, AuditEvent eventId, IVirtualResourceItem <T> resource, string message) where T : VirtualResourceInfo { if (!AuditHelper.IsWarnEnabledFor(auditor, context)) { return; } string msg = String.Format("Blocked operation '{0}' due to event '{1}'.", context, eventId); if (!String.IsNullOrEmpty(message)) { msg = String.Format("{0}\n{1}", msg, message); } msg = String.Format("{0}\n\n{1}", msg, AuditHelper.CreateResourceInfoString(resource)); auditor.Audit(AuditLevel.Warning, context, eventId, msg); }
/// <summary> /// Internally resolves a given file resource by invoking <see cref="ResolveFileResourcePath"/>, /// and performs basic exception handling, auditing, access and availability checks.<br/> /// This method may be overridden in case additional work needs to be done in order to resolve /// the resource based on the submitted path. /// </summary> /// <param name="virtualFilePath">The submitted file path that needs to be resolved.</param> /// <param name="mustExist">Whether the file must exist on the file system. If this parameter is true /// and the received <typeparamref name="TFile"/>'s <see cref="IVirtualFileItem.Exists"/> is /// false, and <see cref="VirtualResourceNotFoundException"/> is being thrown.</param> /// <param name="context">The file system operation that is being performed during the invocation of /// this method. Used for internal auditing.</param> /// <returns>A wrapper item that includes the a <see cref="VirtualFileInfo"/> that corresponds /// to the submitted <paramref name="virtualFilePath"/>.</returns> /// <exception cref="ArgumentNullException">If <paramref name="virtualFilePath"/> /// is a null reference.</exception> /// <exception cref="VirtualResourceNotFoundException">If <paramref name="mustExist"/> is true, and /// the folder's <see cref="IVirtualFileItem.Exists"/> property is false.</exception> protected IVirtualFileItem ResolveFileResourcePathInternal(string virtualFilePath, bool mustExist, FileSystemTask context) { //TODO allow null (also for folders), but write test first Ensure.ArgumentNotNull(virtualFilePath, "virtualFilePath"); IVirtualFileItem fileItem; try { fileItem = ResolveFileResourcePath(virtualFilePath, context); } catch (InvalidResourcePathException e) { AuditHelper.AuditException(Auditor,e, context, AuditEvent.InvalidFilePathFormat); throw; } catch (VfsException e) { //audit exception AuditHelper.AuditException(Auditor,e, context, AuditEvent.FileResolveFailed); throw; } catch (Exception e) { //wrap exception and audit string msg = String.Format("Unexpected exception while resolving file path [{0}]", virtualFilePath); var rae = new ResourceAccessException(msg, e); AuditHelper.AuditException(Auditor,rae, context, AuditEvent.FileResolveFailed); throw rae; } if (mustExist && !fileItem.Exists) { //audit and throw exception AuditHelper.AuditRequestedFileNotFound(Auditor,fileItem, context); string msg = String.Format("File [{0}] not found on file system.", fileItem.ResourceInfo.FullName); throw new VirtualResourceNotFoundException(msg) { Resource = fileItem.ResourceInfo, IsAudited = true }; } return fileItem; }
/// <summary> /// Provides exception handling and auditing for a given function. /// </summary> /// <param name="task">The context, used for auditing exceptions that may occur.</param> /// <param name="action">The action to be invoked.</param> /// <param name="errorMessage">Returns an error message in case of an unhandled exception /// that is not derived from <see cref="VfsException"/>.</param> /// <param name="auditor">The auditor that receives the exceptions.</param> /// <returns>The result of the submitted <paramref name="action"/> function.</returns> public static void SecureAction(FileSystemTask task, Action action, Func <string> errorMessage, IAuditor auditor) { try { action(); } catch (VfsException e) { //just audit and rethrow VFS exceptions auditor.AuditException(e, task); throw; } catch (Exception e) { //wrap unhandled exception into VFS exception var exception = new ResourceAccessException(errorMessage(), e); auditor.AuditException(exception, task); throw exception; } }
/// <summary> /// Provides exception handling and auditing for a given function. /// </summary> /// <param name="task">The context, used for auditing exceptions that may occur.</param> /// <param name="func">The function to be invoked.</param> /// <param name="errorMessage">Returns an error message in case of an unhandled exception /// that is not derived from <see cref="VfsException"/>.</param> /// <param name="auditor">The auditor that receives the exceptions.</param> /// <returns>The result of the submitted <paramref name="func"/> function.</returns> public static T SecureFunc <T>(FileSystemTask task, Func <T> func, Func <string> errorMessage, IAuditor auditor) { try { return(func()); } catch (VfsException e) { //just audit and rethrow VFS exceptions AuditHelper.AuditException(auditor, e, task); throw; } catch (Exception e) { //wrap unhandled exception into VFS exception var exception = new ResourceAccessException(errorMessage(), e); AuditHelper.AuditException(auditor, exception, task); throw exception; } }
private Stream DownloadFileImpl(string transferId) { const FileSystemTask context = FileSystemTask.StreamedFileDownloadRequest; //get the cached transfer TTransfer transfer = GetCachedTransfer(transferId, true, context); if (transfer.Token.TotalBlockCount == 0) { //if we don't have any blocks, return a null stream Auditor.AuditTransferOperation(context, AuditEvent.FileDataDownloaded, transfer.TransferId, transfer.FileItem); return(Stream.Null); } //we don't expose the underlying stream directly, but rather use blocks again, //which disconnects the exposed stream from the underlying resource and allows for simple //aborting long resourceLength = transfer.FileItem.ResourceInfo.Length; // ReSharper disable UseObjectOrCollectionInitializer var stream = new StreamedBlockInputStream(blockNumber => ReadBlockStreamed(transferId, blockNumber), resourceLength); // ReSharper restore UseObjectOrCollectionInitializer //assign the stream the transfer object in order so it can query the status during reading stream.Transfer = transfer; //reading the last block closes the transfer automatically.. transfer.AutoCloseAfterLastBlockDelivery = true; //...and so does disposing the stream at any time var closingStream = new ClosingActionStream(stream, () => CompleteTransfer(transferId)); Auditor.AuditTransferOperation(context, AuditEvent.FileDataDownloaded, transfer.TransferId, transfer.FileItem); return(closingStream); }
public virtual void OnIndexFileChange() { string lockedGitCommand = this.context.Repository.GVFSLock.GetLockedGitCommand(); GitCommandLineParser gitCommand = new GitCommandLineParser(lockedGitCommand); if (!gitCommand.IsValidGitCommand) { // Something wrote to the index without holding the GVFS lock, so we invalidate the projection this.GitIndexProjection.InvalidateProjection(); this.InvalidateGitStatusCache(); // But this isn't something we expect to see, so log a warning EventMetadata metadata = new EventMetadata { { "Area", EtwArea }, { TracingConstants.MessageKey.WarningMessage, "Index modified without git holding GVFS lock" }, }; this.context.Tracer.RelatedEvent(EventLevel.Warning, $"{nameof(this.OnIndexFileChange)}_NoLock", metadata); } else if (this.GitCommandLeavesProjectionUnchanged(gitCommand)) { if (this.GitCommandRequiresModifiedPathValidationAfterIndexChange(gitCommand)) { this.GitIndexProjection.InvalidateModifiedFiles(); this.backgroundFileSystemTaskRunner.Enqueue(FileSystemTask.OnIndexWriteRequiringModifiedPathsValidation()); } this.InvalidateGitStatusCache(); } else { this.GitIndexProjection.InvalidateProjection(); this.InvalidateGitStatusCache(); } this.newlyCreatedFileAndFolderPaths.Clear(); }
/// <summary> /// Closes a given transfer, and frees resources that were associated with the /// transfer (by invoking the <see cref="TransferHandlerBase{TFile,TToken,TTransfer}.FinalizeTransfer"/> method). /// </summary> /// <returns>The status depending on the result of the hash verification, which is delegated to the /// abstract <see cref="VerifyTransfer"/> method.</returns> protected virtual TransferStatus CompleteTransferInternal(string transferId, string md5FileHash) { const FileSystemTask context = FileSystemTask.UploadTransferCompletion; //get the transfer TTransfer transfer = GetCachedTransfer(transferId, true, context); lock (transfer.ResourceLock) { bool status = VerifyTransfer(transfer, md5FileHash); if (status) { //complete transfer return(CloseTransferInternal(transfer.TransferId, TransferStatus.Completed, null, context, AuditEvent.TransferCompleted)); } //cancel transfer if verification failed return(CloseTransferInternal(transfer.TransferId, TransferStatus.Aborted, AbortReason.VerificationFailure, context, AuditEvent.TransferHashVerificationError)); } }
public FolderItem ResolveFolderResourcePath2(string submittedFolderPath, FileSystemTask context) { //make sure we operate on absolute paths string absolutePath = PathUtil.GetAbsolutePath(submittedFolderPath ?? "", RootDirectory); if (IsRootPath(absolutePath)) { return(GetFileSystemRootImplementation() as FolderItem); } var di = new DirectoryInfo(absolutePath); VirtualFolderInfo folderInfo = di.CreateFolderResourceInfo(); var item = new FolderItem(di, folderInfo); //convert to relative paths if required (also prevents qualified paths in validation exceptions) if (UseRelativePaths) { item.MakePathsRelativeTo(RootDirectory); } ValidateFolderRequestAccess(item, submittedFolderPath, context); return(item); }
/// <summary> /// A method that is invoked on pretty much every folder request in order /// to resolve a submitted folder path into a <see cref="VirtualFolderInfo"/> /// object.<br/> /// The <see cref="VirtualFolderInfo"/> is being returned as part of a /// <see cref="IVirtualFolderItem"/>, which should also provide some additionally /// required meta data which is used for further validation and auditing. /// </summary> /// <param name="submittedFolderPath">The path that was received as a part of a folder-related /// request.</param> /// <param name="context">The currently performed file system operation.</param> /// <returns>A <see cref="IVirtualFolderItem"/> which encapsulates a <see cref="VirtualFolderInfo"/> /// that represents the requested folder on the file system.</returns> /// <exception cref="InvalidResourcePathException">In case the format of the submitted path /// is invalid, meaning it cannot be interpreted as a valid resource identifier.</exception> /// <exception cref="VfsException">Exceptions will be handled by this base class and audited to /// the <see cref="FileSystemProviderBase.Auditor"/>. If auditing was already performed or should /// be suppressed, implementors can set the <see cref="VfsException.IsAudited"/> and /// <see cref="VfsException.SuppressAuditing"/> properties.</exception> /// <exception cref="Exception">Any exceptions that are not derived from /// <see cref="VfsException"/> will be wrapped and audited.</exception> public abstract IVirtualFolderItem ResolveFolderResourcePath(string submittedFolderPath, FileSystemTask context);
public FolderItem ResolveFolderResourcePath2(string submittedFolderPath, FileSystemTask context) { //make sure we operate on absolute paths string absolutePath = PathUtil.GetAbsolutePath(submittedFolderPath ?? "", RootDirectory); if (IsRootPath(absolutePath)) { return GetFileSystemRootImplementation() as FolderItem; } var di = new DirectoryInfo(absolutePath); VirtualFolderInfo folderInfo = di.CreateFolderResourceInfo(); var item = new FolderItem(di, folderInfo); //convert to relative paths if required (also prevents qualified paths in validation exceptions) if (UseRelativePaths) item.MakePathsRelativeTo(RootDirectory); ValidateFolderRequestAccess(item, submittedFolderPath, context); return item; }
/// <summary> /// Validates whether a <see cref="LocalFileSystemProvider"/> was configured /// with access restricted to a given <see cref="LocalFileSystemProvider.RootDirectory"/>, /// and makes sure that the requested <paramref name="file"/> is indeed contained /// within that folder. /// </summary> /// <param name="file">The requested file resource.</param> /// <param name="submittedFilePath">The path that was submitted in the original request.</param> /// <param name="context">The currently performed file system operation.</param> /// <exception cref="ResourceAccessException">If the requested resource is not /// a descendant of a configured <see cref="LocalFileSystemProvider.RootDirectory"/>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="file"/> /// is a null reference.</exception> private void ValidateFileRequestAccess(FileItem file, string submittedFilePath, FileSystemTask context) { if (file == null) throw new ArgumentNullException("file"); //if there isn't a restricted custom root, every file resource can be accessed //(if the path is invalid, this will fail otherwise, depending on the action) if (RootDirectory == null) return; try { //if we have a custom root, make sure the resource is indeed a descendant of the root if (RootDirectory.IsParentOf(file.LocalFile.FullName)) return; } catch (ResourceAccessException e) { //just bubble a resource access exception if (e.Resource == null) e.Resource = file.ResourceInfo; throw; } catch (Exception e) { //exceptions can happen in case of invalid file paths //log detailed info string error = "Resource request for file [{0}] caused exception when validating against root directory [{1}]."; error = String.Format(error, submittedFilePath, RootDirectory.FullName); AuditHelper.AuditException(Auditor, e, AuditLevel.Warning, context, AuditEvent.InvalidFilePathFormat, error); //do not expose too much path information (e.g. absolute paths if disabled) error = String.Format("Invalid file path: [{0}].", submittedFilePath); throw new ResourceAccessException(error, e) { Resource = file.ResourceInfo, IsAudited = true }; } //if none of the above is true, the request is invalid //log detailed info string msg = "Resource request for file [{0}] was blocked. The resource is outside the root directory [{1}]."; msg = String.Format(msg, file.ResourceInfo.FullName, RootDirectory.FullName); Auditor.Audit(AuditLevel.Warning, context, AuditEvent.InvalidResourceLocationRequested, msg); //do not expose too much path information (e.g. absolute paths if disabled) msg = String.Format("Invalid file path: [{0}].", submittedFilePath); throw new ResourceAccessException(msg) { Resource = file.ResourceInfo, IsAudited = true }; }
/// <summary> /// Audits a given incident. /// </summary> /// <param name="level">Indicates the severity of an audited incident.</param> /// <param name="context">Defines the context of the audited operation on the file system.</param> /// <param name="eventId">An identifier that indicates the incident.</param> /// <param name="message">An optional message that provides background information.</param> public void Audit(AuditLevel level, FileSystemTask context, AuditEvent eventId, string message) { }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public AuditItem(AuditLevel level, FileSystemTask context, AuditEvent eventId) : this(level, context, eventId, String.Empty) { }
Vfs.LocalFileSystem.FolderItem ResolveFolderResourcePathInternal2(string virtualFolderPath, bool mustExist, FileSystemTask context) { return(ResolveFolderResourcePathInternal(virtualFolderPath, mustExist, context) as Vfs.LocalFileSystem.FolderItem); }
/// <summary> /// Whether auditing is being performed for incidents of /// a given <see cref="AuditLevel"/> and context. /// </summary> /// <param name="level">The severity of the audited incident.</param> /// <param name="context">The currently performed file system operation /// that delivers the context of the audited incident.</param> /// <returns>True if messages for the level and area are being actively /// audited. If this method returns false, <see cref="IAuditor.Audit"/> is /// not supposed to be invoked with an <see cref="AuditItem"/> /// that matches this level and area.</returns> public bool IsAuditEnabled(AuditLevel level, FileSystemTask context) { return true; }
public FileItem ResolveFileResourcePath2(string submittedFilePath, FileSystemTask context) { if (String.IsNullOrEmpty(submittedFilePath)) { throw new InvalidResourcePathException("An empty or null string is not a valid file path"); } //make sure we operate on absolute paths var absolutePath = PathUtil.GetAbsolutePath(submittedFilePath, RootDirectory); if (IsRootPath(absolutePath)) { throw new InvalidResourcePathException("Invalid path submitted: " + submittedFilePath); } var localFile = new FileInfo(absolutePath); VirtualFileInfo virtualFile = localFile.CreateFileResourceInfo(); var item = new FileItem(localFile, virtualFile); //convert to relative paths if required (also prevents qualified paths in validation exceptions) if (UseRelativePaths) item.MakePathsRelativeTo(RootDirectory); ValidateFileRequestAccess(item, submittedFilePath, context); return item; }
/// <summary> /// Audits a given incident. /// </summary> /// <param name="level">Indicates the severity of an audited incident.</param> /// <param name="context">Defines the context of the audited operation on the file system.</param> /// <param name="eventId">An identifier that indicates the incident.</param> /// <param name="message">An optional message that provides background information.</param> public void Audit(AuditLevel level, FileSystemTask context, AuditEvent eventId, string message) { Audit(new AuditItem(level, context, eventId, message)); }
Vfs.Zip.ZipFolderItem ResolveFolderResourcePathInternal2(string virtualFolderPath, bool mustExist, FileSystemTask context) { return ResolveFolderResourcePathInternal(virtualFolderPath, mustExist, context) as Vfs.Zip.ZipFolderItem; }
public ZipFolderItem ResolveFolderResourcePath2(string submittedFolderPath, FileSystemTask context) { if (String.IsNullOrEmpty(submittedFolderPath) || submittedFolderPath == ZipNodeRepository.RootFolderPath) { return GetFileSystemRootImplementation() as ZipFolderItem; } return NodeRepository.GetFolderItem(submittedFolderPath); }
/// <summary> /// A method that is invoked on pretty much every folder request in order /// to resolve a submitted folder path into a <see cref="VirtualFolderInfo"/> /// object.<br/> /// The <see cref="VirtualFolderInfo"/> is being returned as part of a /// <see cref="IVirtualFolderItem"/>, which should also provide some additionally /// required meta data which is used for further validation and auditing. /// </summary> /// <param name="submittedFolderPath">The path that was received as a part of a folder-related /// request.</param> /// <param name="context">The currently performed file system operation.</param> /// <returns>A <see cref="IVirtualFolderItem"/> which encapsulates a <see cref="VirtualFolderInfo"/> /// that represents the requested folder on the file system.</returns> /// <exception cref="InvalidResourcePathException">In case the format of the submitted path /// is invalid, meaning it cannot be interpreted as a valid resource identifier.</exception> /// <exception cref="VfsException">Exceptions will be handled by this base class and audited to /// the <see cref="FileSystemProviderBase.Auditor"/>. If auditing was already performed or should /// be suppressed, implementors can set the <see cref="VfsException.IsAudited"/> and /// <see cref="VfsException.SuppressAuditing"/> properties.</exception> /// <exception cref="Exception">Any exceptions that are not derived from /// <see cref="VfsException"/> will be wrapped and audited.</exception> public override IVirtualFolderItem ResolveFolderResourcePath(string submittedFolderPath, FileSystemTask context) { return ResolveFolderResourcePath2(submittedFolderPath, context); }
public ZipFileItem ResolveFileResourcePath2(string submittedFilePath, FileSystemTask context) { return NodeRepository.GetFileItem(submittedFilePath); }
/// <summary> /// A method that is invoked on pretty much every folder request in order /// to resolve a submitted folder path into a <see cref="VirtualFolderInfo"/> /// object.<br/> /// The <see cref="VirtualFolderInfo"/> is being returned as part of a /// <see cref="IVirtualFolderItem"/>, which should also provide some additionally /// required meta data which is used for further validation and auditing. /// </summary> /// <param name="submittedFolderPath">The path that was received as a part of a folder-related /// request.</param> /// <param name="context">The currently performed file system operation.</param> /// <returns>A <see cref="IVirtualFolderItem"/> which encapsulates a <see cref="VirtualFolderInfo"/> /// that represents the requested folder on the file system.</returns> /// <exception cref="InvalidResourcePathException">In case the format of the submitted path /// is invalid, meaning it cannot be interpreted as a valid resource identifier.</exception> /// <exception cref="VfsException">Exceptions will be handled by this base class and audited to /// the <see cref="FileSystemProviderBase.Auditor"/>. If auditing was already performed or should /// be suppressed, implementors can set the <see cref="VfsException.IsAudited"/> and /// <see cref="VfsException.SuppressAuditing"/> properties.</exception> /// <exception cref="Exception">Any exceptions that are not derived from /// <see cref="VfsException"/> will be wrapped and audited.</exception> public override IVirtualFolderItem ResolveFolderResourcePath(string submittedFolderPath, FileSystemTask context) { return(ResolveFolderResourcePath2(submittedFolderPath, context)); }
/// <summary> /// Internally resolves a given folder resource by invoking <see cref="ResolveFolderResourcePath"/>, /// and performs basic exception handling, auditing, access and availability checks.<br/> /// This method may be overridden in case additional work needs to be done in order to resolve /// the resource based on the submitted path. /// </summary> /// <param name="virtualFolderPath">The submitted folder path that needs to be resolved.</param> /// <param name="mustExist">Whether the folder must exist on the file system. If this parameter is true /// and the received <typeparamref name="TFolder"/>'s <see cref="IVirtualFolderItem.Exists"/> is /// false, and <see cref="VirtualResourceNotFoundException"/> is being thrown.</param> /// <param name="context">The file system operation that is being performed during the invocation of /// this method. Used for internal auditing.</param> /// <returns>A wrapper item that includes the a <see cref="VirtualFolderInfo"/> that corresponds /// to the submitted <paramref name="virtualFolderPath"/>.</returns> /// <exception cref="ArgumentNullException">If <paramref name="virtualFolderPath"/> /// is a null reference.</exception> /// <exception cref="VirtualResourceNotFoundException">If <paramref name="mustExist"/> is true, and /// the folder's <see cref="IVirtualFolderItem.Exists"/> property is false.</exception> protected virtual IVirtualFolderItem ResolveFolderResourcePathInternal(string virtualFolderPath, bool mustExist, FileSystemTask context) { IVirtualFolderItem folderItem; try { folderItem = ResolveFolderResourcePath(virtualFolderPath, context); } catch(InvalidResourcePathException e) { AuditHelper.AuditException(Auditor,e, context, AuditEvent.InvalidFolderPathFormat); throw; } catch (VfsException e) { //audit exception AuditHelper.AuditException(Auditor,e, context, AuditEvent.FolderResolveFailed); throw; } catch (Exception e) { //wrap exception and audit string msg = String.Format("Unexpected exception while resolving folder path [{0}]", virtualFolderPath); var rae = new ResourceAccessException(msg, e); AuditHelper.AuditException(Auditor,rae, context, AuditEvent.FolderResolveFailed); throw rae; } if (mustExist && !folderItem.Exists) { //audit and throw exception AuditHelper.AuditRequestedFolderNotFound(Auditor,folderItem, context); string msg = String.Format("Folder [{0}] not found on file system.", folderItem.ResourceInfo.FullName); throw new VirtualResourceNotFoundException(msg) { Resource = folderItem.ResourceInfo, IsAudited = true}; } return folderItem; }
/// <summary> /// Validates whether a <see cref="LocalFileSystemProvider"/> was configured /// with access restricted to a given <see cref="LocalFileSystemProvider.RootDirectory"/>, /// and makes sure that the requested <paramref name="file"/> is indeed contained /// within that folder. /// </summary> /// <param name="file">The requested file resource.</param> /// <param name="submittedFilePath">The path that was submitted in the original request.</param> /// <param name="context">The currently performed file system operation.</param> /// <exception cref="ResourceAccessException">If the requested resource is not /// a descendant of a configured <see cref="LocalFileSystemProvider.RootDirectory"/>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="file"/> /// is a null reference.</exception> private void ValidateFileRequestAccess(FileItem file, string submittedFilePath, FileSystemTask context) { if (file == null) { throw new ArgumentNullException("file"); } //if there isn't a restricted custom root, every file resource can be accessed //(if the path is invalid, this will fail otherwise, depending on the action) if (RootDirectory == null) { return; } try { //if we have a custom root, make sure the resource is indeed a descendant of the root if (RootDirectory.IsParentOf(file.LocalFile.FullName)) { return; } } catch (ResourceAccessException e) { //just bubble a resource access exception if (e.Resource == null) { e.Resource = file.ResourceInfo; } throw; } catch (Exception e) { //exceptions can happen in case of invalid file paths //log detailed info string error = "Resource request for file [{0}] caused exception when validating against root directory [{1}]."; error = String.Format(error, submittedFilePath, RootDirectory.FullName); AuditHelper.AuditException(Auditor, e, AuditLevel.Warning, context, AuditEvent.InvalidFilePathFormat, error); //do not expose too much path information (e.g. absolute paths if disabled) error = String.Format("Invalid file path: [{0}].", submittedFilePath); throw new ResourceAccessException(error, e) { Resource = file.ResourceInfo, IsAudited = true }; } //if none of the above is true, the request is invalid //log detailed info string msg = "Resource request for file [{0}] was blocked. The resource is outside the root directory [{1}]."; msg = String.Format(msg, file.ResourceInfo.FullName, RootDirectory.FullName); Auditor.Audit(AuditLevel.Warning, context, AuditEvent.InvalidResourceLocationRequested, msg); //do not expose too much path information (e.g. absolute paths if disabled) msg = String.Format("Invalid file path: [{0}].", submittedFilePath); throw new ResourceAccessException(msg) { Resource = file.ResourceInfo, IsAudited = true }; }
/// <summary> /// Tries to acquire a lock for a given folder and its parent folders, /// and executes the submitted <paramref name="action"/> if the lock /// was granted. Otherwise audits a warning. /// </summary> /// <param name="folder">The folder to be locked.</param> /// <param name="context">The currently performed file system operation.</param> /// <param name="lockType">Whether a read or a write lock is required for the /// <paramref name="folder"/>.</param> /// <param name="action">An action that is being executed if the locking /// succeeded.</param> /// <returns>True if locking succeeded and the <paramref name="action"/> was invoked. False /// if the lock was not granted.</returns> protected virtual bool LockResourceAndExecute(IVirtualFolderItem folder, FileSystemTask context, ResourceLockType lockType, Action action) { using (var guard = RequestChainedLockGuard(folder, lockType)) { if (!guard.IsLockEnabled) { AuditEvent ae = lockType == ResourceLockType.Read ? AuditEvent.FolderReadLockDenied : AuditEvent.FolderWriteLockDenied; AuditHelper.AuditDeniedOperation(Auditor,context, ae, folder); return false; } action(); return true; } }
/// <summary> /// A method that is invoked on pretty much every file request in order /// to resolve a submitted file path into a <see cref="VirtualFileInfo"/> /// object.<br/> /// The <see cref="VirtualFileInfo"/> is being returned as part of a /// <see cref="IVirtualFileItem"/>, which should also provide some additionally /// required meta data which is used for further validation and auditing. /// </summary> /// <param name="submittedFilePath">The path that was received as a part of a file-related /// request.</param> /// <param name="context">The currently performed file system operation.</param> /// <returns>A <see cref="IVirtualFileItem"/> which encapsulates a <see cref="VirtualFileInfo"/> /// that represents the requested file on the file system.</returns> /// <exception cref="InvalidResourcePathException">In case the format of the submitted path /// is invalid, meaning it cannot be interpreted as a valid resource identifier.</exception> /// <exception cref="VfsException">Exceptions will be handled by this base class and audited to /// the <see cref="FileSystemProviderBase.Auditor"/>. If auditing was already performed or should /// be suppressed, implementors can set the <see cref="VfsException.IsAudited"/> and /// <see cref="VfsException.SuppressAuditing"/> properties.</exception> /// <exception cref="Exception">Any exceptions that are not derived from /// <see cref="VfsException"/> will be wrapped and audited.</exception> public abstract IVirtualFileItem ResolveFileResourcePath(string submittedFilePath, FileSystemTask context);
//add Vfs.LocalFileSystem.FileItem ResolveFileResourcePathInternal2(string virtualFilePath, bool mustExist, FileSystemTask context) { return ResolveFileResourcePathInternal(virtualFilePath, mustExist, context) as Vfs.LocalFileSystem.FileItem; }