mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
760cd5e46f | |||
b36b6c60e2 | |||
e4984bf675 | |||
0c8bcd5d7d | |||
b5d8cd3ea6 | |||
af5f409233 | |||
cffb066d46 | |||
804434d836 | |||
f7595e40b6 | |||
669dd07ce2 | |||
b6fa54d301 | |||
342e7e39e2 | |||
9dfdd19616 | |||
2c651b1bd8 | |||
41764f7b41 | |||
08e697c52c | |||
66cc043149 | |||
518cd0e8c0 | |||
c0344f53b0 | |||
76445a5403 | |||
0577b8febb | |||
610a7ac2a6 |
@ -45,13 +45,14 @@
|
|||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
<DirectoryRef Id="INSTALLDIR">
|
<DirectoryRef Id="INSTALLDIR">
|
||||||
<Component Id="C.INSTALLDIR">
|
<Component Id="C.INSTALLDIR" Guid="{F876F26E-5016-4AC6-93B3-653C0312A6CE}">
|
||||||
<RegistryValue
|
<RegistryValue
|
||||||
Root="HKLM"
|
Root="HKLM"
|
||||||
Key="[P.RegistryKey]"
|
Key="[P.RegistryKey]"
|
||||||
Name="InstallDir"
|
Name="InstallDir"
|
||||||
Type="string"
|
Type="string"
|
||||||
Value="[INSTALLDIR]" />
|
Value="[INSTALLDIR]"
|
||||||
|
KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -128,6 +129,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -149,6 +151,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -170,6 +173,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
||||||
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
|
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
|
||||||
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
|
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
|
||||||
<MyVersion>0.13.$(MyBuildNumber)</MyVersion>
|
<MyVersion>0.14.$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@ -182,7 +182,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -207,7 +207,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -235,7 +235,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -263,7 +263,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v0.14::
|
||||||
|
|
||||||
|
This release includes support for file systems protected by credentials.
|
||||||
|
|
||||||
|
- WinFsp now supports file systems that require username/password to be unlocked (e.g. sshfs/secfs). Such file systems must add a DWORD registry value with name "Credentials" and value 1 under their WinFsp.Launcher service entry. The WinFsp network provider will then prompt for credentials using the `CredUIPromptForWindowsCredentials` API. Credentials can optionally be saved with the Windows Credential Manager.
|
||||||
|
- WinFsp-FUSE now uses the S-1-0-65534 <--> 65534 mapping for unmapped SID/UID's. The Anonymous SID mapping from the previous release had security issues.
|
||||||
|
|
||||||
|
|
||||||
v0.13::
|
v0.13::
|
||||||
|
|
||||||
This release includes a Cygwin package, an API change and some other minor changes:
|
This release includes a Cygwin package, an API change and some other minor changes:
|
||||||
|
2
ext/test
2
ext/test
Submodule ext/test updated: da7b88d6cf...a651263c4c
@ -244,6 +244,7 @@ struct fsp_fuse_env
|
|||||||
void (*memfree)(void *);
|
void (*memfree)(void *);
|
||||||
int (*daemonize)(int);
|
int (*daemonize)(int);
|
||||||
int (*set_signal_handlers)(void *);
|
int (*set_signal_handlers)(void *);
|
||||||
|
void (*reserved[4])();
|
||||||
};
|
};
|
||||||
|
|
||||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
NAME="fuse"
|
NAME="fuse"
|
||||||
VERSION=2.8
|
VERSION=2.8
|
||||||
RELEASE=2
|
RELEASE=3
|
||||||
CATEGORY="Utils"
|
CATEGORY="Utils"
|
||||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||||
|
@ -463,9 +463,9 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
return 1;
|
return 1;
|
||||||
case 'U':
|
case 'U':
|
||||||
if ('U' == arg[2])
|
if ('U' == arg[2])
|
||||||
arg += sizeof "--UNC" - 1;
|
arg += sizeof "--UNC=" - 1;
|
||||||
else if ('V' == arg[2])
|
else if ('V' == arg[2])
|
||||||
arg += sizeof "--VolumePrefix" - 1;
|
arg += sizeof "--VolumePrefix=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
||||||
return -1;
|
return -1;
|
||||||
@ -507,6 +507,9 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
f->env = env;
|
f->env = env;
|
||||||
|
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
||||||
|
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
||||||
|
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
||||||
memcpy(&f->ops, ops, opsize);
|
memcpy(&f->ops, ops, opsize);
|
||||||
f->data = data;
|
f->data = data;
|
||||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||||
|
@ -205,6 +205,13 @@ static NTSTATUS fsp_fuse_intf_GetFileInfoEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != err)
|
if (0 != err)
|
||||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
|
||||||
|
if (f->set_umask)
|
||||||
|
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
||||||
|
if (f->set_uid)
|
||||||
|
stbuf.st_uid = f->uid;
|
||||||
|
if (f->set_gid)
|
||||||
|
stbuf.st_gid = f->gid;
|
||||||
|
|
||||||
*PUid = stbuf.st_uid;
|
*PUid = stbuf.st_uid;
|
||||||
*PGid = stbuf.st_gid;
|
*PGid = stbuf.st_gid;
|
||||||
*PMode = stbuf.st_mode;
|
*PMode = stbuf.st_mode;
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
struct fuse
|
struct fuse
|
||||||
{
|
{
|
||||||
struct fsp_fuse_env *env;
|
struct fsp_fuse_env *env;
|
||||||
|
int set_umask, umask;
|
||||||
|
int set_uid, uid;
|
||||||
|
int set_gid, gid;
|
||||||
struct fuse_operations ops;
|
struct fuse_operations ops;
|
||||||
void *data;
|
void *data;
|
||||||
UINT32 DebugLog;
|
UINT32 DebugLog;
|
||||||
|
332
src/dll/np.c
332
src/dll/np.c
@ -18,10 +18,29 @@
|
|||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <launcher/launcher.h>
|
#include <launcher/launcher.h>
|
||||||
#include <npapi.h>
|
#include <npapi.h>
|
||||||
|
#include <wincred.h>
|
||||||
|
|
||||||
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the following macro to use CredUIPromptForWindowsCredentials.
|
||||||
|
* Otherwise CredUIPromptForCredentials will be used.
|
||||||
|
*/
|
||||||
|
#define FSP_NP_CREDUI_PROMPT_NEW
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the following macro to include support for the credential manager.
|
||||||
|
*/
|
||||||
|
#define FSP_NP_CREDENTIAL_MANAGER
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FSP_NP_CREDENTIALS_NONE = 0,
|
||||||
|
FSP_NP_CREDENTIALS_PASSWORD = 1,
|
||||||
|
FSP_NP_CREDENTIALS_USERPASS = 3,
|
||||||
|
};
|
||||||
|
|
||||||
DWORD APIENTRY NPGetCaps(DWORD Index)
|
DWORD APIENTRY NPGetCaps(DWORD Index)
|
||||||
{
|
{
|
||||||
switch (Index)
|
switch (Index)
|
||||||
@ -102,6 +121,9 @@ static inline BOOLEAN FspNpParseRemoteName(PWSTR RemoteName,
|
|||||||
PWSTR ClassName, InstanceName, P;
|
PWSTR ClassName, InstanceName, P;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
|
||||||
|
if (!FspNpCheckRemoteName(RemoteName))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
ClassName = RemoteName + 2; /* skip \\ */
|
ClassName = RemoteName + 2; /* skip \\ */
|
||||||
for (P = ClassName; *P; P++)
|
for (P = ClassName; *P; P++)
|
||||||
if (L'\\' == *P)
|
if (L'\\' == *P)
|
||||||
@ -129,6 +151,27 @@ static inline BOOLEAN FspNpParseRemoteName(PWSTR RemoteName,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpParseUserName(PWSTR RemoteName,
|
||||||
|
PWSTR UserName, ULONG UserNameSize/* in chars */)
|
||||||
|
{
|
||||||
|
PWSTR ClassName, InstanceName, P;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
|
||||||
|
if (FspNpParseRemoteName(RemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
{
|
||||||
|
for (P = InstanceName; *P; P++)
|
||||||
|
if ('@' == *P && P - InstanceName < UserNameSize)
|
||||||
|
{
|
||||||
|
memcpy(UserName, InstanceName, (P - InstanceName) * sizeof(WCHAR));
|
||||||
|
UserName[P - InstanceName] = L'\0';
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
@ -225,6 +268,144 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||||
|
{
|
||||||
|
HKEY RegKey = 0;
|
||||||
|
DWORD NpResult, RegSize;
|
||||||
|
DWORD Credentials;
|
||||||
|
PWSTR ClassName, InstanceName;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
|
||||||
|
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||||
|
|
||||||
|
if (!FspNpParseRemoteName(RemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
|
||||||
|
if (ClassNameLen > sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1)
|
||||||
|
ClassNameLen = sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1;
|
||||||
|
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||||
|
ClassNameBuf[ClassNameLen] = '\0';
|
||||||
|
|
||||||
|
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY, 0, KEY_READ, &RegKey);
|
||||||
|
if (ERROR_SUCCESS != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
RegSize = sizeof Credentials;
|
||||||
|
Credentials = 0; /* default is NO credentials */
|
||||||
|
NpResult = RegGetValueW(RegKey, ClassNameBuf, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||||
|
&Credentials, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != NpResult && ERROR_FILE_NOT_FOUND != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
switch (Credentials)
|
||||||
|
{
|
||||||
|
case FSP_NP_CREDENTIALS_NONE:
|
||||||
|
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||||
|
case FSP_NP_CREDENTIALS_USERPASS:
|
||||||
|
*PCredentialsKind = Credentials;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != RegKey)
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD FspNpGetCredentials(
|
||||||
|
HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult,
|
||||||
|
DWORD CredentialsKind,
|
||||||
|
PBOOL PSave,
|
||||||
|
PWSTR UserName, ULONG UserNameSize/* in chars */,
|
||||||
|
PWSTR Password, ULONG PasswordSize/* in chars */)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
CREDUI_INFOW UiInfo;
|
||||||
|
|
||||||
|
memset(&UiInfo, 0, sizeof UiInfo);
|
||||||
|
UiInfo.cbSize = sizeof UiInfo;
|
||||||
|
UiInfo.hwndParent = hwndOwner;
|
||||||
|
UiInfo.pszCaptionText = Caption;
|
||||||
|
UiInfo.pszMessageText = L"Enter credentials to unlock this file system.";
|
||||||
|
|
||||||
|
#if !defined(FSP_NP_CREDUI_PROMPT_NEW)
|
||||||
|
NpResult = CredUIPromptForCredentialsW(&UiInfo, L"NONE", 0, 0,
|
||||||
|
UserName, UserNameSize,
|
||||||
|
Password, PasswordSize,
|
||||||
|
PSave,
|
||||||
|
CREDUI_FLAGS_GENERIC_CREDENTIALS |
|
||||||
|
CREDUI_FLAGS_DO_NOT_PERSIST |
|
||||||
|
CREDUI_FLAGS_ALWAYS_SHOW_UI |
|
||||||
|
(0 != PrevNpResult ? CREDUI_FLAGS_INCORRECT_PASSWORD : 0) |
|
||||||
|
(0 != PSave ? CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX : 0) |
|
||||||
|
(FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0));
|
||||||
|
#else
|
||||||
|
WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
|
||||||
|
ULONG AuthPackage = 0;
|
||||||
|
PVOID InAuthBuf = 0, OutAuthBuf = 0;
|
||||||
|
ULONG InAuthSize, OutAuthSize, DomainSize;
|
||||||
|
|
||||||
|
InAuthSize = 0;
|
||||||
|
if (!CredPackAuthenticationBufferW(
|
||||||
|
CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, 0, &InAuthSize) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
InAuthBuf = MemAlloc(InAuthSize);
|
||||||
|
if (0 == InAuthBuf)
|
||||||
|
{
|
||||||
|
NpResult = ERROR_NO_SYSTEM_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CredPackAuthenticationBufferW(
|
||||||
|
CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, InAuthBuf, &InAuthSize))
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult,
|
||||||
|
&AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave,
|
||||||
|
CREDUIWIN_GENERIC | (0 != PSave ? CREDUIWIN_CHECKBOX : 0));
|
||||||
|
if (ERROR_SUCCESS != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
DomainSize = sizeof Domain / sizeof Domain[0];
|
||||||
|
if (!CredUnPackAuthenticationBufferW(0, OutAuthBuf, OutAuthSize,
|
||||||
|
UserName, &UserNameSize, Domain, &DomainSize, Password, &PasswordSize))
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != OutAuthBuf)
|
||||||
|
{
|
||||||
|
SecureZeroMemory(OutAuthBuf, OutAuthSize);
|
||||||
|
CoTaskMemFree(OutAuthBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != InAuthBuf)
|
||||||
|
{
|
||||||
|
SecureZeroMemory(InAuthBuf, InAuthSize);
|
||||||
|
MemFree(InAuthBuf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPGetConnection(
|
DWORD APIENTRY NPGetConnection(
|
||||||
LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
||||||
{
|
{
|
||||||
@ -303,12 +484,6 @@ DWORD APIENTRY NPGetConnection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
|
DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
|
||||||
{
|
|
||||||
return NPAddConnection3(0, lpNetResource, lpPassword, lpUserName, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|
||||||
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
DWORD dwType = lpNetResource->dwType;
|
DWORD dwType = lpNetResource->dwType;
|
||||||
@ -317,14 +492,15 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
WCHAR LocalNameBuf[3];
|
WCHAR LocalNameBuf[3];
|
||||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
DWORD CredentialsKind;
|
||||||
PWSTR PipeBuf = 0;
|
PWSTR PipeBuf = 0;
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
PCREDENTIALW Credential = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dwType & RESOURCETYPE_PRINT)
|
if (dwType & RESOURCETYPE_PRINT)
|
||||||
return WN_BAD_VALUE;
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
if (!FspNpCheckRemoteName(lpRemoteName))
|
|
||||||
return WN_BAD_NETNAME;
|
|
||||||
|
|
||||||
if (!FspNpParseRemoteName(lpRemoteName,
|
if (!FspNpParseRemoteName(lpRemoteName,
|
||||||
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
return WN_BAD_NETNAME;
|
return WN_BAD_NETNAME;
|
||||||
@ -344,22 +520,75 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
return WN_ALREADY_CONNECTED;
|
return WN_ALREADY_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
/* if we need credentials and none were passed check with the credential manager */
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind && 0 == lpPassword &&
|
||||||
|
CredReadW(lpRemoteName, CRED_TYPE_GENERIC, 0, &Credential))
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) <= Credential->CredentialBlobSize &&
|
||||||
|
L'\0' == ((PWSTR)(Credential->CredentialBlob))
|
||||||
|
[(Credential->CredentialBlobSize / sizeof(WCHAR)) - 1])
|
||||||
|
{
|
||||||
|
lpUserName = Credential->UserName;
|
||||||
|
lpPassword = (PVOID)Credential->CredentialBlob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if we need credentials and we don't have any return ACCESS DENIED */
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
if (0 == lpPassword ||
|
||||||
|
(0 == (Length = lstrlenW(lpPassword))) || CREDUI_MAX_PASSWORD_LENGTH < Length)
|
||||||
|
{
|
||||||
|
NpResult = WN_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
if (0 == lpUserName ||
|
||||||
|
(0 == (Length = lstrlenW(lpUserName))) || CREDUI_MAX_USERNAME_LENGTH < Length)
|
||||||
|
{
|
||||||
|
NpResult = WN_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
if (0 == PipeBuf)
|
if (0 == PipeBuf)
|
||||||
return WN_OUT_OF_MEMORY;
|
{
|
||||||
|
NpResult = WN_OUT_OF_MEMORY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we do not explicitly check, but assumption is it all fits in LAUNCHER_PIPE_BUFFER_SIZE */
|
||||||
P = PipeBuf;
|
P = PipeBuf;
|
||||||
*P++ = LauncherSvcInstanceStart;
|
*P++ = FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
|
||||||
|
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||||
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||||
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
||||||
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
||||||
|
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||||
|
{
|
||||||
|
lstrcpyW(P, lpUserName); P += lstrlenW(lpUserName) + 1;
|
||||||
|
}
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
|
||||||
|
{
|
||||||
|
lstrcpyW(P, lpPassword); P += lstrlenW(lpPassword) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
NpResult = FspNpCallLauncherPipe(
|
NpResult = FspNpCallLauncherPipe(
|
||||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
switch (NpResult)
|
switch (NpResult)
|
||||||
{
|
{
|
||||||
case WN_SUCCESS:
|
case WN_SUCCESS:
|
||||||
|
case WN_ACCESS_DENIED:
|
||||||
break;
|
break;
|
||||||
case ERROR_ALREADY_EXISTS:
|
case ERROR_ALREADY_EXISTS:
|
||||||
/*
|
/*
|
||||||
@ -393,8 +622,89 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
MemFree(PipeBuf);
|
MemFree(PipeBuf);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
if (0 != Credential)
|
||||||
|
CredFree(Credential);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
||||||
|
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
PWSTR RemoteName = lpNetResource->lpRemoteName;
|
||||||
|
DWORD CredentialsKind;
|
||||||
|
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
BOOL Save = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//dwFlags |= CONNECT_INTERACTIVE | CONNECT_PROMPT; /* TESTING ONLY! */
|
||||||
|
|
||||||
|
/* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */
|
||||||
|
if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT)))
|
||||||
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
|
/* if not CONNECT_PROMPT go ahead and attempt to NPAddConnection once */
|
||||||
|
if (0 == (dwFlags & CONNECT_PROMPT))
|
||||||
|
{
|
||||||
|
NpResult = NPAddConnection(lpNetResource, lpPassword, lpUserName);
|
||||||
|
if (WN_ACCESS_DENIED != NpResult || 0 == (dwFlags & CONNECT_INTERACTIVE))
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspNpGetCredentialsKind(RemoteName, &CredentialsKind);
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||||
|
return WN_CANCEL;
|
||||||
|
|
||||||
|
/* if CONNECT_INTERACTIVE keep asking the user for valid credentials or cancel */
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
lstrcpyW(UserName, L"UNSPECIFIED");
|
||||||
|
Password[0] = L'\0';
|
||||||
|
if (FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind)
|
||||||
|
FspNpParseUserName(RemoteName, UserName, sizeof UserName / sizeof UserName[0]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NpResult = FspNpGetCredentials(
|
||||||
|
hwndOwner, RemoteName, NpResult,
|
||||||
|
CredentialsKind,
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
&Save,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
UserName, sizeof UserName / sizeof UserName[0],
|
||||||
|
Password, sizeof Password / sizeof Password[0]);
|
||||||
|
if (WN_SUCCESS != NpResult)
|
||||||
|
break;
|
||||||
|
|
||||||
|
NpResult = NPAddConnection(lpNetResource, Password, UserName);
|
||||||
|
} while (WN_ACCESS_DENIED == NpResult);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
if (WN_SUCCESS == NpResult && Save)
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential;
|
||||||
|
|
||||||
|
memset(&Credential, 0, sizeof Credential);
|
||||||
|
Credential.Type = CRED_TYPE_GENERIC;
|
||||||
|
Credential.Persist = CRED_PERSIST_LOCAL_MACHINE;
|
||||||
|
Credential.TargetName = RemoteName;
|
||||||
|
Credential.UserName = UserName;
|
||||||
|
Credential.CredentialBlobSize = (lstrlenW(Password) + 1) * sizeof(WCHAR);
|
||||||
|
Credential.CredentialBlob = (PVOID)Password;
|
||||||
|
|
||||||
|
CredWriteW(&Credential, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SecureZeroMemory(Password, sizeof Password);
|
||||||
|
|
||||||
return NpResult;
|
return NpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,16 +42,16 @@ union
|
|||||||
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
||||||
} FspUnmappedSidBuf =
|
} FspUnmappedSidBuf =
|
||||||
{
|
{
|
||||||
/* S-1-5-7 (Anonymous) */
|
/* S-1-0-65534 */
|
||||||
.V.Revision = SID_REVISION,
|
.V.Revision = SID_REVISION,
|
||||||
.V.SubAuthorityCount = 1,
|
.V.SubAuthorityCount = 1,
|
||||||
.V.IdentifierAuthority.Value[5] = 5,
|
.V.IdentifierAuthority.Value[5] = 0,
|
||||||
.V.SubAuthority[0] = 7,
|
.V.SubAuthority[0] = 65534,
|
||||||
};
|
};
|
||||||
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
||||||
|
|
||||||
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
||||||
#define FspUnmappedUid (7)
|
#define FspUnmappedUid (65534)
|
||||||
|
|
||||||
static BOOL WINAPI FspPosixInitialize(
|
static BOOL WINAPI FspPosixInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
@ -223,7 +223,7 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
||||||
* S-1-5-X-RID <=> uid/gid: 0x1000 * X + RID
|
* S-1-5-X-RID <=> uid/gid: 0x1000 * X + RID
|
||||||
*/
|
*/
|
||||||
else if (0x1000 <= Uid && Uid < 0x100000)
|
else if (FspUnmappedUid != Uid && 0x1000 <= Uid && Uid < 0x100000)
|
||||||
*PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff);
|
*PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff);
|
||||||
|
|
||||||
if (0 == *PSid)
|
if (0 == *PSid)
|
||||||
@ -325,7 +325,9 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
|||||||
*/
|
*/
|
||||||
*PUid = 0x60000 + Rid;
|
*PUid = 0x60000 + Rid;
|
||||||
}
|
}
|
||||||
else
|
else if (
|
||||||
|
FspUnmappedSid->IdentifierAuthority.Value[5] != Authority ||
|
||||||
|
FspUnmappedSid->SubAuthority[0] != Rid)
|
||||||
{
|
{
|
||||||
/* [IDMAP]
|
/* [IDMAP]
|
||||||
* Other well-known SIDs:
|
* Other well-known SIDs:
|
||||||
|
@ -54,9 +54,10 @@ static void usage(void)
|
|||||||
"usage: %s COMMAND ARGS\n"
|
"usage: %s COMMAND ARGS\n"
|
||||||
"\n"
|
"\n"
|
||||||
"commands:\n"
|
"commands:\n"
|
||||||
" start ClassName InstanceName Args...\n"
|
" start ClassName InstanceName Args...\n"
|
||||||
" stop ClassName InstanceName\n"
|
" startWithSecret ClassName InstanceName Args... Secret\n"
|
||||||
" info ClassName InstanceName\n"
|
" stop ClassName InstanceName\n"
|
||||||
|
" info ClassName InstanceName\n"
|
||||||
" list\n",
|
" list\n",
|
||||||
PROGNAME);
|
PROGNAME);
|
||||||
}
|
}
|
||||||
@ -115,7 +116,8 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv)
|
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
PWSTR P;
|
PWSTR P;
|
||||||
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
||||||
@ -130,7 +132,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
|||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
P = PipeBuf;
|
P = PipeBuf;
|
||||||
*P++ = LauncherSvcInstanceStart;
|
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||||
@ -230,7 +232,17 @@ int wmain(int argc, wchar_t **argv)
|
|||||||
if (3 > argc || argc > 12)
|
if (3 > argc || argc > 12)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3);
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"startWithSecret", argv[0]))
|
||||||
|
{
|
||||||
|
if (4 > argc || argc > 13)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (0 == lstrcmpW(L"stop", argv[0]))
|
if (0 == lstrcmpW(L"stop", argv[0]))
|
||||||
|
@ -19,7 +19,54 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
|
|
||||||
#define PROGNAME "WinFsp.Launcher"
|
#define PROGNAME "WinFsp.Launcher"
|
||||||
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
#define REGKEY LAUNCHER_REGKEY
|
||||||
|
|
||||||
|
BOOL CreateOverlappedPipe(
|
||||||
|
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||||
|
DWORD ReadMode, DWORD WriteMode)
|
||||||
|
{
|
||||||
|
RPC_STATUS RpcStatus;
|
||||||
|
UUID Uuid;
|
||||||
|
WCHAR PipeNameBuf[MAX_PATH];
|
||||||
|
HANDLE ReadPipe, WritePipe;
|
||||||
|
DWORD LastError;
|
||||||
|
|
||||||
|
RpcStatus = UuidCreate(&Uuid);
|
||||||
|
if (S_OK != RpcStatus && RPC_S_UUID_LOCAL_ONLY != RpcStatus)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INTERNAL_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsprintfW(PipeNameBuf, L"\\\\.\\pipe\\"
|
||||||
|
"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||||
|
Uuid.Data1, Uuid.Data2, Uuid.Data3,
|
||||||
|
Uuid.Data4[0], Uuid.Data4[1], Uuid.Data4[2], Uuid.Data4[3],
|
||||||
|
Uuid.Data4[4], Uuid.Data4[5], Uuid.Data4[6], Uuid.Data4[7]);
|
||||||
|
|
||||||
|
ReadPipe = CreateNamedPipeW(PipeNameBuf,
|
||||||
|
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
|
||||||
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||||
|
1, Size, Size, 120 * 1000, SecurityAttributes);
|
||||||
|
if (INVALID_HANDLE_VALUE == ReadPipe)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
WritePipe = CreateFileW(PipeNameBuf,
|
||||||
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == WritePipe)
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
CloseHandle(ReadPipe);
|
||||||
|
SetLastError(LastError);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PReadPipe = ReadPipe;
|
||||||
|
*PWritePipe = WritePipe;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -80,6 +127,7 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
LONG RefCount;
|
||||||
PWSTR ClassName;
|
PWSTR ClassName;
|
||||||
PWSTR InstanceName;
|
PWSTR InstanceName;
|
||||||
PWSTR CommandLine;
|
PWSTR CommandLine;
|
||||||
@ -87,6 +135,7 @@ typedef struct
|
|||||||
DWORD ProcessId;
|
DWORD ProcessId;
|
||||||
HANDLE Process;
|
HANDLE Process;
|
||||||
HANDLE ProcessWait;
|
HANDLE ProcessWait;
|
||||||
|
HANDLE StdioHandles[2];
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
WCHAR Buffer[];
|
WCHAR Buffer[];
|
||||||
} SVC_INSTANCE;
|
} SVC_INSTANCE;
|
||||||
@ -231,8 +280,132 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||||
|
HANDLE StdioHandles[2],
|
||||||
|
PPROCESS_INFORMATION ProcessInfo)
|
||||||
|
{
|
||||||
|
STARTUPINFOEXW StartupInfoEx;
|
||||||
|
HANDLE ChildHandles[3] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0/* DO NOT CLOSE!*/ };
|
||||||
|
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||||
|
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
|
||||||
|
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
|
||||||
|
SIZE_T Size;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
memset(&StartupInfoEx, 0, sizeof StartupInfoEx);
|
||||||
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||||
|
|
||||||
|
if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Create child process and redirect stdin/stdout. Do *not* inherit other handles.
|
||||||
|
*
|
||||||
|
* For explanation see:
|
||||||
|
* https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* create stdin read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
|
||||||
|
0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create stdout read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
|
||||||
|
FILE_FLAG_OVERLAPPED, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChildHandles[2] = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
Size = 0;
|
||||||
|
if (!InitializeProcThreadAttributeList(0, 1, 0, &Size) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttrList = MemAlloc(Size);
|
||||||
|
if (0 == AttrList)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InitializeProcThreadAttributeList(AttrList, 1, 0, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only the child ends of stdin/stdout are actually inherited */
|
||||||
|
if (!UpdateProcThreadAttribute(AttrList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||||
|
ChildHandles, sizeof ChildHandles, 0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx;
|
||||||
|
StartupInfoEx.lpAttributeList = AttrList;
|
||||||
|
StartupInfoEx.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
StartupInfoEx.StartupInfo.hStdInput = ChildHandles[0];
|
||||||
|
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
||||||
|
StartupInfoEx.StartupInfo.hStdError = ChildHandles[2];
|
||||||
|
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
|
||||||
|
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
|
||||||
|
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[1]);
|
||||||
|
}
|
||||||
|
else if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
StdioHandles[0] = ParentHandles[0];
|
||||||
|
StdioHandles[1] = ParentHandles[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[0])
|
||||||
|
CloseHandle(ChildHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[1])
|
||||||
|
CloseHandle(ChildHandles[1]);
|
||||||
|
|
||||||
|
MemFree(AttrList);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
||||||
|
BOOLEAN RedirectStdio,
|
||||||
SVC_INSTANCE **PSvcInstance)
|
SVC_INSTANCE **PSvcInstance)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = 0;
|
SVC_INSTANCE *SvcInstance = 0;
|
||||||
@ -241,10 +414,9 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
DWORD ClassNameSize, InstanceNameSize;
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
||||||
PWSTR CommandLine, Security;
|
PWSTR CommandLine, Security;
|
||||||
DWORD JobControl;
|
DWORD JobControl, Credentials;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
PWSTR Argv[10];
|
PWSTR Argv[10];
|
||||||
STARTUPINFOW StartupInfo;
|
|
||||||
PROCESS_INFORMATION ProcessInfo;
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -259,7 +431,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
Argv[0] = 0;
|
Argv[0] = 0;
|
||||||
Argc++;
|
Argc++;
|
||||||
|
|
||||||
memset(&StartupInfo, 0, sizeof StartupInfo);
|
|
||||||
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
@ -277,6 +448,22 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegSize = sizeof Credentials;
|
||||||
|
Credentials = 0;
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||||
|
&Credentials, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if ((!RedirectStdio && 0 != Credentials) ||
|
||||||
|
( RedirectStdio && 0 == Credentials))
|
||||||
|
{
|
||||||
|
Result = STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
RegSize = sizeof Executable;
|
RegSize = sizeof Executable;
|
||||||
Executable[0] = L'\0';
|
Executable[0] = L'\0';
|
||||||
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
||||||
@ -336,7 +523,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
//FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
||||||
|
|
||||||
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_START, SecurityDescriptor);
|
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_START, SecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -353,23 +540,23 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(SvcInstance, 0, sizeof *SvcInstance);
|
memset(SvcInstance, 0, sizeof *SvcInstance);
|
||||||
|
SvcInstance->RefCount = 2;
|
||||||
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
||||||
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
||||||
SvcInstance->ClassName = SvcInstance->Buffer;
|
SvcInstance->ClassName = SvcInstance->Buffer;
|
||||||
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
||||||
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
StartupInfo.cb = sizeof StartupInfo;
|
Result = SvcInstanceCreateProcess(Executable, SvcInstance->CommandLine,
|
||||||
if (!CreateProcessW(Executable, SvcInstance->CommandLine, 0, 0, FALSE,
|
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfo, &ProcessInfo))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
|
|
||||||
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
||||||
SvcInstance->Process = ProcessInfo.hProcess;
|
SvcInstance->Process = ProcessInfo.hProcess;
|
||||||
@ -413,6 +600,11 @@ exit:
|
|||||||
|
|
||||||
if (0 != SvcInstance)
|
if (0 != SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
|
|
||||||
@ -435,13 +627,21 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID SvcInstanceDelete(SVC_INSTANCE *SvcInstance)
|
static VOID SvcInstanceRelease(SVC_INSTANCE *SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (0 != InterlockedDecrement(&SvcInstance->RefCount))
|
||||||
|
return;
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
if (RemoveEntryList(&SvcInstance->ListEntry))
|
if (RemoveEntryList(&SvcInstance->ListEntry))
|
||||||
SetEvent(SvcInstanceEvent);
|
SetEvent(SvcInstanceEvent);
|
||||||
LeaveCriticalSection(&SvcInstanceLock);
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
if (0 != SvcInstance->Process)
|
if (0 != SvcInstance->Process)
|
||||||
@ -457,15 +657,92 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
|
|||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = Context;
|
SVC_INSTANCE *SvcInstance = Context;
|
||||||
|
|
||||||
SvcInstanceDelete(SvcInstance);
|
SvcInstanceRelease(SvcInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job)
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance;
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, Job, &SvcInstance);
|
if (HasSecret && (0 == Argc || L'\0' == Argv[Argc - 1][0]))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
HasSecret = !!HasSecret;
|
||||||
|
|
||||||
|
Result = SvcInstanceCreate(ClientToken, ClassName, InstanceName,
|
||||||
|
Argc - HasSecret, Argv, Job, HasSecret,
|
||||||
|
&SvcInstance);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (!HasSecret)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PWSTR Secret = Argv[Argc - 1];
|
||||||
|
UINT8 ReqBuf[256];
|
||||||
|
UINT8 RspBuf[2];
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
OVERLAPPED Overlapped;
|
||||||
|
|
||||||
|
if (0 == (BytesTransferred =
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, Secret, lstrlenW(Secret), ReqBuf, sizeof ReqBuf, 0, 0)))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteFile(SvcInstance->StdioHandles[0], ReqBuf, BytesTransferred, &BytesTransferred, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
memset(&Overlapped, 0, sizeof Overlapped);
|
||||||
|
if (!ReadFile(SvcInstance->StdioHandles[1], RspBuf, sizeof RspBuf, 0, &Overlapped) &&
|
||||||
|
ERROR_IO_PENDING != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResultEx(SvcInstance->StdioHandles[1], &Overlapped, &BytesTransferred,
|
||||||
|
LAUNCHER_START_WITH_SECRET_TIMEOUT, FALSE))
|
||||||
|
{
|
||||||
|
if (WAIT_TIMEOUT == GetLastError())
|
||||||
|
Result = STATUS_TIMEOUT;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
CancelIoEx(SvcInstance->StdioHandles[1], &Overlapped);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeof RspBuf <= BytesTransferred && 'O' == RspBuf[0] && 'K' == RspBuf[1])
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcInstanceRelease(SvcInstance);
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
||||||
@ -625,7 +902,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
&SecurityAttributes.lpSecurityDescriptor, 0))
|
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityAttributes.lpSecurityDescriptor);
|
//FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityAttributes.lpSecurityDescriptor);
|
||||||
|
|
||||||
SvcInstanceEvent = CreateEventW(0, TRUE, TRUE, 0);
|
SvcInstanceEvent = CreateEventW(0, TRUE, TRUE, 0);
|
||||||
if (0 == SvcInstanceEvent)
|
if (0 == SvcInstanceEvent)
|
||||||
@ -909,12 +1186,16 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||||
PWSTR ClassName, InstanceName;
|
PWSTR ClassName, InstanceName;
|
||||||
ULONG Argc; PWSTR Argv[9];
|
ULONG Argc; PWSTR Argv[9];
|
||||||
|
BOOLEAN HasSecret = FALSE;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
*PSize = 0;
|
*PSize = 0;
|
||||||
|
|
||||||
switch (*P++)
|
switch (*P++)
|
||||||
{
|
{
|
||||||
|
case LauncherSvcInstanceStartWithSecret:
|
||||||
|
HasSecret = TRUE;
|
||||||
|
/* fall through! */
|
||||||
case LauncherSvcInstanceStart:
|
case LauncherSvcInstanceStart:
|
||||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
@ -924,7 +1205,8 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
|
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
if (0 != ClassName && 0 != InstanceName)
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob);
|
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob,
|
||||||
|
HasSecret);
|
||||||
|
|
||||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
break;
|
break;
|
||||||
|
@ -21,13 +21,17 @@
|
|||||||
#include <winfsp/winfsp.h>
|
#include <winfsp/winfsp.h>
|
||||||
#include <shared/minimal.h>
|
#include <shared/minimal.h>
|
||||||
|
|
||||||
|
#define LAUNCHER_REGKEY "SYSTEM\\CurrentControlSet\\Services\\WinFsp.Launcher\\Services"
|
||||||
|
|
||||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||||
|
|
||||||
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||||
#define LAUNCHER_PIPE_BUFFER_SIZE 2048
|
#define LAUNCHER_PIPE_BUFFER_SIZE 4096
|
||||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
||||||
|
|
||||||
|
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||||
@ -53,6 +57,7 @@
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||||
|
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||||
|
32
tst/secret/secret.c
Normal file
32
tst/secret/secret.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Compile:
|
||||||
|
* - cl secret.c
|
||||||
|
*
|
||||||
|
* Register:
|
||||||
|
* - secret.reg (fix Executable path first)
|
||||||
|
*
|
||||||
|
* Run:
|
||||||
|
* - launchctl-x64 startWithSecret secret 1 nopass
|
||||||
|
* - launchctl-x64 startWithSecret secret 1 foobar
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char pass[256];
|
||||||
|
|
||||||
|
gets(pass);
|
||||||
|
if (0 == strcmp("foobar", pass))
|
||||||
|
{
|
||||||
|
puts("OK");
|
||||||
|
fprintf(stderr, "OK secret=\"%s\"\n", pass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
puts("KO");
|
||||||
|
fprintf(stderr, "KO secret=\"%s\"\n", pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
tst/secret/secret.reg
Normal file
BIN
tst/secret/secret.reg
Normal file
Binary file not shown.
@ -10,6 +10,7 @@ void posix_map_sid_test(void)
|
|||||||
UINT32 Uid;
|
UINT32 Uid;
|
||||||
} map[] =
|
} map[] =
|
||||||
{
|
{
|
||||||
|
{ L"S-1-0-65534", 65534 },
|
||||||
{ L"S-1-0-0", 0x10000 },
|
{ L"S-1-0-0", 0x10000 },
|
||||||
{ L"S-1-1-0", 0x10100 },
|
{ L"S-1-1-0", 0x10100 },
|
||||||
{ L"S-1-2-0", 0x10200 },
|
{ L"S-1-2-0", 0x10200 },
|
||||||
|
Reference in New Issue
Block a user