从Windows 10上本地用户启动的进程中获取域用户凭据的句柄



背景:

  • 计算机mycomputer正在运行Windows 10,并且已加入域mydomain.com
  • 用户在mycomputer上使用本地帐户mycomputerlocaluser登录
  • 用户还知道域帐户mydomaindomainuser的密码
  • 服务主体名称myprotocol/domainuser在Active Directory中注册,并映射到域帐户mydomaindomainuser
  • 不允许本地用户mycomputerlocalusermydomaindomainuser的身份启动进程

用户希望在本地帐户下启动服务器进程,然后使用域帐户使用Kerberos验证传入连接。

我想写那个服务器的代码。

客户端代码:

客户端代码很简单,包括对AcquireCredentialsHandle的调用和对InitializeSecurityContext:的调用

AcquireCredentialsHandle(
nullptr,
"Kerberos",
SECPKG_CRED_OUTBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
InitializeSecurityContext(
&credentials,
nullptr,
"myprotocol/myport",
ISC_REQ_CONFIDENTIALITY,
0,
SECURITY_NATIVE_DREP,
nullptr,
0,
&securityContext,
&outBufferArray,
&contextAttributes,
&lifetime);

请注意代码片段中字符串的简化用法。必须处理wchar_tconst正确性的现实有些丑陋。

还要注意,如果适当的凭据存储在控制面板的凭据管理器中,即主机名为domainuser(原文如此(的,则本地用户启动此代码时,此代码即可工作

服务器代码:

我已经有了一个代码,当进程由mydomaindomainuser:启动时可以工作

AcquireCredentialsHandle(
nullptr,
"Kerberos",
SECPKG_CRED_INBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
AcceptSecurityContext(
&credentials,
nullptr,
&inBufferArray,
attribs,
SECURITY_NATIVE_DREP,
&securityContext,
nullptr,
&attribs,
&lifetime);

但当mycomputerlocaluser启动服务器时,对AcquireCredentialsHandle的调用失败,代码为SEC_E_NO_CREDENTIALS

  • 我尝试将该调用的第一个参数修改为"myprotocol/domainuser""domainuser""mydomaindomainuser"甚至"domainuser@mydomain.com"
  • 我尝试使用主机名mycomputer甚至domainuser在控制面板的凭据管理器中添加所需的凭据

mycomputerlocaluser启动的进程中,我可以做些什么来获取mydomaindomainuser的凭据句柄

编译代码片段:

#include <string>
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define SECURITY_WIN32
#include <sspi.h>//Requires linking on Secur32.lib
int main(){
CredHandle credentials;
TimeStamp lifetime;
std::string package="Kerberos";
std::string principal="myprotocol/domainuser";
auto res=AcquireCredentialsHandle(
principal.data(),
package.data(),
SECPKG_CRED_INBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
if(res==SEC_E_OK){
std::printf("Successn");
FreeCredentialsHandle(&credentials);
return 0;}
else{
std::printf("Failuren");
return res;}}

要获得与当前登录会话关联的凭据以外的凭据,请使用备用安全主体的信息填充SEC_WINNT_AUTH_IDENTITY结构。使用pAuthData参数将结构传递给AcquireCredentialsHandle函数。

这个micrsoft示例演示了一个客户端调用,以获取特定用户帐户的摘要凭据:

#include <windows.h>
#ifdef UNICODE
ClientAuthID.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
#else
ClientAuthID.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
#endif
void main()
{
SECURITY_STATUS SecStatus; 
TimeStamp tsLifetime; 
CredHandle hCred;
SEC_WINNT_AUTH_IDENTITY ClientAuthID;
LPTSTR UserName = TEXT("ASecurityPrinciple");
LPTSTR DomainName = TEXT("AnAuthenticatingDomain");
// Initialize the memory.
ZeroMemory( &ClientAuthID, sizeof(ClientAuthID) );
// Specify string format for the ClientAuthID structure.

// Specify an alternate user, domain and password.
ClientAuthID.User = (unsigned char *) UserName;
ClientAuthID.UserLength = _tcslen(UserName);
ClientAuthID.Domain = (unsigned char *) DomainName;
ClientAuthID.DomainLength = _tcslen(DomainName);
// Password is an application-defined LPTSTR variable
// containing the user password.
ClientAuthID.Password = Password;
ClientAuthID.PasswordLength = _tcslen(Password);
// Get the client side credential handle.
SecStatus = AcquireCredentialsHandle (
NULL,                  // Default principal.
WDIGEST_SP_NAME,       // The Digest SSP. 
SECPKG_CRED_OUTBOUND,  // Client will use the credentials.
NULL,                  // Do not specify LOGON id.
&ClientAuthID,         // User information.
NULL,                  // Not used with Digest SSP.
NULL,                  // Not used with Digest SSP.
&hCred,                // Receives the credential handle.
&tsLifetime            // Receives the credential time limit.
);
}

相关内容

  • 没有找到相关文章

最新更新