Reputation: 165
I am developing a C# implementation of custom credential provider. It's working with no problems on interactive sessions. However, when i try to connect that computer with RDP (mstsc), It gives an error message after credentials are serialized. Message is:
"An authentication error has occurred. The token supplied to the function is invalid.". In my server, GetSeralization method is like below;
public override int GetSerialization(out _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE pcpgsr, out _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcs, out string ppszOptionalStatusText, out _CREDENTIAL_PROVIDER_STATUS_ICON pcpsiOptionalStatusIcon)
{
pcpgsr = _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE.CPGSR_NO_CREDENTIAL_NOT_FINISHED;
pcpcs = new _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION();
ppszOptionalStatusText = "";
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_NONE;
var otpResult = DialogResult.Yes;
// make OTP operation here
if (otpResult == DialogResult.Yes)
{
CredHelper.Instance.RetrieveNegotiateAuthPackage(out var authPackage);
var userNameField = credentialView.GetField(FieldTypeEnum.UsernameField);
var passwordField = credentialView.GetField(FieldTypeEnum.PasswordField);
var userNameSplitted = userNameField.Value.SplitSpecial('\\');
if (userNameSplitted.Count <= 1)
{
ppszOptionalStatusText = "Failed to pack credentials";
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_ERROR;
return HResult.Fail;
}
pcpgsr = _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE.CPGSR_RETURN_CREDENTIAL_FINISHED;
pcpcs = new _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION();
NativeLogon.KerbInteractiveUnlockLogonInit(userNameSplitted.First(), userNameSplitted.Last(), passwordField.Value, (int)usageScenario, out KerbInteractiveUnlockLogon pkiul);
NativeLogon.KerbInteractiveUnlockLogonPack(ref pkiul, out IntPtr inCredBuffer, out int inCredSize);
ppszOptionalStatusText = string.Empty;
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_SUCCESS;
pcpcs.clsidCredentialProvider = Statics.CredentialProviderGuid;
pcpcs.rgbSerialization = inCredBuffer;
pcpcs.cbSerialization = (uint)inCredSize;
pcpcs.ulAuthenticationPackage = authPackage;
return HResult.Ok;
}
ppszOptionalStatusText = "Failed to pack credentials";
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_ERROR;
return HResult.Fail;
}
My ICredentialProviderFilter
implementation is below but I think its wrong
public int UpdateRemoteCredential(ref _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcsIn, out _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcsOut)
{
pcpcsOut = pcpcsIn;
return HResult.Ok;
}
I am stuck here. I cannot go forward. Thanks.
Upvotes: 3
Views: 322
Reputation: 165
I solved the problem by changing C++ helper library for credential pack. In CredUI scenario, Kerberos ticket was incorrect. It should be like below;
switch (scenario)
{
case 1: //CPUS_LOGON
pkil->MessageType = KerbInteractiveLogon;
hr = S_OK;
break;
case 2: //CPUS_UNLOCK_WORKSTATION
pkil->MessageType = KerbWorkstationUnlockLogon;
hr = S_OK;
break;
case 4: //CPUS_CREDUI
pkil->MessageType = KerbInteractiveLogon;
hr = S_OK;
break;
default:
hr = E_FAIL;
break;
}
Now i can connect to remote machine.
Upvotes: 2