Background:
- Computer
mycomputer
is running Windows 10 and is joined to domainmydomain.com
. - A user is logged with local account
mycomputer\localuser
onmycomputer
. - The user also knows the password of domain account
mydomain\domainuser
. - The service principal name
myprotocol/domainuser
is registered in Active Directory and maps to domain accountmydomain\domainuser
. - Local user
mycomputer\localuser
is not allowed to start a process asmydomain\domainuser
.
The user wants to launch a server process under the local account which would then use the domain account to authenticate incoming connections with Kerberos.
I want to write the code of that server.
Client code:
The client code is straightforward and consist of a call to AcquireCredentialsHandle
followed by a call to 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);
Note the simplified usage of strings in the code snippets. The reality which have to deal with wchar_t
and const
correctness is somewhat uglier.
Also note that this code works when launched by a local user if appropriate credentials are stored in Control Panel's Credential Manager - i.e. with hostname domainuser
(sic.)
Server code:
I already have a code which works when the process is launched by 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);
But when the server is launched by mycomputer\localuser
, the call to AcquireCredentialsHandle
fails with code SEC_E_NO_CREDENTIALS
.
- I tried modifying the first argument of that call to
"myprotocol/domainuser"
,"domainuser"
,"mydomain\domainuser"
or even"[email protected]"
. - I tried adding the required credentials in Control Panel's Credential Manager using hostname
mycomputer
and evendomainuser
.
What can I do to acquire the credential handle of mydomain\domainuser
in a process launched by mycomputer\localuser
?
Compiling code snippet:
#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;}}
To obtain credentials other than those associated with the current logon session, populate a
SEC_WINNT_AUTH_IDENTITY
structure with information for the alternate security principal. Pass the structure to theAcquireCredentialsHandle
function using thepAuthData
parameter.And this micrsoft example demonstrates a client-side call to obtain Digest credentials for a specific user account: