From d5b6a545ed1e9f01c295280495b806981d9877d3 Mon Sep 17 00:00:00 2001 From: pete scott Date: Wed, 13 Aug 2014 15:28:49 -0400 Subject: [PATCH] Windows: Obtain File Attribs for DFS Link target The AFSRetrieveFileAttributes() function is used to acquire the attributes for an AFS symlink. The result is either returned directly to the application or used internally to determine the attributes to be exposed by reparse points. If the evaluated symlink crosses a DFS Link the redirector cannot return the request to IO Manager to evaluate the target. Instead the redirector must handle the request internally and attempt to read the attributes of the target object. Change-Id: If14df8dc41e13fd59b524fdb575c46abab1dfc2f Reviewed-on: http://gerrit.openafs.org/11399 Reviewed-by: Peter Scott Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp | 9 +- src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp | 113 +++++++++++++++++- .../afsrdr/kernel/lib/AFSNameSupport.cpp | 51 +++++--- .../afsrdr/kernel/lib/Include/AFSCommon.h | 12 +- 4 files changed, 159 insertions(+), 26 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp b/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp index 71d18fb70..9ce2635e0 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp @@ -464,7 +464,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, &NewVolumeReferenceReason, &pNewParentDirectoryCB, &pDirectoryCB, - &uniComponentName); + &uniComponentName, + NULL); if ( pNewVolumeCB != NULL) { @@ -697,7 +698,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, &NewVolumeReferenceReason, &pNewParentDirectoryCB, &pDirectoryCB, - &uniComponentName); + &uniComponentName, + NULL); if ( ntStatus == STATUS_SUCCESS || ntStatus == STATUS_OBJECT_NAME_NOT_FOUND || @@ -815,7 +817,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, &NewVolumeReferenceReason, &pNewParentDirectoryCB, &pDirectoryCB, - &uniComponentName); + &uniComponentName, + NULL); } } else diff --git a/src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp b/src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp index abf4bfd59..ffb96c4fe 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp @@ -5683,11 +5683,16 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB, UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName; ULONG ulNameDifference = 0; LONG lCount; + UNICODE_STRING uniDFSTargetName; __Enter { - // + uniDFSTargetName.Length = 0; + uniDFSTargetName.MaximumLength = 0; + uniDFSTargetName.Buffer = NULL; + + // // Retrieve a target name for the entry // @@ -5964,7 +5969,8 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB, &NewVolumeReferenceReason, &pNewParentDirEntry, &pDirectoryEntry, - NULL); + NULL, + &uniDFSTargetName); if ( pNewVolumeCB != NULL) { @@ -6014,10 +6020,21 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB, pNewParentDirEntry = NULL; - if( !NT_SUCCESS( ntStatus) || - ntStatus == STATUS_REPARSE) + if( !NT_SUCCESS( ntStatus)) + { + try_return( ntStatus); + } + + // + // If the status is STATUS_REPARSE then attempt to retrieve the attributes from the target name returned + // + + if( ntStatus == STATUS_REPARSE) { + ntStatus = AFSRetrieveTargetFileInfo( &uniDFSTargetName, + FileInfo); + try_return( ntStatus); } @@ -6144,6 +6161,13 @@ try_exit: AFSExFreePoolWithTag( pwchBuffer, 0); } + + if ( uniDFSTargetName.Buffer != NULL) + { + + AFSExFreePoolWithTag( uniDFSTargetName.Buffer, + AFS_REPARSE_NAME_TAG); + } } return ntStatus; @@ -6808,7 +6832,8 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB, &VolumeReferenceReason, &pNewParentDirEntry, &pDirectoryEntry, - NULL); + NULL, + NULL); if ( pNewVolumeCB != NULL) { @@ -8402,7 +8427,8 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo, &NewVolumeReferenceReason, &pNewParentDirEntry, &pDirectoryEntry, - NULL); + NULL, + NULL); if ( pNewVolumeCB != NULL) { @@ -9901,3 +9927,78 @@ AFSIgnoreReparsePointToFile( void) return bIgnoreReparsePoint; } + +NTSTATUS +AFSRetrieveTargetFileInfo( IN PUNICODE_STRING TargetName, + OUT AFSFileInfoCB *FileInfo) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + OBJECT_ATTRIBUTES stObjectAttribs; + HANDLE hFile = NULL; + IO_STATUS_BLOCK stIoStatus; + FILE_NETWORK_OPEN_INFORMATION stFileInfo; + + __Enter + { + + InitializeObjectAttributes( &stObjectAttribs, + TargetName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + ntStatus = ZwCreateFile( &hFile, + FILE_READ_ATTRIBUTES, + &stObjectAttribs, + &stIoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if( !NT_SUCCESS( ntStatus)) + { + + try_return( ntStatus); + } + + ntStatus = ZwQueryInformationFile( hFile, + &stIoStatus, + &stFileInfo, + sizeof( FILE_NETWORK_OPEN_INFORMATION), + FileNetworkOpenInformation); + + if( !NT_SUCCESS( ntStatus)) + { + + try_return( ntStatus); + } + + FileInfo->FileAttributes = stFileInfo.FileAttributes; + + FileInfo->AllocationSize = stFileInfo.AllocationSize; + + FileInfo->EndOfFile = stFileInfo.EndOfFile; + + FileInfo->CreationTime = stFileInfo.CreationTime; + + FileInfo->LastAccessTime = stFileInfo.LastAccessTime; + + FileInfo->LastWriteTime = stFileInfo.LastWriteTime; + + FileInfo->ChangeTime = stFileInfo.ChangeTime; + +try_exit: + + if( hFile != NULL) + { + ZwClose( hFile); + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp b/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp index bf7851241..7a70e1a82 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp @@ -65,7 +65,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup, OUT LONG *OutVolumeReferenceReason, OUT AFSDirectoryCB **OutParentDirectoryCB, OUT AFSDirectoryCB **OutDirectoryCB, - OUT PUNICODE_STRING ComponentName) + OUT PUNICODE_STRING ComponentName, + OUT PUNICODE_STRING TargetName) { NTSTATUS ntStatus = STATUS_SUCCESS; @@ -1154,13 +1155,15 @@ AFSLocateNameEntry( IN GUID *AuthGroup, // system for it to reevaluate it // - if( FileObject != NULL) + if( FileObject != NULL || + TargetName != NULL) { ntStatus = AFSProcessDFSLink( pDirEntry, FileObject, &uniRemainingPath, - AuthGroup); + AuthGroup, + TargetName); } else { @@ -4992,7 +4995,8 @@ NTSTATUS AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry, IN PFILE_OBJECT FileObject, IN UNICODE_STRING *RemainingPath, - IN GUID *AuthGroup) + IN GUID *AuthGroup, + OUT PUNICODE_STRING TargetName) { NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; @@ -5004,7 +5008,14 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry, __Enter { - // + if ( FileObject != NULL && TargetName != NULL || + FileObject == NULL && TargetName == NULL) + { + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // // Build up the name to reparse // @@ -5103,8 +5114,8 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry, } // - // Allocate the reparse buffer - // + // Allocate the reparse buffer (from FS because might be returned in FileObject) + // uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, uniReparseName.MaximumLength, @@ -5188,17 +5199,29 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry, uniReparseName.Length += RemainingPath->Length; } - // - // Update the name in the file object - // - - if( FileObject->FileName.Buffer != NULL) + if( FileObject != NULL) { + // + // Update the name in the file object + // + + if( FileObject->FileName.Buffer != NULL) + { - AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0); + // + // original FileObject buffer was not allocated by AFS + // + + ExFreePoolWithTag( FileObject->FileName.Buffer, 0); + } + + FileObject->FileName = uniReparseName; } + else + { - FileObject->FileName = uniReparseName; + *TargetName = uniReparseName; + } AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, diff --git a/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h b/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h index 07255272e..f85396078 100644 --- a/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h +++ b/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h @@ -574,7 +574,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup, OUT LONG *OutVolumeReferenceReason, OUT AFSDirectoryCB **OutParentDirectoryCB, OUT AFSDirectoryCB **OutDirectoryCB, - OUT PUNICODE_STRING ComponentName); + OUT PUNICODE_STRING ComponentName, + OUT PUNICODE_STRING TargetName); NTSTATUS AFSCreateDirEntry( IN GUID *AuthGroup, @@ -632,8 +633,9 @@ AFSBuildRootVolume( IN GUID *AuthGroup, NTSTATUS AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry, IN PFILE_OBJECT FileObject, - IN UNICODE_STRING *RemainingPath, - IN GUID *AuthGroup); + IN PUNICODE_STRING RemainingPath, + IN GUID *AuthGroup, + OUT PUNICODE_STRING TargetName); // // AFSNetworkProviderSupport.cpp @@ -1456,6 +1458,10 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo, BOOLEAN AFSIgnoreReparsePointToFile( void); +NTSTATUS +AFSRetrieveTargetFileInfo( IN PUNICODE_STRING TargetName, + OUT AFSFileInfoCB *FileInfo); + // // AFSNameArray.cpp Prototypes // -- 2.39.5