CryptAcquireContext завершается с ошибкой ERROR_FILE_NOT_FOUND (2L), когда пользователь не вошел в Windows 8.1

Я испытываю трудности при переносе приложения на основе C ++ CryptoAPI, которое в настоящее время работает на Windows Server 2008, на Windows 8.1. Сценарий таков:

Это приложение в конечном итоге запускается WatchDog.exe, который, в свою очередь, запускается, когда компьютер запускается планировщиком задач Windows.

Планировщик задач использует следующие правила для запуска WatchDog.exe:

  • Учетная запись администратора;
  • Выполнить независимо от того, вошел ли пользователь в систему или нет;
  • ПРОВЕРЕНО: не хранить пароль. Задача будет иметь доступ только к
    местные ресурсы;
  • Работать с высшими привилегиями;
  • Настроить для Win 8.1;
  • Срабатывает при запуске системы.

Сервер сидит там, никто не вошел в систему, пока в данном сценарии WatchDog.exe не запустит приложение. Журнал приложения подтверждает, что владелец процесса (GetUserName) — это тот же пользовательский планировщик задач, который используется для запуска WatchDog.exe.

Оказывается, это приложение прекрасно работает в Windows Server 2008, но в Windows 8.1 вызов CryptAcquireContext не удается с кодом возврата ERROR_FILE_NOT_FOUND (2 л). Странно то, что приложение НЕ завершится с ошибкой, если при запуске пользователь физически вошел в систему на компьютере, хотя это был не тот пользователь, который запустил приложение вручную.

Я посмотрел на документация и нашел:

«Профиль пользователя не загружен и не может быть найден. Это
происходит, когда приложение олицетворяет пользователя, например,
IUSR_ComputerName account. «

Я никогда не слышал о олицетворении, поэтому я провел исследование и нашел API LogonUser, ImpersonateLoggedOnUser а также RevertToSelf. Затем я обновил приложение следующим образом:

...
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."));
}
}
}
...

Выдержка с призывом к 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."));
...

В результате я получил журнал:

...
[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.
...

Это, кажется, показывает, что олицетворение работает должным образом, но я все еще получаю ошибку 2 (ERROR_FILE_NOT_FOUND) на CryptAcquireContext.

Резюме:

  • В Windows Server 2008 само приложение работает правильно, даже если
    без звонков LogonUser / Impersonate / Revert.
  • В Windows 8.1 приложение с вызовами или без
    LogonUser / Impersonate / Revert, будет работать правильно, только если пользователь вошел в систему (что недопустимо).

Любые мысли, куда я могу бежать, чтобы заставить это работать на Windows 8.1?

Заранее спасибо,

Дэн

2

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]