title: Getting handles to the credentials of a domain user from a process launched by a local user on Windows 10
body: <p><strong>Background:</strong></p>
  <ul>
  <li>Computer <code>mycomputer</code> is running Windows 10 and is joined to domain <code>mydomain.com</code>.</li>
  <li>A user is logged with local account <code>mycomputer\localuser</code> on <code>mycomputer</code>.</li>
  <li>The user also knows the password of domain account <code>mydomain\domainuser</code>.</li>
  <li>The service principal name <code>myprotocol/domainuser</code> is registered in Active Directory and maps to domain account <code>mydomain\domainuser</code>.</li>
  <li>Local user <code>mycomputer\localuser</code> is not allowed to start a process as <code>mydomain\domainuser</code>.</li>
  </ul>
  <p>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.</p>
  <p>I want to write the code of that server.</p>
  <p><strong>Client code:</strong></p>
  <p>The client code is straightforward and consist of a call to <code>AcquireCredentialsHandle</code> followed by a call to <code>InitializeSecurityContext</code>:</p>
  <pre><code>AcquireCredentialsHandle(
      nullptr,
      &quot;Kerberos&quot;,
      SECPKG_CRED_OUTBOUND,
      nullptr,
      nullptr,
      nullptr,
      nullptr,
      &amp;credentials,
      &amp;lifetime);
  InitializeSecurityContext(
      &amp;credentials,
      nullptr,
      &quot;myprotocol/myport&quot;,
      ISC_REQ_CONFIDENTIALITY,
      0,
      SECURITY_NATIVE_DREP,
      nullptr,
      0,
      &amp;securityContext,
      &amp;outBufferArray,
      &amp;contextAttributes,
      &amp;lifetime);
  </code></pre>
  <p>Note the simplified usage of strings in the code snippets. The reality which have to deal with <code>wchar_t</code> and <code>const</code> correctness is somewhat uglier.</p>
  <p>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 <code>domainuser</code> (sic.)</p>
  <p><strong>Server code:</strong></p>
  <p>I already have a code which works when the process is launched by <code>mydomain\domainuser</code>:</p>
  <pre><code>AcquireCredentialsHandle(
      nullptr,
      &quot;Kerberos&quot;,
      SECPKG_CRED_INBOUND,
      nullptr,
      nullptr,
      nullptr,
      nullptr,
      &amp;credentials,
      &amp;lifetime);
  AcceptSecurityContext(
      &amp;credentials,
      nullptr,
      &amp;inBufferArray,
      attribs,
      SECURITY_NATIVE_DREP,
      &amp;securityContext,
      nullptr,
      &amp;attribs,
      &amp;lifetime);
  </code></pre>
  <p>But when the server is launched by <code>mycomputer\localuser</code>, the call to <code>AcquireCredentialsHandle</code> fails with code <code>SEC_E_NO_CREDENTIALS</code>.</p>
  <ul>
  <li>I tried modifying the first argument of that call to <code>&quot;myprotocol/domainuser&quot;</code>, <code>&quot;domainuser&quot;</code>, <code>&quot;mydomain\domainuser&quot;</code> or even <code>&quot;domainuser@mydomain.com&quot;</code>.</li>
  <li>I tried adding the required credentials in Control Panel's Credential Manager using hostname <code>mycomputer</code> and even <code>domainuser</code>.</li>
  </ul>
  <p><strong>What can I do to acquire the credential handle of <code>mydomain\domainuser</code> in a process launched by <code>mycomputer\localuser</code> ?</strong></p>
  <p>Compiling code snippet:</p>
  <pre><code>#include &lt;string&gt;
  
  #define NOMINMAX
  #define WIN32_LEAN_AND_MEAN
  #include &lt;windows.h&gt;
  #define SECURITY_WIN32
  #include &lt;sspi.h&gt;//Requires linking on Secur32.lib
  
  int main(){
      CredHandle credentials;
      TimeStamp lifetime;
      std::string package=&quot;Kerberos&quot;;
      std::string principal=&quot;myprotocol/domainuser&quot;;
      auto res=AcquireCredentialsHandle(
          principal.data(),
          package.data(),
          SECPKG_CRED_INBOUND,
          nullptr,
          nullptr,
          nullptr,
          nullptr,
          &amp;credentials,
          &amp;lifetime);
      if(res==SEC_E_OK){
          std::printf(&quot;Success\n&quot;);
          FreeCredentialsHandle(&amp;credentials);
          return 0;}
      else{
          std::printf(&quot;Failure\n&quot;);
          return res;}}
  </code></pre>