gpt4 book ai didi

c++ - 不同域上的 Windows 用户凭据验证

转载 作者:可可西里 更新时间:2023-11-01 10:30:44 25 4
gpt4 key购买 nike

我正在尝试在未加入域的计算机上验证用户的 Windows 凭据。看起来这应该可以使用 SSPI API 来完成,但我无法让它工作。

我包含了我一直在尝试的代码(为简洁起见省略了资源清理)。这些是重要的信息:

域 Controller :control.dundermifflin.com
域: DUNDERMIFFLIN
用户: jim_halpert
通过: beesly

(我正在气隙网络上进行测试,因此与真正的 dundermifflin.com 没有任何 DNS 冲突。)

我得到的错误是 SEC_E_LOGON_DENIED。我确信用户名和密码是正确的,因为我可以使用该用户使用其他应用程序登录。谁能指出我正确的方向?

#include <Windows.h>
#define SECURITY_WIN32
#include <Security.h>
#include <crtdbg.h>

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

int main()
{
SEC_CHAR* principal = "HOST/control.dundermifflin.com";
SEC_CHAR* spn = NULL;

SEC_CHAR* domain = "DUNDERMIFFLIN";
SEC_CHAR* user = "jim_halpert";
SEC_CHAR* pass = "beesly";

/////////////////////////////////////////////
// Fill out the authentication information //
/////////////////////////////////////////////

SEC_WINNT_AUTH_IDENTITY auth;
auth.Domain = reinterpret_cast<unsigned char*>( domain );
auth.DomainLength = strlen( domain );
auth.User = reinterpret_cast<unsigned char*>( user );
auth.UserLength = strlen( user );
auth.Password = reinterpret_cast<unsigned char*>( pass );
auth.PasswordLength = strlen( pass );
auth.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

////////////////////////////////////////////
// Allocate the client and server buffers //
////////////////////////////////////////////

char clientOutBufferData[8192];
char serverOutBufferData[8192];

SecBuffer clientOutBuffer;
SecBufferDesc clientOutBufferDesc;

SecBuffer serverOutBuffer;
SecBufferDesc serverOutBufferDesc;

///////////////////////////////////////////
// Get the client and server credentials //
///////////////////////////////////////////

CredHandle clientCredentials;
CredHandle serverCredentials;

SECURITY_STATUS status;

status = ::AcquireCredentialsHandle( principal,
"Negotiate",
SECPKG_CRED_OUTBOUND,
NULL,
&auth,
NULL,
NULL,
&clientCredentials,
NULL );

_ASSERT( status == SEC_E_OK );

status = ::AcquireCredentialsHandle( principal,
"Negotiate",
SECPKG_CRED_INBOUND,
NULL,
NULL,
NULL,
NULL,
&serverCredentials,
NULL );

_ASSERT( status == SEC_E_OK );

//////////////////////////////////////
// Initialize the security contexts //
//////////////////////////////////////

CtxtHandle clientContext = {};
unsigned long clientContextAttr = 0;

CtxtHandle serverContext = {};
unsigned long serverContextAttr = 0;

/////////////////////////////
// Clear the client buffer //
/////////////////////////////

clientOutBuffer.BufferType = SECBUFFER_TOKEN;
clientOutBuffer.cbBuffer = sizeof clientOutBufferData;
clientOutBuffer.pvBuffer = clientOutBufferData;

clientOutBufferDesc.cBuffers = 1;
clientOutBufferDesc.pBuffers = &clientOutBuffer;
clientOutBufferDesc.ulVersion = SECBUFFER_VERSION;

///////////////////////////////////
// Initialize the client context //
///////////////////////////////////

status = InitializeSecurityContext( &clientCredentials,
NULL,
spn,
0,
0,
SECURITY_NATIVE_DREP,
NULL,
0,
&clientContext,
&clientOutBufferDesc,
&clientContextAttr,
NULL );

_ASSERT( status == SEC_I_CONTINUE_NEEDED );

/////////////////////////////
// Clear the server buffer //
/////////////////////////////

serverOutBuffer.BufferType = SECBUFFER_TOKEN;
serverOutBuffer.cbBuffer = sizeof serverOutBufferData;
serverOutBuffer.pvBuffer = serverOutBufferData;

serverOutBufferDesc.cBuffers = 1;
serverOutBufferDesc.pBuffers = &serverOutBuffer;
serverOutBufferDesc.ulVersion = SECBUFFER_VERSION;

//////////////////////////////////////////////////////
// Accept the client security context on the server //
//////////////////////////////////////////////////////

status = AcceptSecurityContext( &serverCredentials,
NULL,
&clientOutBufferDesc,
0,
SECURITY_NATIVE_DREP,
&serverContext,
&serverOutBufferDesc,
&serverContextAttr,
NULL );

_ASSERT( status == SEC_I_CONTINUE_NEEDED );

/////////////////////////////
// Clear the client buffer //
/////////////////////////////

clientOutBuffer.BufferType = SECBUFFER_TOKEN;
clientOutBuffer.cbBuffer = sizeof clientOutBufferData;
clientOutBuffer.pvBuffer = clientOutBufferData;

clientOutBufferDesc.cBuffers = 1;
clientOutBufferDesc.pBuffers = &clientOutBuffer;
clientOutBufferDesc.ulVersion = SECBUFFER_VERSION;

///////////////////////////////////////
// Give the client the server buffer //
///////////////////////////////////////

status = InitializeSecurityContext( &clientCredentials,
&clientContext,
spn,
0,
0,
SECURITY_NATIVE_DREP,
&serverOutBufferDesc,
0,
&clientContext,
&clientOutBufferDesc,
&clientContextAttr,
NULL );

_ASSERT( status == SEC_E_OK );

//////////////////////////////////////////////////////
// Accept the client security context on the server //
//////////////////////////////////////////////////////

status = AcceptSecurityContext( &serverCredentials,
&serverContext,
&clientOutBufferDesc,
0,
SECURITY_NATIVE_DREP,
&serverContext,
&serverOutBufferDesc,
&serverContextAttr,
NULL );

_ASSERT( status == SEC_E_LOGON_DENIED );
}

最佳答案

这是行不通的,因为您在同一台不知道 control.dundermifflin.com 域的机器上。

如果要确认用户名和密码,最简单的方法是到实际域中的机器进行身份验证。它可以像“net use\dc\netlogon/u:username password”一样简单,但你没有提到是否必须通过 SSPI 完成。如果是,您需要在 DC 上找到一个服务来进行身份验证。例如,您可以使用 LDAP。

另一种可行的方法是将您尝试访问的域告知您的非域计算机。这可以通过使用 ksetup 工具来完成。它将允许您为您拥有的域配置 KDC 主机名。查看/AddKdc 选项。这将使 Kerberos 知道对于提供的领域(又名域),它应该转到为 KDC 请求提供的主机名。

希望对您有所帮助。

关于c++ - 不同域上的 Windows 用户凭据验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1257642/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com