3

I am having a hard time migrating a C++ CryptoAPI-based application that currently runs on Windows Server 2008 to Windows 8.1. The scenario is:

This application is eventually triggered by WatchDog.exe, which in its turn is triggered when the computer is started by Windows' Task Scheduler.

Task Scheduler uses the following rules to start the WatchDog.exe:

  • A Administrator User Account;
  • Run Whether user is logged on or not;
  • UNCHECKED: Do not store password. The task will only have access to local resources;
  • Run with Highest Privileges;
  • Configure for Win 8.1;
  • Triggered at system startup.

The server sits there, nobody logged, until in a given scenario WatchDog.exe starts the application. Application log confirms that the owner of the process (GetUserName) is the very same user Task Scheduler used to trigger WatchDog.exe.

It turns out that this application works fine in Windows Server 2008, but in windows 8.1 a call to CryptAcquireContext fails with return code ERROR_FILE_NOT_FOUND (2L). The odd thing is that the application will NOT fail if, when started, the user is physically logged onthe machine, although it was not the user who started the application manually.

I took a look at the documentation and found:

"The profile of the user is not loaded and cannot be found. This happens when the application impersonates a user, for example, the IUSR_ComputerName account."

I had never heard of impersonification, so I made a research and found the APIs LogonUser, ImpersonateLoggedOnUser and RevertToSelf. I then updated the application in this way:

...
HANDLE hToken;
if (! LogonUser(L"admin", L".", L"XXXXXXXX", LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken))
{
    logger->log (_T("Error logging on."));
}
else
{
    logger->log (PMLOG_LEVEL_TRACE, _T("Logged on."));
    if (! ImpersonateLoggedOnUser(hToken))
    {
        logger->log (_T("Error impersonating."));
    }
    else
    {
        logger->log (_T("Impersonated."));
        err = XXXXXXXXX(); // calls function which will execute CryptAcquireContext 
        if (! RevertToSelf())
        {
            logger->log (_T("Error reverting."));
        }
        else
        {
            logger->log (_T("Reverted."));
        }
    }
}
...

Excerpt with the call to CryptAcquireContext:

...
//---------------------------------------------------------------
// Get the handle to the default provider. 
if(! CryptAcquireContext(&hCryptProv, cryptContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
    DWORD e = GetLastError();
    _stprintf_s (logMsg, 1000, _T("Error %ld acquiring cryptographic provider."), e);
    cRSALogger->log (logMsg);
    return ERR_CCRYPT_NO_KEY_CONTAINER;
}
cRSALogger->log (_T("Cryptographic provider acquired."));
...

As the result, I got the log:

...
[2015/01/08 20:53:25-TRACE] Logged on.
[2015/01/08 20:53:25-TRACE] Impersonated.
...
[2015/01/08 20:53:26-ERROR] Error 2 acquiring cryptographic provider.
...
[2015/01/08 20:53:26-TRACE] Reverted.
...

That seems to show that impersonation is working properly, but still I get Error 2 (ERROR_FILE_NOT_FOUND) on CryptAcquireContext.

Summary:

  • On Windows Server 2008, the very same application runs properly even without the calls to LogonUser/Impersonate/Revert.
  • On Windows 8.1, the application, with or without the calls to LogonUser/Impersonate/Revert, will only work properly if the user is logged on (which is not acceptable).

Any thoughts where I can run to in order to get this working on windows 8.1?

Thank in advance,

Dan

Dan
  • 51
  • 4
  • @2501 Hi 2501. Using the default pszProvider (NULL) renders the application with the exact same behavior: The code works when admin is logged in, but it does not work if admin is logged off, regardless if impersonification is used or nor. Same old same old. Other ideas? – Dan Jan 10 '15 at 22:06

0 Answers0