Winapi SSPI WDigest服务器可用性故障

Winapi SSPI WDigest服务器可用性故障,winapi,sspi,Winapi,Sspi,我正在尝试使用Win32 SSPI API来验证来自客户端的。对的调用始终失败,并出现SEC_E_无效令牌(0x80090308)或SEC_E_内部错误(0x80090304) 我已将问题简化为以下示例代码: #define SECURITY_WIN32 #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <security.h> #include <wdigest.h> #include <

我正在尝试使用Win32 SSPI API来验证来自客户端的。对的调用始终失败,并出现SEC_E_无效令牌(0x80090308)或SEC_E_内部错误(0x80090304)

我已将问题简化为以下示例代码:

#define SECURITY_WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <security.h>
#include <wdigest.h>
#include <cstdlib>
#include <string>
#include <iostream>

#pragma comment(lib, "Secur32.lib")

using namespace std::string_literals;

int main()
{
    auto const realm = L"realm"s;
    auto const client_method = "GET"s;
    auto const client_target = L"HTTP/TARGETMACHINE"s;
    auto const client_uri = L"/"s;
    auto const client_uri_utf8 = "/"s;

    // server generate digest challenge
    PSecPkgInfoW package_info;
    auto result = QuerySecurityPackageInfoW(const_cast<LPWSTR>(WDIGEST_SP_NAME_W), &package_info);
    if (result != SEC_E_OK) 
    {
        return EXIT_FAILURE;
    }

    CredHandle serverCredHandle;
    TimeStamp lifetime;
    result = AcquireCredentialsHandleW(nullptr, const_cast<LPWSTR>(WDIGEST_SP_NAME_W), SECPKG_CRED_INBOUND, nullptr, nullptr, nullptr, nullptr, &serverCredHandle, &lifetime);
    if (result != SEC_E_OK)
    {
        return EXIT_FAILURE;
    }

    SecBuffer challengeInBuffers[5];

    // token
    challengeInBuffers[0].BufferType = SECBUFFER_TOKEN;
    challengeInBuffers[0].cbBuffer = 0;
    challengeInBuffers[0].pvBuffer = nullptr;

    // method
    challengeInBuffers[1].BufferType = SECBUFFER_PKG_PARAMS;
    challengeInBuffers[1].cbBuffer = 0;
    challengeInBuffers[1].pvBuffer = nullptr;

    // uri
    challengeInBuffers[2].BufferType = SECBUFFER_PKG_PARAMS;
    challengeInBuffers[2].cbBuffer = 0;
    challengeInBuffers[2].pvBuffer = nullptr;

    // body hash
    challengeInBuffers[3].BufferType = SECBUFFER_PKG_PARAMS;
    challengeInBuffers[3].cbBuffer = 0;
    challengeInBuffers[3].pvBuffer = nullptr;

    // realm
    challengeInBuffers[4].BufferType = SECBUFFER_PKG_PARAMS;
    challengeInBuffers[4].cbBuffer = realm.size() * sizeof(wchar_t);
    challengeInBuffers[4].pvBuffer = const_cast<void*>(static_cast<void const*>(realm.c_str()));

    SecBufferDesc challengeInBufferDesc;

    challengeInBufferDesc.ulVersion = 0;
    challengeInBufferDesc.cBuffers = 5;
    challengeInBufferDesc.pBuffers  = challengeInBuffers;

    std::string challenge;
    challenge.resize(package_info->cbMaxToken);

    SecBuffer challengeOutBuffer;
    challengeOutBuffer.BufferType = SECBUFFER_TOKEN;
    challengeOutBuffer.cbBuffer = challenge.size();
    challengeOutBuffer.pvBuffer = const_cast<void*>(static_cast<void const*>(challenge.data()));

    SecBufferDesc challengeOutBufferDesc;
    challengeOutBufferDesc.ulVersion = 0;
    challengeOutBufferDesc.cBuffers = 1;
    challengeOutBufferDesc.pBuffers = &challengeOutBuffer;

    CtxtHandle serverContextHandle;
    unsigned long outContextAttributes;
    result = AcceptSecurityContext(&serverCredHandle, nullptr, &challengeInBufferDesc, 0, SECURITY_NETWORK_DREP, &serverContextHandle, &challengeOutBufferDesc, &outContextAttributes, &lifetime);
    if (result != SEC_I_CONTINUE_NEEDED)
    {
        return EXIT_FAILURE;
    }

    challenge.resize(challengeOutBuffer.cbBuffer);

    std::cout << "Challenge: [" << challenge << "]\n";


    // client challenge response generation
    SEC_WINNT_AUTH_IDENTITY_W auth_data;
    auth_data.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
    auth_data.User = nullptr;
    auth_data.UserLength = 0;
    auth_data.Domain = nullptr;
    auth_data.DomainLength = 0;
    auth_data.Password = nullptr;
    auth_data.PasswordLength = 0;

    CredHandle clientCredHandle;
    result = AcquireCredentialsHandleW(nullptr, const_cast<LPWSTR>(WDIGEST_SP_NAME_W), SECPKG_CRED_OUTBOUND, nullptr, &auth_data, nullptr, nullptr, &clientCredHandle, &lifetime);
    if (result != SEC_E_OK)
    {
        return EXIT_FAILURE;
    }

    SecBuffer challengeResponseInBuffers[4];

    // token
    challengeResponseInBuffers[0].BufferType = SECBUFFER_TOKEN;
    challengeResponseInBuffers[0].cbBuffer = challenge.size();
    challengeResponseInBuffers[0].pvBuffer = const_cast<void*>(static_cast<void const*>(challenge.data()));

    // method
    challengeResponseInBuffers[1].BufferType = SECBUFFER_PKG_PARAMS;
    challengeResponseInBuffers[1].cbBuffer = client_method.size();
    challengeResponseInBuffers[1].pvBuffer = const_cast<void*>(static_cast<void const*>(client_method.data()));

    // body hash
    challengeResponseInBuffers[2].BufferType = SECBUFFER_PKG_PARAMS;
    challengeResponseInBuffers[2].cbBuffer = 0;
    challengeResponseInBuffers[2].pvBuffer = nullptr;

    // target
    challengeResponseInBuffers[3].BufferType = SECBUFFER_STREAM;
    challengeResponseInBuffers[3].cbBuffer = client_target.size() * sizeof(wchar_t);
    challengeResponseInBuffers[3].pvBuffer = const_cast<void*>(static_cast<void const*>(client_target.data()));

    SecBufferDesc challengeResponseInBufferDesc;

    challengeResponseInBufferDesc.ulVersion = 0;
    challengeResponseInBufferDesc.cBuffers = 4;
    challengeResponseInBufferDesc.pBuffers  = challengeResponseInBuffers;

    std::string challengeResponse;
    challengeResponse.resize(package_info->cbMaxToken);

    SecBuffer challengeResponseOutBuffer;
    challengeResponseOutBuffer.BufferType = SECBUFFER_TOKEN;
    challengeResponseOutBuffer.cbBuffer = challengeResponse.size();
    challengeResponseOutBuffer.pvBuffer = const_cast<void*>(static_cast<void const*>(challengeResponse.data()));

    SecBufferDesc challengeResponseOutBufferDesc;
    challengeResponseOutBufferDesc.ulVersion = 0;
    challengeResponseOutBufferDesc.cBuffers = 1;
    challengeResponseOutBufferDesc.pBuffers = &challengeResponseOutBuffer;

    CtxtHandle clientContextHandle;
    result = InitializeSecurityContextW(&clientCredHandle, nullptr, const_cast<SEC_WCHAR*>(client_uri.c_str()), 0, 0, SECURITY_NETWORK_DREP, &challengeResponseInBufferDesc, 0, &clientContextHandle, &challengeResponseOutBufferDesc, &outContextAttributes, &lifetime);
    if(result != SEC_E_OK)
    {
        return EXIT_FAILURE;
    }

    challengeResponse.resize(challengeResponseOutBuffer.cbBuffer);

    std::cout << "Challenge Response: [" << challengeResponse << "]\n";


    // server verify challenge response

    SecBuffer verifyChallengeResponseInBuffers[5];

    // token
    verifyChallengeResponseInBuffers[0].BufferType = SECBUFFER_TOKEN;
    verifyChallengeResponseInBuffers[0].cbBuffer = challengeResponse.size();
    verifyChallengeResponseInBuffers[0].pvBuffer = const_cast<void*>(static_cast<void const*>(challengeResponse.data()));

    // method
    verifyChallengeResponseInBuffers[1].BufferType = SECBUFFER_PKG_PARAMS;
    verifyChallengeResponseInBuffers[1].cbBuffer = client_method.size();
    verifyChallengeResponseInBuffers[1].pvBuffer = const_cast<void*>(static_cast<void const*>(client_method.data()));

    // uri
    verifyChallengeResponseInBuffers[2].BufferType = SECBUFFER_PKG_PARAMS;
    verifyChallengeResponseInBuffers[2].cbBuffer = client_uri_utf8.size();
    verifyChallengeResponseInBuffers[2].pvBuffer = const_cast<void*>(static_cast<void const*>(client_uri_utf8.data()));

    // body hash
    verifyChallengeResponseInBuffers[3].BufferType = SECBUFFER_PKG_PARAMS;
    verifyChallengeResponseInBuffers[3].cbBuffer = 0;
    verifyChallengeResponseInBuffers[3].pvBuffer = nullptr;

    // realm
    verifyChallengeResponseInBuffers[4].BufferType = SECBUFFER_PKG_PARAMS;
    verifyChallengeResponseInBuffers[4].cbBuffer = realm.size() * sizeof(wchar_t);
    verifyChallengeResponseInBuffers[4].pvBuffer = const_cast<void*>(static_cast<void const*>(realm.c_str()));

    SecBufferDesc verifyChallengeResponseInBufferDesc;

    verifyChallengeResponseInBufferDesc.ulVersion = 0;
    verifyChallengeResponseInBufferDesc.cBuffers = 5;
    verifyChallengeResponseInBufferDesc.pBuffers  = verifyChallengeResponseInBuffers;

    std::string verifyChallengeResponse;
    verifyChallengeResponse.resize(package_info->cbMaxToken);

    SecBuffer verifyChallengeResponseOutBuffer;
    challengeOutBuffer.BufferType = SECBUFFER_TOKEN;
    challengeOutBuffer.cbBuffer = verifyChallengeResponse.size();
    challengeOutBuffer.pvBuffer = const_cast<void*>(static_cast<void const*>(verifyChallengeResponse.data()));

    SecBufferDesc verifyChallengeResponseOutBufferDesc;
    verifyChallengeResponseOutBufferDesc.ulVersion = 0;
    verifyChallengeResponseOutBufferDesc.cBuffers = 1;
    verifyChallengeResponseOutBufferDesc.pBuffers = &verifyChallengeResponseOutBuffer;

    result = AcceptSecurityContext(&serverCredHandle, &serverContextHandle, &verifyChallengeResponseInBufferDesc, 0, SECURITY_NETWORK_DREP, &serverContextHandle, &verifyChallengeResponseOutBufferDesc, &outContextAttributes, &lifetime);
    if (result != SEC_I_COMPLETE_NEEDED)
    {
        std::cout << "Challenge Response Verification Failed with [0x" << std::hex << result << "]";
        return EXIT_FAILURE;
    }

    std::cout << "Challenge Response Verified";
    return EXIT_SUCCESS;
}
在我看来,这似乎是可行的,但我不明白为什么您需要最后一个客户端初始化SecurityContext,因为服务器端已经验证了它

此外,我还可以取出第一个“CLIENT:InitializeSecurityContext”,因为它不需要,并返回一个“blank”标记,如果删除,它仍然可以正常工作


我无法使用客户端的当前用户凭据,我必须提供一个具有有效凭据的SEC_WINNT_AUTH_身份。有什么原因吗?

wdigest包在默认情况下被禁用,因为它使用的是不安全的MD5。 您必须在注册表中启用程序包才能使用代码。既然wdigest不再安全,为什么要使用它呢

#include <windows.h>
#include <stdio.h>
#define SECURITY_WIN32
#include <sspi.h>

void wmain(int argc, WCHAR *argv[])
{
    SECURITY_STATUS ss;
    SecPkgInfo      *spi = {0};

    ss = QuerySecurityPackageInfo(L"wdigest", &spi);
    if (ss != SEC_E_OK)
    {
        wprintf(L"QuerySecurityPackageInfo failed with %u\n", ss);
        return;
    }

    wprintf(L"Capabilities:   0x%X\n", spi->fCapabilities);
    wprintf(L"wVersion:       0x%X\n", spi->wVersion);
    wprintf(L"Max Token Size: 0x%X\n", spi->cbMaxToken);

    LPBYTE lpbOut = NULL;
    lpbOut = (LPBYTE)LocalAlloc(LPTR, spi->cbMaxToken);
    if (lpbOut == NULL)
    {
        wprintf(L"LocalAlloc failed with %u\n", GetLastError());
        return;
    }

    CredHandle ServerCred;
    CredHandle ClientCred;
    TimeStamp LifeTime;

    // server side
    ss = AcquireCredentialsHandle(NULL, L"wdigest", SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &ServerCred, &LifeTime);
    if (ss != SEC_E_OK)
    {
        wprintf(L"AcquireCredentialsHandle failed with %u\n", ss);
        return;
    }
    else
        wprintf(L"SERVER: AcquireCredentialsHandle SUCCESS\n");

    // client side
    SEC_WINNT_AUTH_IDENTITY   AuthIdentity;


    WCHAR szDomain[] = L"domain";
    WCHAR szPassword[] = L"password";
    WCHAR szUser[] = L"user";



    AuthIdentity.Domain = (unsigned short *)szDomain;
    AuthIdentity.DomainLength = (unsigned long)wcslen(szDomain);
    AuthIdentity.Password = (unsigned short *)szPassword;
    AuthIdentity.PasswordLength = (unsigned long)wcslen(szPassword);
    AuthIdentity.User = (unsigned short *)szUser;
    AuthIdentity.UserLength = (unsigned long)wcslen(szUser);
    AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

    /*
    AuthIdentity.Domain = (unsigned short *)NULL;
    AuthIdentity.DomainLength = (unsigned long)0;
    AuthIdentity.Password = (unsigned short *)NULL;
    AuthIdentity.PasswordLength = (unsigned long)0;
    AuthIdentity.User = (unsigned short *)NULL;
    AuthIdentity.UserLength = (unsigned long)0;
    AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;*/


    ss = AcquireCredentialsHandle(NULL, L"wdigest", SECPKG_CRED_OUTBOUND, NULL, &AuthIdentity, NULL, NULL, &ClientCred, &LifeTime);
    if (ss != SEC_E_OK)
    {
        wprintf(L"OUTBOUND: AcquireCredentialsHandle failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"CLIENT: AcquireCredentialsHandle SUCCESS\n");

    SecBufferDesc OutputBuffers;
    SecBuffer     TempTokensOut[6];

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer   = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer   = lpbOut;

    CtxtHandle ClientCtxtHandle;
    ULONG ClientContextRetFlags = 0;
    BOOL  bContinue             = FALSE;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | */ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, NULL, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"CLIENT: InitializeSecurityContext: SEC_I__CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"InitializeSecurityContext failed with 0x%X\n", ss);
            return;
        }
    }

    SecBufferDesc InputBuffers;
    SecBuffer     TempTokensIn[10];

    LPBYTE lpbIn = NULL;
    lpbIn = (LPBYTE)LocalAlloc(LPTR, spi->cbMaxToken);
    if (lpbIn == NULL)
    {
        wprintf(L"LocalAlloc failed with %u\n", GetLastError());
        return;
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ULONG      TargetDataRep = 0;
    CtxtHandle ServerCtxtHandle;
    ULONG      ServerContextRetFlags = 0;

    ss = AcceptSecurityContext(&ServerCred, NULL, &InputBuffers, 0 /*ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY*/, TargetDataRep, &ServerCtxtHandle, &OutputBuffers, &ServerContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"SERVER: AcceptSecurityContext: SEC_I__CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"AcceptSecurityContext failed with 0x%X\n", ss);
            return;
        }
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | */ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, &InputBuffers, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"CLIENT: InitializeSecurityContext: SEC_I_CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"InitializeSecurityContext (2) failed with 0x%X\n", ss);
            return;
        }
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = AcceptSecurityContext(&ServerCred, NULL, &InputBuffers, 0 /*ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY*/, TargetDataRep, &ServerCtxtHandle, &OutputBuffers, &ServerContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;
    }
    else if (ss != SEC_E_OK)
    {
        wprintf(L"AcceptSecurityContext (2) failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"AcceptSecurityContext SUCCESS\n");

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY |*/ ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, &InputBuffers, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;
    }
    else if (ss != SEC_E_OK)
    {
        wprintf(L"InitializeSecurityContext (2) failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"InitializeSecurityContext SUCCESS\n");

    ss = FreeCredentialsHandle(&ClientCred);
    if (ss != SEC_E_OK)
    {
        wprintf(L"FreeCredentialsHandle failed with %u\n", ss);
        return;
    }

    ss = FreeCredentialsHandle(&ServerCred);
    if (ss != SEC_E_OK)
    {
        wprintf(L"FreeCredentialsHandle failed with %u\n", ss);
        return;
    }

    if (lpbOut != NULL)
        LocalFree((HLOCAL)lpbOut);

    if (lpbIn != NULL)
        LocalFree((HLOCAL)lpbIn);

    if (spi != NULL)
        FreeContextBuffer((PVOID)spi);
}
#包括
#包括
#在WIN32中定义安全性
#包括
void wmain(int argc,WCHAR*argv[])
{
安全状况;
SecPkgInfo*spi={0};
ss=查询安全包信息(L“wdigest”和spi);
如果(ss!=秒E__确定)
{
wprintf(L“QuerySecurityPackageInfo失败,错误为%u\n”,ss);
回来
}
wprintf(L“能力:0x%X\n”,spi->fCapabilities);
wprintf(L“wVersion:0x%X\n”,spi->wVersion);
wprintf(L“最大令牌大小:0x%X\n”,spi->cbMaxToken);
LPBYTE lpbOut=NULL;
lpbOut=(LPBYTE)LocalAlloc(LPTR,spi->cbMaxToken);
if(lpbOut==NULL)
{
wprintf(L“LocalAlloc失败,错误为%u\n”,GetLastError());
回来
}
CredHandle服务器Cred;
CredHandle ClientCred;
时间戳寿命;
//服务器端
ss=AcquireCredentialsHandle(NULL,L“wdigest”,SECPKG_CRED_INBOUND,NULL,NULL,NULL,&ServerCred,&life);
如果(ss!=秒E__确定)
{
wprintf(L“AcquireCredentialsHandle失败,错误为%u\n”,ss);
回来
}
其他的
wprintf(L“服务器:AcquireCredentialsHandle成功\n”);
//客户端
SEC_WINNT_AUTH_IDENTITY AuthIdentity;
WCHAR szDomain[]=L“domain”;
WCHAR szPassword[]=L“密码”;
WCHAR szUser[]=L“用户”;
域=(无符号短*)szDomain;
AuthIdentity.DomainLength=(无符号长)wcslen(szDomain);
AuthIdentity.Password=(无符号短*)szPassword;
AuthIdentity.PasswordLength=(无符号长)wcslen(szPassword);
AuthIdentity.User=(无符号短*)szUser;
AuthIdentity.UserLength=(无符号长)wcslen(szUser);
Flags=SEC\u WINNT\u AUTH\u IDENTITY\u UNICODE;
/*
AuthIdentity.Domain=(无符号短*)NULL;
AuthIdentity.DomainLength=(无符号长)0;
AuthIdentity.Password=(无符号短*)NULL;
AuthIdentity.PasswordLength=(无符号长)0;
AuthIdentity.User=(无符号短*)NULL;
AuthIdentity.UserLength=(无符号长)0;
Flags=SEC\u WINNT\u AUTH\u IDENTITY\u UNICODE*/
ss=AcquireCredentialsHandle(NULL,L“wdigest”,SECPKG_CRED_出站,NULL,&AuthIdentity,NULL,NULL,&ClientCred,&life);
如果(ss!=秒E__确定)
{
wprintf(L“出站:AcquireCredentialsHandle失败,错误为0x%X\n”,ss);
回来
}
其他的
wprintf(L“客户端:AcquireCredentialsHandle成功\n”);
SecBufferDesc输出缓冲区;
SecBuffer-okensout[6];
OutputBuffers.ulVersion=SECBUFFER\u版本;
OutputBuffers.cBuffers=1;
OutputBuffers.pBuffers=TentokensOut;
TestOkenOut[0]。BufferType=SECBUFFER\u令牌;
TestOkenOut[0].cbBuffer=spi->cbMaxToken;
TestOkenOut[0]。pvBuffer=lpbOut;
CtxtHandle客户端CtxtHandle;
ULONG ClientContextRetFlags=0;
BOOL bContinue=FALSE;
ss=InitializeSecurityContext(&ClientCred,NULL,L“HTTP://test.com”,/*ISC_-REQ_完整性| ISC_-REQ_保密性|*/ISC_-REQ_-REPLAY|DETECT | ISC_-REQ_-CONNECTION,NULL,SECURITY_-NATIVE_-DREP,NULL,NULL,
&ClientCtxtHandle、&OutputBuffers、&ClientContextRetFlags、&LifeTime);
如果(ss==第二节,需要继续)
{
b继续=真;
wprintf(L“客户端:初始化安全上下文:需要时继续”);
}
其他的
{
如果(ss!=秒E__确定)
{
wprintf(L“InitializeSecurityContext失败,错误为0x%X\n”,ss);
回来
}
}
SecBufferDesc输入缓冲区;
secokensin[10];
LPBYTE lpbIn=NULL;
lpbIn=(LPBYTE)LocalAlloc(LPTR,spi->cbMaxToken);
如果(lpbIn==NULL)
{
wprintf(L“LocalAlloc失败,错误为%u\n”,GetLastError());
回来
}
InputBuffers.ulVersion=SECBUFFER\u版本;
InputBuffers.cBuffers=1;
InputBuffers.pBuffers=Tentokensin;
Testokensin[0]。BufferType=SECBUFFER\u令牌;
Testokensin[0].cbBuffer=Testokensout[0].cbBuffer;
Tentokensin[0].pvBuffer=Tentokensout[0].pvBuffer;
OutputBuffers.ulVersion=SECBUFFER\u版本;
OutputBuffers.cBuffers=1;
OutputBuffers.pBuffers=TentokensOut;
TestOkenOut[0]。BufferType=SECBUFFER\u令牌;
TestOkenOut[0].cbBuffer=spi->cbMaxToken;
TestOkenOut[0]。pvBuffer=lpbOut;
ULONG TargetDataRep=0;
CtxtHandle服务器CtxtHandle;
ULONG ServerContextRetFlags=0;
ss=AcceptSecurityContext(&ServerCred,NULL,&InputBuffers,0/*ASC_请求_完整性| ASC_请求_机密性*/,TargetDataRep,&ServerCtxtHandle,&OutputBuffers,&ServerContextRetFlags,&LifeTime);
如果(ss==第二节,需要继续)
{
b继续=真;
wprintf(L“服务器:AcceptSecurityContext:SEC\u I\u CONTINUE\u NEEDED\n”);
}
其他的
{
如果(ss!=秒E__确定)
{
wprintf(L“AcceptSecurityContext失败,错误为0x%X\n”,ss);
回来
}
}
InputBuffers.ulVersion=SECBUFFER\u版本;
输入缓冲区
#include <windows.h>
#include <stdio.h>
#define SECURITY_WIN32
#include <sspi.h>

void wmain(int argc, WCHAR *argv[])
{
    SECURITY_STATUS ss;
    SecPkgInfo      *spi = {0};

    ss = QuerySecurityPackageInfo(L"wdigest", &spi);
    if (ss != SEC_E_OK)
    {
        wprintf(L"QuerySecurityPackageInfo failed with %u\n", ss);
        return;
    }

    wprintf(L"Capabilities:   0x%X\n", spi->fCapabilities);
    wprintf(L"wVersion:       0x%X\n", spi->wVersion);
    wprintf(L"Max Token Size: 0x%X\n", spi->cbMaxToken);

    LPBYTE lpbOut = NULL;
    lpbOut = (LPBYTE)LocalAlloc(LPTR, spi->cbMaxToken);
    if (lpbOut == NULL)
    {
        wprintf(L"LocalAlloc failed with %u\n", GetLastError());
        return;
    }

    CredHandle ServerCred;
    CredHandle ClientCred;
    TimeStamp LifeTime;

    // server side
    ss = AcquireCredentialsHandle(NULL, L"wdigest", SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &ServerCred, &LifeTime);
    if (ss != SEC_E_OK)
    {
        wprintf(L"AcquireCredentialsHandle failed with %u\n", ss);
        return;
    }
    else
        wprintf(L"SERVER: AcquireCredentialsHandle SUCCESS\n");

    // client side
    SEC_WINNT_AUTH_IDENTITY   AuthIdentity;


    WCHAR szDomain[] = L"domain";
    WCHAR szPassword[] = L"password";
    WCHAR szUser[] = L"user";



    AuthIdentity.Domain = (unsigned short *)szDomain;
    AuthIdentity.DomainLength = (unsigned long)wcslen(szDomain);
    AuthIdentity.Password = (unsigned short *)szPassword;
    AuthIdentity.PasswordLength = (unsigned long)wcslen(szPassword);
    AuthIdentity.User = (unsigned short *)szUser;
    AuthIdentity.UserLength = (unsigned long)wcslen(szUser);
    AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

    /*
    AuthIdentity.Domain = (unsigned short *)NULL;
    AuthIdentity.DomainLength = (unsigned long)0;
    AuthIdentity.Password = (unsigned short *)NULL;
    AuthIdentity.PasswordLength = (unsigned long)0;
    AuthIdentity.User = (unsigned short *)NULL;
    AuthIdentity.UserLength = (unsigned long)0;
    AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;*/


    ss = AcquireCredentialsHandle(NULL, L"wdigest", SECPKG_CRED_OUTBOUND, NULL, &AuthIdentity, NULL, NULL, &ClientCred, &LifeTime);
    if (ss != SEC_E_OK)
    {
        wprintf(L"OUTBOUND: AcquireCredentialsHandle failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"CLIENT: AcquireCredentialsHandle SUCCESS\n");

    SecBufferDesc OutputBuffers;
    SecBuffer     TempTokensOut[6];

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer   = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer   = lpbOut;

    CtxtHandle ClientCtxtHandle;
    ULONG ClientContextRetFlags = 0;
    BOOL  bContinue             = FALSE;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | */ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, NULL, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"CLIENT: InitializeSecurityContext: SEC_I__CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"InitializeSecurityContext failed with 0x%X\n", ss);
            return;
        }
    }

    SecBufferDesc InputBuffers;
    SecBuffer     TempTokensIn[10];

    LPBYTE lpbIn = NULL;
    lpbIn = (LPBYTE)LocalAlloc(LPTR, spi->cbMaxToken);
    if (lpbIn == NULL)
    {
        wprintf(L"LocalAlloc failed with %u\n", GetLastError());
        return;
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ULONG      TargetDataRep = 0;
    CtxtHandle ServerCtxtHandle;
    ULONG      ServerContextRetFlags = 0;

    ss = AcceptSecurityContext(&ServerCred, NULL, &InputBuffers, 0 /*ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY*/, TargetDataRep, &ServerCtxtHandle, &OutputBuffers, &ServerContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"SERVER: AcceptSecurityContext: SEC_I__CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"AcceptSecurityContext failed with 0x%X\n", ss);
            return;
        }
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | */ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, &InputBuffers, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;

        wprintf(L"CLIENT: InitializeSecurityContext: SEC_I_CONTINUE_NEEDED\n");
    }
    else
    {
        if (ss != SEC_E_OK)
        {
            wprintf(L"InitializeSecurityContext (2) failed with 0x%X\n", ss);
            return;
        }
    }

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = AcceptSecurityContext(&ServerCred, NULL, &InputBuffers, 0 /*ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY*/, TargetDataRep, &ServerCtxtHandle, &OutputBuffers, &ServerContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;
    }
    else if (ss != SEC_E_OK)
    {
        wprintf(L"AcceptSecurityContext (2) failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"AcceptSecurityContext SUCCESS\n");

    InputBuffers.ulVersion = SECBUFFER_VERSION;
    InputBuffers.cBuffers  = 1;
    InputBuffers.pBuffers  = TempTokensIn;

    TempTokensIn[0].BufferType = SECBUFFER_TOKEN;
    TempTokensIn[0].cbBuffer   = TempTokensOut[0].cbBuffer;
    TempTokensIn[0].pvBuffer   = TempTokensOut[0].pvBuffer;

    OutputBuffers.ulVersion = SECBUFFER_VERSION;
    OutputBuffers.cBuffers  = 1;
    OutputBuffers.pBuffers  = TempTokensOut;

    TempTokensOut[0].BufferType = SECBUFFER_TOKEN;
    TempTokensOut[0].cbBuffer = spi->cbMaxToken;
    TempTokensOut[0].pvBuffer = lpbOut;

    ss = InitializeSecurityContext(&ClientCred, NULL, L"HTTP//test.com", /*ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY |*/ ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, NULL, SECURITY_NATIVE_DREP, &InputBuffers, NULL,
                                   &ClientCtxtHandle, &OutputBuffers, &ClientContextRetFlags, &LifeTime);
    if (ss == SEC_I_CONTINUE_NEEDED)
    {
        bContinue = TRUE;
    }
    else if (ss != SEC_E_OK)
    {
        wprintf(L"InitializeSecurityContext (2) failed with 0x%X\n", ss);
        return;
    }
    else
        wprintf(L"InitializeSecurityContext SUCCESS\n");

    ss = FreeCredentialsHandle(&ClientCred);
    if (ss != SEC_E_OK)
    {
        wprintf(L"FreeCredentialsHandle failed with %u\n", ss);
        return;
    }

    ss = FreeCredentialsHandle(&ServerCred);
    if (ss != SEC_E_OK)
    {
        wprintf(L"FreeCredentialsHandle failed with %u\n", ss);
        return;
    }

    if (lpbOut != NULL)
        LocalFree((HLOCAL)lpbOut);

    if (lpbIn != NULL)
        LocalFree((HLOCAL)lpbIn);

    if (spi != NULL)
        FreeContextBuffer((PVOID)spi);
}