如何序列化智能卡凭据提供程序中用于域帐户登录和解锁的凭据?

问题描述

我正在建立一个凭据提供程序,其工作方式与Windows智能卡凭据提供程序相同,即,仅适用于域帐户。将凭据传递到Negotiate ssp时遇到问题,并且我使用Microsoft基本智能卡加密提供程序作为CSP。输入密码后,锁定屏幕上出现The parameter is incorrect错误

GetSerialization

HRESULT CCredential::GetSerialization(
    CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,PWSTR* ppwszOptionalStatusText,CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
)
{
    UNREFERENCED_ParaMETER(ppwszOptionalStatusText);
    UNREFERENCED_ParaMETER(pcpsiOptionalStatusIcon);
    HRESULT hr;
    WCHAR dmz[244] = L"demodomain";

        PWSTR pwzProtectedPin;

        hr = ProtectIfNecessaryAndcopyPassword(_rgFieldStrings[SFI_PIN],_cpus,_dwFlags,&pwzProtectedPin);

        if (SUCCEEDED(hr))
        {
            KERB_CERTIFICATE_UNLOCK_logoN kiul;

            // Initialize kiul with weak references to our credential.
            hr = UnlocklogonInit(dmz,_rgFieldStrings[SFI_USERNAME],pwzProtectedPin,&kiul);

            if (SUCCEEDED(hr))
            {
                PBASE_SMARTCARD_CSP_INFO pCspInfo = _pContainer->GetCSPInfo();
                if (pCspInfo)
                {
                    CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcp;

                    hr = UnlocklogonPack(kiul,pCspInfo,&pcpcs->rgbSerialization,&pcpcs->cbSerialization);
                    _pContainer->FreeCSPInfo(pCspInfo);

                    if (SUCCEEDED(hr))
                    {
                        ULONG ulAuthPackage;

                        hr = RetrieveNegotiateAuthPackage(&ulAuthPackage);
                        if (SUCCEEDED(hr))
                        {
                            pcpcs->ulAuthenticationPackage = ulAuthPackage;
                            pcpcs->clsidCredentialProvider = CLSID_CProvider;

                            // At this point the credential has created the serialized credential used for logon
                            // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI kNow
                            // that we have all the information we need and it should attempt to submit the 
                            // serialized credential.
                            *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
                        }
                        else
                        {
                            PrintLn(WINEVENT_LEVEL_WARNING,L"RetrieveNegotiateAuthPackage not SUCCEEDED hr=0x%08x",hr);
                        }
                    }
                    else
                    {
                        PrintLn(WINEVENT_LEVEL_WARNING,L"UnlocklogonPack not SUCCEEDED hr=0x%08x",hr);
                    }
                }
                else
                {
                    PrintLn(WINEVENT_LEVEL_WARNING,L"pCspInfo NULL");
                }
            }
            else
            {
                PrintLn(WINEVENT_LEVEL_WARNING,L"UnlocklogonInit not SUCCEEDED hr=0x%08x",hr);
            }
            CoTaskMemFree(pwzProtectedPin);
        }
        else
        {
            PrintLn(WINEVENT_LEVEL_WARNING,L"ProtectIfNecessaryAndcopyPassword not SUCCEEDED hr=0x%08x",hr);
        }
    
    if (!SUCCEEDED(hr))
    {
        PrintLn(WINEVENT_LEVEL_WARNING,L"not SUCCEEDED hr=0x%08x",hr);
    }
    else
    {
        PrintLn(WINEVENT_LEVEL_WARNING,L"OK");
    }
    return hr;
}

UnlocklogonInit

HRESULT UnlocklogonInit(
                                       PWSTR pwzDomain,PWSTR pwzUsername,PWSTR pwzPin,CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,KERB_CERTIFICATE_UNLOCK_logoN* pkiul
                                       )
{
    UNREFERENCED_ParaMETER(cpus);
    KERB_CERTIFICATE_UNLOCK_logoN kiul;
    ZeroMemory(&kiul,sizeof(kiul));

    KERB_CERTIFICATE_logoN* pkil = &kiul.logon;

    HRESULT hr = UnicodeStringInitWithString(pwzDomain,&pkil->logonDomainName);

    if (SUCCEEDED(hr))
    {
        hr = UnicodeStringInitWithString(pwzUsername,&pkil->UserName);

        if (SUCCEEDED(hr))
        {
            hr = UnicodeStringInitWithString(pwzPin,&pkil->Pin);
            
            if (SUCCEEDED(hr))
            {
                // Set a MessageType based on the usage scenario.
                pkil->MessageType = KerbCertificatelogon; //13
                pkil->CspDataLength = 0;
                pkil->CspData = NULL;
                pkil->Flags = 0;

                if (SUCCEEDED(hr))
                {
                    // KERB_INteraCTIVE_UNLOCK_logoN is just a series of structures.  A
                    // flat copy will properly initialize the output parameter.
                    copyMemory(pkiul,&kiul,sizeof(*pkiul));
                }
            }
        }
    }

    return hr;
}

UnlocklogonPack

HRESULT UnlocklogonPack(
                                       const KERB_CERTIFICATE_UNLOCK_logoN& rkiulIn,const PBASE_SMARTCARD_CSP_INFO pCspInfo,BYTE** prgb,DWORD* pcb
                                       )
{
    HRESULT hr;

    const KERB_CERTIFICATE_logoN* pkilIn = &rkiulIn.logon;

    // alloc space for struct plus extra for the three strings
    DWORD cb = sizeof(rkiulIn) +
        pkilIn->logonDomainName.Length +
        pkilIn->UserName.Length +
        pkilIn->Pin.Length +
        pCspInfo->dwCspInfoLen;


    KERB_CERTIFICATE_UNLOCK_logoN* pkiulOut = (KERB_CERTIFICATE_UNLOCK_logoN*)CoTaskMemAlloc(cb);

    if (pkiulOut)
    {
        ZeroMemory(&pkiulOut->logonId,sizeof(LUID));

        //
        // point pbBuffer at the beginning of the extra space
        //
        BYTE* pbBuffer = (BYTE*)pkiulOut + sizeof(*pkiulOut);


        KERB_CERTIFICATE_logoN* pkilOut = &pkiulOut->logon;

        pkilOut->MessageType = pkilIn->MessageType;
        pkilOut->Flags = pkilIn->Flags;

        //
        // copy each string,// fix up appropriate buffer pointer to be offset,// advance buffer pointer over copied characters in extra space
        //
        _UnicodeStringPackedUnicodeStringcopy(pkilIn->logonDomainName,(PWSTR)pbBuffer,&pkilOut->logonDomainName);
        pkilOut->logonDomainName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut);
        pbBuffer += pkilOut->logonDomainName.Length;

        _UnicodeStringPackedUnicodeStringcopy(pkilIn->UserName,&pkilOut->UserName);
        pkilOut->UserName.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut);
        pbBuffer += pkilOut->UserName.Length;

        _UnicodeStringPackedUnicodeStringcopy(pkilIn->Pin,&pkilOut->Pin);
        pkilOut->Pin.Buffer = (PWSTR)(pbBuffer - (BYTE*)pkiulOut);
        pbBuffer += pkilOut->Pin.Length;

        pkilOut->CspData = (PUCHAR) (pbBuffer - (BYTE*)pkiulOut);
        pkilOut->CspDataLength = pCspInfo->dwCspInfoLen;

        memcpy(pbBuffer,pCspInfo->dwCspInfoLen);

        *prgb = (BYTE*)pkiulOut;
        *pcb = cb;

        hr = S_OK;
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }

    return hr;
}

_KERB_SMARTCARD_CSP_INFO结构和GetCSPInfo


// based on _KERB_SMARTCARD_CSP_INFO 
typedef struct _BASE_SMARTCARD_CSP_INFO 
{
  DWORD dwCspInfoLen;
  DWORD MessageType;
  union {
    PVOID Contextinformation;
    ULONG64 SpaceHolderForWow64;
  } ;
  DWORD flags;
  DWORD KeySpec;
  ULONG nCardNameOffset;
  ULONG nReaderNameOffset;
  ULONG nContainerNameOffset;
  ULONG nCSPNameOffset;
  TCHAR bBuffer[sizeof(DWORD)];
} BASE_SMARTCARD_CSP_INFO,*PBASE_SMARTCARD_CSP_INFO;

PBASE_SMARTCARD_CSP_INFO CContainer::GetCSPInfo()
{
//szreaderName,szCardname,szproviderName,szContainerName are initialized with respective values in constructor
    _ASSERTE( _CrtCheckMemory( ) );
    DWORD dwReaderLen = (DWORD) _tcslen(_szReaderName)+1;
    DWORD dwCardLen = (DWORD) _tcslen(_szCardName)+1;
    DWORD dwProviderLen = (DWORD) _tcslen(_szProviderName)+1;
    DWORD dwContainerLen = (DWORD) _tcslen(_szContainerName)+1;
    DWORD dwBufferSize = dwReaderLen + dwCardLen + dwProviderLen + dwContainerLen;

    PBASE_SMARTCARD_CSP_INFO pCspInfo = (PBASE_SMARTCARD_CSP_INFO) BASEAlloc(sizeof(BASE_SMARTCARD_CSP_INFO)+dwBufferSize*sizeof(TCHAR));
    if (!pCspInfo) return NULL;
    //ZeroMemory(pCspInfo);
    memset(pCspInfo,sizeof(BASE_SMARTCARD_CSP_INFO));
    pCspInfo->dwCspInfoLen = sizeof(BASE_SMARTCARD_CSP_INFO)+dwBufferSize*sizeof(TCHAR);
    pCspInfo->MessageType = 1;
    pCspInfo->KeySpec = _KeySpec;
    pCspInfo->nCardNameOffset = ARRAYSIZE(pCspInfo->bBuffer);
    pCspInfo->nReaderNameOffset = pCspInfo->nCardNameOffset + dwCardLen;
    pCspInfo->nContainerNameOffset = pCspInfo->nReaderNameOffset + dwReaderLen;
    pCspInfo->nCSPNameOffset = pCspInfo->nContainerNameOffset + dwContainerLen;
    memset(pCspInfo->bBuffer,sizeof(pCspInfo->bBuffer));
    _tcscpy_s(&pCspInfo->bBuffer[pCspInfo->nCardNameOffset],dwBufferSize + 4 - pCspInfo->nCardNameOffset,_szCardName);
    _tcscpy_s(&pCspInfo->bBuffer[pCspInfo->nReaderNameOffset],dwBufferSize + 4 - pCspInfo->nReaderNameOffset,_szReaderName);
    _tcscpy_s(&pCspInfo->bBuffer[pCspInfo->nContainerNameOffset],dwBufferSize + 4 - pCspInfo->nContainerNameOffset,_szContainerName);
    _tcscpy_s(&pCspInfo->bBuffer[pCspInfo->nCSPNameOffset],dwBufferSize + 4 - pCspInfo->nCSPNameOffset,_szProviderName);
    _ASSERTE( _CrtCheckMemory( ) );
    return pCspInfo;
}

我不知道我在哪里做错了,现在被困在这里了一段时间。任何帮助将不胜感激。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)