mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
dll: fuse: uidmap option and AzureAD support
This commit is contained in:
parent
74bb51ae07
commit
9ae9b8ff2c
@ -82,6 +82,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FUSE_OPT_KEY("fstypename=", 'F'),
|
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||||
FUSE_OPT_KEY("volname=", 'v'),
|
FUSE_OPT_KEY("volname=", 'v'),
|
||||||
|
|
||||||
|
FUSE_OPT_KEY("uidmap=", 'm'),
|
||||||
|
|
||||||
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
||||||
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
||||||
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
||||||
@ -293,43 +295,241 @@ static int fsp_fuse_sddl_to_security(const char *Sddl, PUINT8 Security, PULONG P
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsp_fuse_username_to_uid(const char *username, int *puid)
|
static int fsp_fuse_tokenuser_to_sid(HANDLE Token, PSID Sid, PULONG PSidSize)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TOKEN_USER V;
|
||||||
|
UINT8 B[128];
|
||||||
|
} InfoBuf;
|
||||||
|
PTOKEN_USER InfoPtr = &InfoBuf.V;
|
||||||
|
DWORD Size;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
if (!GetTokenInformation(Token, TokenUser, InfoPtr, sizeof InfoBuf, &Size))
|
||||||
|
{
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
InfoPtr = MemAlloc(Size);
|
||||||
|
if (0 == InfoPtr)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (!GetTokenInformation(Token, TokenUser, InfoPtr, Size, &Size))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = GetLengthSid(InfoPtr->User.Sid);
|
||||||
|
if (*PSidSize >= Size)
|
||||||
|
{
|
||||||
|
memcpy(Sid, InfoPtr->User.Sid, Size);
|
||||||
|
*PSidSize = Size;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (InfoPtr != &InfoBuf.V)
|
||||||
|
MemFree(InfoPtr);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_tokenuser_is_azuread(HANDLE Token)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
SID V;
|
SID V;
|
||||||
UINT8 B[SECURITY_MAX_SID_SIZE];
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
} SidBuf;
|
} SidBuf;
|
||||||
|
ULONG Size;
|
||||||
|
PSID Sid = &SidBuf.V;
|
||||||
|
BYTE Count, Authority;
|
||||||
|
UINT32 SubAuthority0;
|
||||||
|
|
||||||
|
Size = sizeof SidBuf;
|
||||||
|
if (-1 == fsp_fuse_tokenuser_to_sid(Token, &SidBuf.V, &Size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Count = *GetSidSubAuthorityCount(Sid);
|
||||||
|
Authority = GetSidIdentifierAuthority(Sid)->Value[5];
|
||||||
|
SubAuthority0 = 2 <= Count ? *GetSidSubAuthority(Sid, 0) : 0;
|
||||||
|
|
||||||
|
return 12 == Authority && 1 == SubAuthority0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_username_to_sid(const char *UserName, PSID Sid, PULONG PSidSize)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} SidBuf;
|
||||||
|
PSID SidPtr = &SidBuf.V;
|
||||||
char Name[256], Domn[256];
|
char Name[256], Domn[256];
|
||||||
DWORD SidSize, NameSize, DomnSize;
|
DWORD Size, NameSize, DomnSize;
|
||||||
SID_NAME_USE Use;
|
SID_NAME_USE Use;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
if ('S' == UserName[0] && '-' == UserName[1] && '1' == UserName[2] && '-' == UserName[3])
|
||||||
|
{
|
||||||
|
if (!ConvertStringSidToSidA(UserName, &SidPtr))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NameSize = lstrlenA(UserName) + 1;
|
||||||
|
if (sizeof Name / sizeof Name[0] < NameSize)
|
||||||
|
goto exit;
|
||||||
|
memcpy(Name, UserName, NameSize);
|
||||||
|
for (PSTR P = Name, EndP = P + NameSize; EndP > P; P++)
|
||||||
|
if ('+' == *P)
|
||||||
|
*P = '\\';
|
||||||
|
|
||||||
|
Size = sizeof SidBuf;
|
||||||
|
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||||
|
if (!LookupAccountNameA(0, Name, SidPtr, &Size, Domn, &DomnSize, &Use))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = GetLengthSid(SidPtr);
|
||||||
|
if (*PSidSize >= Size)
|
||||||
|
{
|
||||||
|
memcpy(Sid, SidPtr, Size);
|
||||||
|
*PSidSize = Size;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (SidPtr != &SidBuf.V)
|
||||||
|
LocalFree(SidPtr);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_username_to_uid(const char *UserName, int *PUid)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} SidBuf;
|
||||||
|
ULONG SidSize;
|
||||||
UINT32 Uid;
|
UINT32 Uid;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
*puid = 0;
|
*PUid = 0;
|
||||||
|
|
||||||
NameSize = lstrlenA(username) + 1;
|
|
||||||
if (sizeof Name / sizeof Name[0] < NameSize)
|
|
||||||
return -1;
|
|
||||||
memcpy(Name, username, NameSize);
|
|
||||||
for (PSTR P = Name, EndP = P + NameSize; EndP > P; P++)
|
|
||||||
if ('+' == *P)
|
|
||||||
*P = '\\';
|
|
||||||
|
|
||||||
SidSize = sizeof SidBuf;
|
SidSize = sizeof SidBuf;
|
||||||
DomnSize = sizeof Domn / sizeof Domn[0];
|
if (-1 == fsp_fuse_username_to_sid(UserName, &SidBuf.V, &SidSize))
|
||||||
if (!LookupAccountNameA(0, Name, &SidBuf, &SidSize, Domn, &DomnSize, &Use))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Result = FspPosixMapSidToUid(&SidBuf, &Uid);
|
Result = FspPosixMapSidToUid(&SidBuf.V, &Uid);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*puid = Uid;
|
*PUid = Uid;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_set_uidmap(const char *Spec)
|
||||||
|
{
|
||||||
|
char Buf[1024], *P = Buf, *UidP, *UserP, C;
|
||||||
|
int Len;
|
||||||
|
UINT32 Uid[8];
|
||||||
|
PSID Sid[8];
|
||||||
|
union
|
||||||
|
{
|
||||||
|
SID V;
|
||||||
|
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||||
|
} SidBuf[8];
|
||||||
|
ULONG SidSize;
|
||||||
|
ULONG Count;
|
||||||
|
NTSTATUS Result;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
Len = lstrlenA(Spec);
|
||||||
|
if (sizeof Buf <= Len)
|
||||||
|
return -1;
|
||||||
|
memcpy(Buf, Spec, Len + 1);
|
||||||
|
|
||||||
|
Count = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (sizeof Uid / sizeof Uid[0] <= Count)
|
||||||
|
{
|
||||||
|
/* out of space */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
UidP = P;
|
||||||
|
for (; '\0' != (C = *P) && ';' != C && ':' != C; P++)
|
||||||
|
;
|
||||||
|
*P = '\0';
|
||||||
|
|
||||||
|
if (UidP == P)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Uid[Count] = strtouint(UidP, 0, 10, 0);
|
||||||
|
if (0 == Uid[Count])
|
||||||
|
{
|
||||||
|
/* invalid uid */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserP = 0;
|
||||||
|
if (':' == C)
|
||||||
|
{
|
||||||
|
UserP = ++P;
|
||||||
|
for (; '\0' != (C = *P) && ';' != C; P++)
|
||||||
|
;
|
||||||
|
*P = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != UserP && '\0' != *UserP)
|
||||||
|
{
|
||||||
|
SidSize = sizeof SidBuf[Count];
|
||||||
|
if (-1 == fsp_fuse_username_to_sid(UserP, &SidBuf[Count].V, &SidSize))
|
||||||
|
{
|
||||||
|
/* invalid SID */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Sid[Count] = &SidBuf[Count].V;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HANDLE Token;
|
||||||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
||||||
|
{
|
||||||
|
SidSize = sizeof SidBuf[Count];
|
||||||
|
if (-1 == fsp_fuse_tokenuser_to_sid(Token, &SidBuf[Count].V, &SidSize))
|
||||||
|
{
|
||||||
|
/* invalid SID */
|
||||||
|
CloseHandle(Token);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
CloseHandle(Token);
|
||||||
|
Sid[Count] = &SidBuf[Count].V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Count++;
|
||||||
|
|
||||||
|
if ('\0' == C)
|
||||||
|
break;
|
||||||
|
|
||||||
|
P++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspPosixSetUidMap(Uid, Sid, Count);
|
||||||
|
res = NT_SUCCESS(Result) ? 0 : -1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int fsp_fuse_utf8towcs_trunc(
|
static int fsp_fuse_utf8towcs_trunc(
|
||||||
const char *Str, int StrLen,
|
const char *Str, int StrLen,
|
||||||
PWSTR Wcs, int WcsLen)
|
PWSTR Wcs, int WcsLen)
|
||||||
@ -424,6 +624,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
" -o KeepFileCache do not discard cache when files are closed\n"
|
" -o KeepFileCache do not discard cache when files are closed\n"
|
||||||
" -o LegacyUnlinkRename do not support new POSIX unlink/rename\n"
|
" -o LegacyUnlinkRename do not support new POSIX unlink/rename\n"
|
||||||
" -o ThreadCount number of file system dispatcher threads\n"
|
" -o ThreadCount number of file system dispatcher threads\n"
|
||||||
|
" -o uidmap=UID:SID[;...] explicit UID <-> SID map (max 8 entries)\n"
|
||||||
);
|
);
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
return 1;
|
return 1;
|
||||||
@ -531,6 +732,14 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
if (0 == opt_data->VolumeLabelLength)
|
if (0 == opt_data->VolumeLabelLength)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
case 'm':
|
||||||
|
arg += sizeof "uidmap=" - 1;
|
||||||
|
if (-1 == fsp_fuse_set_uidmap(arg))
|
||||||
|
{
|
||||||
|
opt_data->set_uidmap = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,6 +788,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
ErrorMessage = L": invalid user or group name.";
|
ErrorMessage = L": invalid user or group name.";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
else if (-1 == opt_data.set_uidmap)
|
||||||
|
{
|
||||||
|
ErrorMessage = L": invalid uidmap.";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (opt_data.help)
|
if (opt_data.help)
|
||||||
@ -601,6 +815,10 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
|
|
||||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
||||||
{
|
{
|
||||||
|
/* if an AzureAD user and no uidmap specified, set a default uidmap that matches Cygwin */
|
||||||
|
if (!opt_data.set_uidmap && fsp_fuse_tokenuser_is_azuread(Token))
|
||||||
|
fsp_fuse_set_uidmap("4096:");
|
||||||
|
|
||||||
fsp_fuse_get_token_uidgid(Token, TokenUser,
|
fsp_fuse_get_token_uidgid(Token, TokenUser,
|
||||||
opt_data.set_uid && -1 == opt_data.uid ? &opt_data.uid : 0,
|
opt_data.set_uid && -1 == opt_data.uid ? &opt_data.uid : 0,
|
||||||
opt_data.set_gid && -1 == opt_data.gid ? &opt_data.gid : 0);
|
opt_data.set_gid && -1 == opt_data.gid ? &opt_data.gid : 0);
|
||||||
|
@ -147,6 +147,7 @@ struct fsp_fuse_core_opt_data
|
|||||||
set_create_dir_umask, create_dir_umask,
|
set_create_dir_umask, create_dir_umask,
|
||||||
set_uid, uid, username_to_uid_result,
|
set_uid, uid, username_to_uid_result,
|
||||||
set_gid, gid,
|
set_gid, gid,
|
||||||
|
set_uidmap,
|
||||||
set_attr_timeout, attr_timeout,
|
set_attr_timeout, attr_timeout,
|
||||||
rellinks,
|
rellinks,
|
||||||
dothidden;
|
dothidden;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user