Я пытаюсь реализовать локальный вход в систему из своего пользовательского провайдера учетных данных. Для этого я пытаюсь использовать пакет аутентификации MSV1_0
, но он продолжает отказывать, давая статус INVALID_PARAMETER
.
Код выглядит так:
static void _UnicodeStringPackedUnicodeStringCopy(
const UNICODE_STRING& rus,
PWSTR pwzBuffer,
UNICODE_STRING* pus
) {
pus->Length = rus.Length;
pus->MaximumLength = rus.Length;
pus->Buffer = pwzBuffer;
CopyMemory(pus->Buffer, rus.Buffer, pus->Length);
}
HRESULT LsaInitStringW(PUNICODE_STRING pszDestinationString, PCWSTR pszSourceString)
{
size_t cchLength;
HRESULT hr = StringCchLengthW(pszSourceString, USHORT_MAX, &cchLength);
if (SUCCEEDED(hr))
{
USHORT usLength;
hr = SizeTToUShort(cchLength, &usLength);
if (SUCCEEDED(hr))
{
pszDestinationString->Buffer = (PWCHAR)pszSourceString;
pszDestinationString->Length = usLength * sizeof(WCHAR);
pszDestinationString->MaximumLength = pszDestinationString->Length + 1;
hr = S_OK;
}
}
return hr;
}
HRESULT MsvLogonPack(
const MSV1_0_INTERACTIVE_LOGON& milIn,
BYTE** prgb,
DWORD* pcb
) {
size_t cb = sizeof(milIn)
+ milIn.LogonDomainName.Length
+ milIn.UserName.Length
+ milIn.Password.Length;
MSV1_0_INTERACTIVE_LOGON* milOut = (MSV1_0_INTERACTIVE_LOGON*)CoTaskMemAlloc(cb);
if (!milOut) {
return E_OUTOFMEMORY;
}
milOut->MessageType = milIn.MessageType;
BYTE *pbBuffer = (BYTE*)milOut + sizeof(*milOut);
_UnicodeStringPackedUnicodeStringCopy(milIn.LogonDomainName, (PWSTR)pbBuffer, &milOut->LogonDomainName);
pbBuffer += milOut->LogonDomainName.Length;
_UnicodeStringPackedUnicodeStringCopy(milIn.UserName, (PWSTR)pbBuffer, &milOut->UserName);
pbBuffer += milOut->UserName.Length;
_UnicodeStringPackedUnicodeStringCopy(milIn.Password, (PWSTR)pbBuffer, &milOut->Password);
pbBuffer += milOut->Password.Length;
if (pbBuffer != (BYTE*)milOut + cb) {
return E_ABORT;
}
*prgb = (BYTE*)milOut;
*pcb = cb;
return S_OK;
}
HRESULT GetMsvPackage(ULONG * pulAuthPackage) {
HRESULT hr;
HANDLE hLsa;
NTSTATUS status = LsaConnectUntrusted(&hLsa);
if (SUCCEEDED(HRESULT_FROM_NT(status))) {
ULONG ulAuthPackage;
LSA_STRING lsaszKerberosName;
LsaInitString(&lsaszKerberosName, MSV1_0_PACKAGE_NAME);
status = LsaLookupAuthenticationPackage(hLsa, &lsaszKerberosName, &ulAuthPackage);
if (SUCCEEDED(HRESULT_FROM_NT(status))) {
*pulAuthPackage = ulAuthPackage;
hr = S_OK;
}
else {
hr = HRESULT_FROM_NT(status);
}
LsaDeregisterLogonProcess(hLsa);
}
else {
hr = HRESULT_FROM_NT(status);
}
return hr;
}
HRESULT MyCredential::CompleteAuthentication(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,
PWSTR* ppwszOptionalStatusText,
CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon) {
HRESULT hr;
pcpcs->clsidCredentialProvider = CLSID_MyProvider;
MSV1_0_INTERACTIVE_LOGON mil;
mil.MessageType = MsV1_0WorkstationUnlockLogon;
hr = LsaInitStringW(&mil.LogonDomainName, L"");
if (SUCCEEDED(hr)) hr = LsaInitStringW(&mil.UserName, L"tester");
if (SUCCEEDED(hr)) hr = LsaInitStringW(&mil.Password, L"12345");
if (SUCCEEDED(hr)) {
hr = MsvLogonPack(mil, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
if (SUCCEEDED(hr)) {
ULONG ulAuthPackage;
hr = GetMsvPackage(&ulAuthPackage);
if (SUCCEEDED(hr)) {
pcpcs->ulAuthenticationPackage = ulAuthPackage;
}
}
}
return hr;
}
Это продолжает давать статус INVALID_PARAMETER
с под-статусом 0. Я попытался заменить MsV1_0InteractiveLogon
на MsV1_0WorkstationUnlockLogon
, что дало мне статус STATUS_LOGON_FAILURE
с под-статусом INTERNAL_ERROR
.
Что бы предложить решить эту проблему?