From 0f185587c93b7d702287f58878abf18512063a7a Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 29 Nov 2018 21:05:57 -0800 Subject: [PATCH] dll: np: implement custom Credential Provider logic --- build/VStudio/winfsp_dll.vcxproj | 8 +-- inc/winfsp/launch.h | 6 +- src/dll/launch.c | 7 ++ src/dll/np.c | 107 +++++++++++++++++++++++++------ 4 files changed, 103 insertions(+), 25 deletions(-) diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index a2c13545..661bec99 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -222,7 +222,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf $(OutDir)$(TargetFileName).map false ..\..\src\dll\library.def - %(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib + %(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib $(OutDir)$(TargetFileName).public.pdb @@ -250,7 +250,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf $(OutDir)$(TargetFileName).map true ..\..\src\dll\library.def - %(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib + %(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib $(OutDir)$(TargetFileName).public.pdb @@ -281,7 +281,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf $(OutDir)$(TargetFileName).map false ..\..\src\dll\library.def - %(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib + %(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib $(OutDir)$(TargetFileName).public.pdb @@ -312,7 +312,7 @@ copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(Platf $(OutDir)$(TargetFileName).map true ..\..\src\dll\library.def - %(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib + %(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib $(OutDir)$(TargetFileName).public.pdb diff --git a/inc/winfsp/launch.h b/inc/winfsp/launch.h index 1ee53547..14a4d31e 100644 --- a/inc/winfsp/launch.h +++ b/inc/winfsp/launch.h @@ -286,10 +286,12 @@ typedef struct _FSP_LAUNCH_REG_RECORD PWSTR WorkDirectory; PWSTR RunAs; PWSTR Security; - PVOID Reserved0[6]; + PWSTR AuthPackage; + PVOID Reserved0[5]; ULONG JobControl; ULONG Credentials; - ULONG Reserved1[6]; + ULONG AuthPackageId; + ULONG Reserved1[5]; UINT8 Buffer[]; } FSP_LAUNCH_REG_RECORD; #pragma warning(pop) diff --git a/src/dll/launch.c b/src/dll/launch.c index adb343fb..b79a1b46 100644 --- a/src/dll/launch.c +++ b/src/dll/launch.c @@ -270,8 +270,10 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( SETFIELD(WorkDirectory); SETFIELD(RunAs); SETFIELD(Security); + SETFIELD(AuthPackage); SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */ SETFIELDI(Credentials, 0); + SETFIELDI(AuthPackageId, 0); } else { @@ -420,8 +422,10 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( GETFIELD(WorkDirectory); GETFIELD(RunAs); GETFIELD(Security); + GETFIELD(AuthPackage); GETFIELDI(JobControl); GETFIELDI(Credentials); + GETFIELDI(AuthPackageId); if (0 == Record->Executable) { @@ -450,8 +454,11 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0; Record->Security = 0 != RecordBuf.Security ? (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0; + Record->AuthPackage = 0 != RecordBuf.AuthPackage ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.AuthPackage - RegBuf)) : 0; Record->JobControl = RecordBuf.JobControl; Record->Credentials = RecordBuf.Credentials; + Record->AuthPackageId = RecordBuf.AuthPackageId; *PRecord = Record; Result = STATUS_SUCCESS; diff --git a/src/dll/np.c b/src/dll/np.c index 9d96b482..95824460 100644 --- a/src/dll/np.c +++ b/src/dll/np.c @@ -23,6 +23,9 @@ #include #include +#define _NTDEF_ +#include + #define FSP_NP_NAME LIBRARY_NAME ".Np" #define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */ #define FSP_NP_ADDCONNECTION_TIMEOUT 15000 @@ -253,8 +256,50 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName) return 0; } +static NTSTATUS FspNpGetAuthPackage(PWSTR AuthPackageName, PULONG PAuthPackage) +{ + HANDLE LsaHandle; + BOOLEAN LsaHandleValid = FALSE; + CHAR LsaAuthPackageNameBuf[127]; /* "The package name must not exceed 127 bytes in length." */ + LSA_STRING LsaAuthPackageName; + ULONG AuthPackage; + NTSTATUS Result; + + *PAuthPackage = 0; + + Result = LsaConnectUntrusted(&LsaHandle); + if (!NT_SUCCESS(Result)) + goto exit; + LsaHandleValid = TRUE; + + LsaAuthPackageName.MaximumLength = sizeof LsaAuthPackageNameBuf; + LsaAuthPackageName.Buffer = LsaAuthPackageNameBuf; + LsaAuthPackageName.Length = WideCharToMultiByte(CP_UTF8, 0, + AuthPackageName, lstrlenW(AuthPackageName), + LsaAuthPackageNameBuf, sizeof LsaAuthPackageNameBuf, + 0, 0); + if (0 == LsaAuthPackageName.Length) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + Result = LsaLookupAuthenticationPackage(LsaHandle, &LsaAuthPackageName, &AuthPackage); + if (!NT_SUCCESS(Result)) + goto exit; + + *PAuthPackage = AuthPackage; + Result = STATUS_SUCCESS; + +exit: + if (LsaHandleValid) + LsaDeregisterLogonProcess(LsaHandle); + + return Result; +} + static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, - PDWORD PCredentialsKind, PBOOLEAN PAllowImpersonation) + PDWORD PAuthPackage, PDWORD PCredentialsKind, PBOOLEAN PAllowImpersonation) { PWSTR ClassName, InstanceName; ULONG ClassNameLen, InstanceNameLen; @@ -262,8 +307,14 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, FSP_LAUNCH_REG_RECORD *Record; NTSTATUS Result; - *PCredentialsKind = FSP_NP_CREDENTIALS_NONE; - *PAllowImpersonation = FALSE; + if (0 != PAuthPackage) + *PAuthPackage = 0; + + if (0 != PCredentialsKind) + *PCredentialsKind = FSP_NP_CREDENTIALS_NONE; + + if (0 != PAllowImpersonation) + *PAllowImpersonation = FALSE; if (!FspNpParseRemoteName(RemoteName, &ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen)) @@ -278,17 +329,35 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, if (!NT_SUCCESS(Result)) return WN_NO_NETWORK; - switch (Record->Credentials) + if (0 != PAuthPackage) { - case FSP_NP_CREDENTIALS_NONE: - case FSP_NP_CREDENTIALS_PASSWORD: - case FSP_NP_CREDENTIALS_USERPASS: - *PCredentialsKind = Record->Credentials; - break; + if (0 != Record->AuthPackage) + { + ULONG AuthPackage = 0; + + Result = FspNpGetAuthPackage(Record->AuthPackage, &AuthPackage); + if (!NT_SUCCESS(Result)) + return WN_NO_NETWORK; + + *PAuthPackage = AuthPackage + 1; /* ensure non-0 (Negotiate AuthPackage == 0) */ + } + else if (0 != Record->AuthPackageId) + *PAuthPackage = Record->AuthPackageId + 1; /* ensure non-0 (Negotiate AuthPackage == 0) */ } - *PAllowImpersonation = 0 != Record->RunAs && - L'.' == Record->RunAs[0] && L'\0' == Record->RunAs[1]; + if (0 != PCredentialsKind) + switch (Record->Credentials) + { + case FSP_NP_CREDENTIALS_NONE: + case FSP_NP_CREDENTIALS_PASSWORD: + case FSP_NP_CREDENTIALS_USERPASS: + *PCredentialsKind = Record->Credentials; + break; + } + + if (0 != PAllowImpersonation) + *PAllowImpersonation = 0 != Record->RunAs && + L'.' == Record->RunAs[0] && L'\0' == Record->RunAs[1]; FspLaunchRegFreeRecord(Record); @@ -297,7 +366,7 @@ static DWORD FspNpGetRemoteInfo(PWSTR RemoteName, static DWORD FspNpGetCredentials( HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult, - DWORD CredentialsKind, + DWORD AuthPackage0, DWORD CredentialsKind, PBOOL PSave, PWSTR UserName, ULONG UserNameSize/* in chars */, PWSTR Password, ULONG PasswordSize/* in chars */) @@ -324,7 +393,7 @@ static DWORD FspNpGetCredentials( (FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0)); #else WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1]; - ULONG AuthPackage = 0; + ULONG AuthPackage = 0 != AuthPackage0 ? AuthPackage0 - 1 : 0; PVOID InAuthBuf = 0, OutAuthBuf = 0; ULONG InAuthSize, OutAuthSize, DomainSize; @@ -353,7 +422,8 @@ static DWORD FspNpGetCredentials( NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult, &AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave, - CREDUIWIN_GENERIC | (0 != PSave ? CREDUIWIN_CHECKBOX : 0)); + (0 != AuthPackage0 ? CREDUIWIN_AUTHPACKAGE_ONLY : CREDUIWIN_GENERIC) | + (0 != PSave ? CREDUIWIN_CHECKBOX : 0)); if (ERROR_SUCCESS != NpResult) goto exit; @@ -501,7 +571,7 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, return WN_ALREADY_CONNECTED; } - NpResult = FspNpGetRemoteInfo(lpRemoteName, &CredentialsKind, &AllowImpersonation); + NpResult = FspNpGetRemoteInfo(lpRemoteName, 0, &CredentialsKind, &AllowImpersonation); if (WN_SUCCESS != NpResult) return NpResult; @@ -669,8 +739,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner, { DWORD NpResult; PWSTR RemoteName = lpNetResource->lpRemoteName; - DWORD CredentialsKind; - BOOLEAN AIDummy; + DWORD AuthPackage, CredentialsKind; WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1]; #if defined(FSP_NP_CREDENTIAL_MANAGER) BOOL Save = TRUE; @@ -690,7 +759,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner, return NpResult; } - NpResult = FspNpGetRemoteInfo(RemoteName, &CredentialsKind, &AIDummy); + NpResult = FspNpGetRemoteInfo(RemoteName, &AuthPackage, &CredentialsKind, 0); if (WN_SUCCESS != NpResult) return NpResult; if (FSP_NP_CREDENTIALS_NONE == CredentialsKind) @@ -706,7 +775,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner, { NpResult = FspNpGetCredentials( hwndOwner, RemoteName, NpResult, - CredentialsKind, + AuthPackage, CredentialsKind, #if defined(FSP_NP_CREDENTIAL_MANAGER) &Save, #else