背景:
- 计算机
mycomputer
正在运行 Windows 10 并已加入域mydomain.com
。 - 用户使用本地帐户登录
mycomputer\localuser
。mycomputer
- 用户也知道域帐户的密码
mydomain\domainuser
。 - 服务主体名称
myprotocol/domainuser
在 Active Directory 中注册并映射到域帐户mydomain\domainuser
。 - 不允许本地用户
mycomputer\localuser
以mydomain\domainuser
.
用户希望在本地帐户下启动服务器进程,然后使用域帐户来验证与 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_t
和const
正确性有些丑陋。
另请注意,如果适当的凭据存储在控制面板的凭据管理器中,则此代码在由本地用户启动时有效 - 即使用主机名domainuser
(原文如此。)
服务器代码:
我已经有一个代码可以在进程启动时工作mydomain\domainuser
:
AcquireCredentialsHandle(
nullptr,
"Kerberos",
SECPKG_CRED_INBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
AcceptSecurityContext(
&credentials,
nullptr,
&inBufferArray,
attribs,
SECURITY_NATIVE_DREP,
&securityContext,
nullptr,
&attribs,
&lifetime);
但是,当服务器启动时mycomputer\localuser
,调用AcquireCredentialsHandle
失败并出现代码SEC_E_NO_CREDENTIALS
。
- 我尝试将该调用的第一个参数修改为
"myprotocol/domainuser"
,"domainuser"
或"mydomain\domainuser"
什至"domainuser@mydomain.com"
. mycomputer
我尝试使用主机名甚至在控制面板的凭据管理器中添加所需的凭据domainuser
。
mydomain\domainuser
在由 启动的进程中,我可以做些什么来获取凭据句柄mycomputer\localuser
?
编译代码片段:
#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("Success\n");
FreeCredentialsHandle(&credentials);
return 0;}
else{
std::printf("Failure\n");
return res;}}