Удаленный вход в систему провайдера учетных данных Windows
Я пытаюсь прочитать учетные данные со смарт-карты на одной рабочей станции (локальной), а затем отправить ее на другую рабочую станцию (удаленную) и использовать ее для входа на эту рабочую станцию из провайдера учетных данных.
Я искал и изучал уже несколько недель, но не нашел никого, кто бы показывал или рассказывал, как это сделать.
Я нашел несколько ссылок на отличную работу по адресу https://www.idrix.fr/Root/Samples/LsaSmartCardLogon2.cpp, который является рабочим кодом для поставщика учетных данных смарт-карт, но, к сожалению, требует, чтобы поставщик учетных данных имел прямой доступ к смарт-карта с учетными данными на нем.
Фактический код, с которым я работаю, кажется, слишком длинным для включения в пост, поэтому я решил попробовать задать вопрос с использованием кода sudo. На локальной рабочей станции:
MySendCredentialsFromSmartCard(){
CryptAcquireContext(hProv, containerName, cardName, PROV_RSA_FULL, CRYPT_SILENT)
CryptGetUserKey(*hProv, AT_KEYEXCHANGE, &hCryptKey);
CryptGetKeyParam(hCryptKey, KP_CERTIFICATE, encodedCert, &size, 0);
MySendCertToRemote(encodedCert,size);
}
На удаленной рабочей станции, работающей в провайдере пользовательских учетных данных:
HRESULT CSampleCredential::GetSerialization(
_Out_ CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpgsr,
_Out_ CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs,
_Outptr_result_maybenull_ PWSTR *ppwszOptionalStatusText,
_Out_ CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon){
MyReadCertFromRemote(&cert,&size);
CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
CryptCreateHash(hCryptProv, CALG_SHA1, NULL, 0, &hHash);
CryptHashData(hHash, (BYTE *)cert, (DWORD)size, 0);
CERT_CREDENTIAL_INFO certInfo;
CryptGetHashParam(hHash, HP_HASHVAL, certInfo.rgbHashOfCert, &dwHashLen, 0);
CredMarshalCredential(CertCredential, &certInfo, marshalledCred);
/****************************for debug only*****************************/
LogonUser((*marshalledCred, NULL, NULL, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &userHandle);
//this reuturns 1 (success)
/**************************************************************************/
KERB_INTERACTIVE_UNLOCK_LOGON kiul;
CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus
KerbInteractiveUnlockLogonInit(L"", (PWSTR)marshaledCred, L"", cpus, &kiul);//(note:I've tried this with the third param set to the card's pin)
KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
RetrieveNegotiateAuthPackage(&ulAuthPackage);
pcpcs->ulAuthenticationPackage = ulAuthPackage;
pcpcs->clsidCredentialProvider = CLSID_OfProvider;
*pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
}
LogonUI.exe отображает "Указанный сеанс входа в систему не существует. Возможно, он уже был прерван". Это похоже на код ошибки Windows 1312. Кажется, что большинство разработчиков, борющихся с этим кодом ошибки, испытывают трудности при настройке IIS с сертификатом SSL. Я не нашел ссылки на эту ошибку в отношении поставщика учетных данных. Кажется, что различные потоки указывают, что LogonUser - просто оболочка вокруг LSALogonUser, и возвращенные значения из ICredentialProviderCredential::GetSerialization будут переданы LSALogonUser. Тот факт, что мой звонок в LogonUser с маршализованными учетными данными успешен, может показаться, что я на правильном пути, но я не смог ни это проверить, ни выяснить, что мне не хватает. Я хотел бы попытаться избежать решений, которые требуют хранения учетных данных на удаленной рабочей станции, поскольку это, как правило, учетные данные администратора домена. Есть идеи кто-нибудь? Любой совет, как поступить?
Спасибо
1 ответ
Я полагаю, что вы можете сделать это, используя механизм связи, при котором вы отправляете свои данные с одной рабочей станции на другую, а на удаленной вы сериализуете свои данные в SetSerialization() вместо GetSerialization(), подготавливая все поля и обрабатывая вход в систему.
С моей точки зрения, класс Provider (наследуемый ICredentialProvider) должен каким-то образом ждать эти учетные данные и передавать их в SetSerialization.