diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 499c9b8b..dc9ce7d6 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -1835,6 +1835,7 @@ NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem, /* * POSIX Interop */ +FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count); FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid); FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid); FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)()); diff --git a/src/shared/ku/posix.c b/src/shared/ku/posix.c index fc0a6864..2f20eb50 100644 --- a/src/shared/ku/posix.c +++ b/src/shared/ku/posix.c @@ -34,6 +34,7 @@ #include +FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count); FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid); FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid); static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...); @@ -58,6 +59,7 @@ FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size); #if defined(_KERNEL_MODE) #ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FspPosixSetUidMap) #pragma alloc_text(PAGE, FspPosixMapUidToSid) #pragma alloc_text(PAGE, FspPosixMapSidToUid) #pragma alloc_text(PAGE, FspPosixCreateSid) @@ -345,6 +347,8 @@ VOID FspPosixFinalize(BOOLEAN Dynamic) if (Dynamic) { + FspPosixSetUidMap(0, 0, 0); + MemFree(FspTrustedDomains); MemFree(FspAccountDomainSid); MemFree(FspPrimaryDomainSid); @@ -425,6 +429,52 @@ static inline BOOLEAN FspPosixIsRelativeSid(PISID Sid1, PISID Sid2) return TRUE; } +static UINT32 FspPosixUidMap_Uid[8]; +static PSID FspPosixUidMap_Sid[8]; +static ULONG FspPosixUidMap_Cnt = 0; + +FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count) +{ + FSP_KU_CODE; + + NTSTATUS Result; + + if (sizeof FspPosixUidMap_Uid / sizeof FspPosixUidMap_Uid[0] < Count) + Count = sizeof FspPosixUidMap_Uid / sizeof FspPosixUidMap_Uid[0]; + + for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++) + { + MemFree(FspPosixUidMap_Sid[I]); + FspPosixUidMap_Uid[I] = 0; + FspPosixUidMap_Sid[I] = 0; + } + + FspPosixUidMap_Cnt = 0; + for (ULONG I = 0; Count > I; I++) + { + ULONG L = GetLengthSid(Sid[I]); + PSID S = MemAlloc(L); + if (0 == S) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + FspPosixUidMap_Uid[I] = Uid[I]; + FspPosixUidMap_Sid[I] = S; + memcpy(S, Sid[I], L); + FspPosixUidMap_Cnt = I + 1; + } + + Result = STATUS_SUCCESS; + +exit: + if (!NT_SUCCESS(Result)) + FspPosixSetUidMap(0, 0, 0); + + return Result; +} + FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid) { FSP_KU_CODE; @@ -433,6 +483,20 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid) *PSid = 0; + /* + * UidMap overrides default UID <-> SID mapping. + */ + for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++) + if (FspPosixUidMap_Uid[I] == Uid) + { + ULONG L = GetLengthSid(FspPosixUidMap_Sid[I]); + PSID S = MemAlloc(L); + if (0 != S) + memcpy(S, FspPosixUidMap_Sid[I], L); + *PSid = S; + goto exit; + } + /* * UID namespace partitioning (from [IDMAP] rules): * @@ -556,6 +620,7 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid) else if (FspUnmappedUid != Uid && 0x1000 <= Uid && Uid < 0x100000) *PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff); +exit: if (0 == *PSid) *PSid = FspUnmappedSid; @@ -577,6 +642,16 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid) if (!IsValidSid(Sid) || 0 == (Count = *GetSidSubAuthorityCount(Sid))) return STATUS_INVALID_SID; + /* + * UidMap overrides default UID <-> SID mapping. + */ + for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++) + if (EqualSid(FspPosixUidMap_Sid[I], Sid)) + { + *PUid = FspPosixUidMap_Uid[I]; + goto exit; + } + Authority = GetSidIdentifierAuthority(Sid)->Value[5]; SubAuthority0 = 2 <= Count ? *GetSidSubAuthority(Sid, 0) : 0; Rid = *GetSidSubAuthority(Sid, Count - 1); @@ -671,6 +746,7 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid) *PUid = 0x10000 + 0x100 * Authority + Rid; } +exit: if (-1 == *PUid) *PUid = FspUnmappedUid; diff --git a/tst/winfsp-tests/posix-test.c b/tst/winfsp-tests/posix-test.c index 87175278..d051bfd9 100644 --- a/tst/winfsp-tests/posix-test.c +++ b/tst/winfsp-tests/posix-test.c @@ -27,6 +27,8 @@ static void posix_map_sid_test(void) { +#define TEST_UIDMAP_UID 1000042 +#define TEST_UIDMAP_SID L"S-1-12-1-1111-2222-3333-4444" struct { PWSTR SidStr; @@ -100,6 +102,7 @@ static void posix_map_sid_test(void) { L"S-1-16-16384", 0x64000 }, { L"S-1-16-20480", 0x65000 }, { L"S-1-16-28672", 0x67000 }, + { TEST_UIDMAP_SID, TEST_UIDMAP_UID }, { 0, 0 }, { 0, 0 }, }; @@ -112,6 +115,14 @@ static void posix_map_sid_test(void) PSID Sid0, Sid1; UINT32 Uid; + UINT32 UidMap_Uid[1] = { TEST_UIDMAP_UID }; + PSID UidMap_Sid[1]; + Success = ConvertStringSidToSidW(TEST_UIDMAP_SID, &UidMap_Sid[0]); + ASSERT(Success); + Result = FspPosixSetUidMap(UidMap_Uid, UidMap_Sid, 1); + ASSERT(NT_SUCCESS(Result)); + LocalFree(UidMap_Sid[0]); + Success = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token); ASSERT(Success); @@ -169,6 +180,12 @@ static void posix_map_sid_test(void) LocalFree(map[sizeof map / sizeof map[0] - 2].SidStr); LocalFree(map[sizeof map / sizeof map[0] - 1].SidStr); + + Result = FspPosixSetUidMap(0, 0, 0); + ASSERT(NT_SUCCESS(Result)); + +#undef TEST_UIDMAP_UID +#undef TEST_UIDMAP_SID } static void posix_map_sd_test(void)