mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FspUnicodePathIsValid, FspUnicodePathIsValidPattern
This commit is contained in:
		| @@ -618,7 +618,7 @@ static NTSTATUS FspFsvolQueryDirectory( | |||||||
|         return STATUS_INVALID_PARAMETER; |         return STATUS_INVALID_PARAMETER; | ||||||
|  |  | ||||||
|     /* check that FileName is valid (if supplied) */ |     /* check that FileName is valid (if supplied) */ | ||||||
|     if (0 != FileName && !FspUnicodePathIsValid(FileName, FALSE)) |     if (0 != FileName && !FspUnicodePathIsValidPattern(FileName)) | ||||||
|         return STATUS_INVALID_PARAMETER; |         return STATUS_INVALID_PARAMETER; | ||||||
|  |  | ||||||
|     /* is this an allowed file information class? */ |     /* is this an allowed file information class? */ | ||||||
|   | |||||||
| @@ -426,6 +426,7 @@ BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime) | |||||||
| PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag); | PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag); | ||||||
| PVOID FspAllocateIrpMustSucceed(CCHAR StackSize); | PVOID FspAllocateIrpMustSucceed(CCHAR StackSize); | ||||||
| BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); | BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); | ||||||
|  | BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern); | ||||||
| VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | ||||||
| NTSTATUS FspCreateGuid(GUID *Guid); | NTSTATUS FspCreateGuid(GUID *Guid); | ||||||
| NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess, | NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess, | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
| #include <sys/driver.h> | #include <sys/driver.h> | ||||||
|  |  | ||||||
| BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); | BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); | ||||||
|  | BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern); | ||||||
| VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | ||||||
| NTSTATUS FspCreateGuid(GUID *Guid); | NTSTATUS FspCreateGuid(GUID *Guid); | ||||||
| NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess, | NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess, | ||||||
| @@ -88,6 +89,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); | |||||||
|  |  | ||||||
| #ifdef ALLOC_PRAGMA | #ifdef ALLOC_PRAGMA | ||||||
| #pragma alloc_text(PAGE, FspUnicodePathIsValid) | #pragma alloc_text(PAGE, FspUnicodePathIsValid) | ||||||
|  | #pragma alloc_text(PAGE, FspUnicodePathIsValidPattern) | ||||||
| #pragma alloc_text(PAGE, FspUnicodePathSuffix) | #pragma alloc_text(PAGE, FspUnicodePathSuffix) | ||||||
| #pragma alloc_text(PAGE, FspCreateGuid) | #pragma alloc_text(PAGE, FspCreateGuid) | ||||||
| #pragma alloc_text(PAGE, FspGetDeviceObjectPointer) | #pragma alloc_text(PAGE, FspGetDeviceObjectPointer) | ||||||
| @@ -171,30 +173,91 @@ PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) | |||||||
|  |  | ||||||
| BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) | BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) | ||||||
| { | { | ||||||
|     /* this does NOT check if the Path contains invalid file name chars (*, ?, etc.) */ |  | ||||||
|  |  | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     if (0 != Path->Length % sizeof(WCHAR)) |     if (0 != Path->Length % sizeof(WCHAR)) | ||||||
|         return FALSE; |         return FALSE; | ||||||
|  |  | ||||||
|     PWSTR PathBgn, PathEnd, PathPtr; |     PWSTR PathBgn, PathEnd, PathPtr; | ||||||
|  |     UCHAR Flags = FSRTL_NTFS_LEGAL; | ||||||
|  |     WCHAR Char; | ||||||
|  |  | ||||||
|     PathBgn = Path->Buffer; |     PathBgn = Path->Buffer; | ||||||
|     PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length); |     PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length); | ||||||
|     PathPtr = PathBgn; |     PathPtr = PathBgn; | ||||||
|  |  | ||||||
|     while (PathEnd > PathPtr) |     while (PathEnd > PathPtr) | ||||||
|         if (L'\\' == *PathPtr) |     { | ||||||
|  |         Char = *PathPtr; | ||||||
|  |  | ||||||
|  |         if (L'\\' == Char) | ||||||
|         { |         { | ||||||
|  |             /* stream names can only appear as the last path component */ | ||||||
|  |             if (BooleanFlagOn(Flags, FSRTL_OLE_LEGAL)) | ||||||
|  |                 return FALSE; | ||||||
|  |  | ||||||
|             PathPtr++; |             PathPtr++; | ||||||
|  |  | ||||||
|  |             /* don't like multiple backslashes */ | ||||||
|             if (PathEnd > PathPtr && L'\\' == *PathPtr) |             if (PathEnd > PathPtr && L'\\' == *PathPtr) | ||||||
|                 return FALSE; |                 return FALSE; | ||||||
|         } |         } | ||||||
|         else if (!AllowStreams && L':' == *PathPtr) |         else if (L':' == Char) | ||||||
|  |         { | ||||||
|  |             if (!AllowStreams) | ||||||
|  |                 return FALSE; | ||||||
|  |  | ||||||
|  |             /* | ||||||
|  |              * Where are the docs on legal stream names? | ||||||
|  |              */ | ||||||
|  |  | ||||||
|  |             PathPtr++; | ||||||
|  |  | ||||||
|  |             /* stream characters now allowed */ | ||||||
|  |             SetFlag(Flags, FSRTL_OLE_LEGAL); | ||||||
|  |         } | ||||||
|  |         else if (0x80 > Char && !FsRtlTestAnsiCharacter(Char, TRUE, FALSE, Flags)) | ||||||
|             return FALSE; |             return FALSE; | ||||||
|         else |         else | ||||||
|             PathPtr++; |             PathPtr++; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Path) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     if (0 != Path->Length % sizeof(WCHAR)) | ||||||
|  |         return FALSE; | ||||||
|  |  | ||||||
|  |     PWSTR PathBgn, PathEnd, PathPtr; | ||||||
|  |     WCHAR Char; | ||||||
|  |  | ||||||
|  |     PathBgn = Path->Buffer; | ||||||
|  |     PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length); | ||||||
|  |     PathPtr = PathBgn; | ||||||
|  |  | ||||||
|  |     while (PathEnd > PathPtr) | ||||||
|  |     { | ||||||
|  |         Char = *PathPtr; | ||||||
|  |  | ||||||
|  |         /* | ||||||
|  |          * A pattern is allowed to have wildcards. It cannot consist of multiple | ||||||
|  |          * path components (have a backslash) and it cannot reference a stream (have | ||||||
|  |          * a colon). | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         if (L'\\' == Char) | ||||||
|  |             return FALSE; | ||||||
|  |         else if (L':' == Char) | ||||||
|  |             return FALSE; | ||||||
|  |         else if (0x80 > Char && !FsRtlTestAnsiCharacter(Char, TRUE, TRUE, FSRTL_NTFS_LEGAL)) | ||||||
|  |             return FALSE; | ||||||
|  |         else | ||||||
|  |             PathPtr++; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return TRUE; |     return TRUE; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -68,6 +68,24 @@ void create_dotest(ULONG Flags, PWSTR Prefix) | |||||||
|         ASSERT(ERROR_INVALID_NAME == GetLastError()); |         ASSERT(ERROR_INVALID_NAME == GetLastError()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /* invalid chars (wildcards) not allowed */ | ||||||
|  |     StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0*", | ||||||
|  |         Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); | ||||||
|  |  | ||||||
|  |     Handle = CreateFileW(FilePath, | ||||||
|  |         GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); | ||||||
|  |     ASSERT(INVALID_HANDLE_VALUE == Handle); | ||||||
|  |     ASSERT(ERROR_INVALID_NAME == GetLastError()); | ||||||
|  |  | ||||||
|  |     /* stream names can only appear as the last path component */ | ||||||
|  |     StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\DOESNOTEXIST:foo\\file0*", | ||||||
|  |         Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); | ||||||
|  |  | ||||||
|  |     Handle = CreateFileW(FilePath, | ||||||
|  |         GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); | ||||||
|  |     ASSERT(INVALID_HANDLE_VALUE == Handle); | ||||||
|  |     ASSERT(ERROR_INVALID_NAME == GetLastError()); | ||||||
|  |  | ||||||
|     StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1", |     StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1", | ||||||
|         Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); |         Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs)); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user