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

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

我正在建立一个凭据提供程序,其工作方式与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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-