::CertOpenStore() не работает в Docker Windows
Я позвонил::CertOpenStore() из службы Windows, работающей под учетной записью "Сетевая служба" и Docker Windows. Но это не удалось с "Доступ запрещен".
Хост Windows 10.
Действия по воспроизведению:
- Создайте Dockerfile.
- Docker build -t пример.
- Docker run --name sample -i --rm sample
- sc create DEMO_SERVICE binPath = C: \ tools \ CertOpenStoreExperimental.exe obj = "nt полномочия \ сетевая служба"
- чистый старт DEMO_SERVICE
- чистый стоп DEMO_SERVICE
- TYPE result.txt
Исходный код CertOpenStoreExperimental.exe находится ниже:
//
// Demo Service
//
#include <fstream>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <assert.h>
#include <stdarg.h>
DWORD WINAPI HandlerEx(
DWORD dwControl,
DWORD dwEventType,
PVOID pvEventData,
PVOID pvContext);
VOID WINAPI ServiceMain(DWORD dwArgc, PTSTR* pszArgv);
VOID DebugPrint(LPTSTR szFormat, ...);
///////////////////////////////////////////////////////////////////////////////
#define SERVICE_NAME (TEXT("Demo_Service"))
#define DEBUG_BUFF_SIZE (1024)
///////////////////////////////////////////////////////////////////////////////
SERVICE_TABLE_ENTRY ServiceTable[] = {
{ SERVICE_NAME, ServiceMain },
{ NULL, NULL }
};
///////////////////////////////////////////////////////////////////////////////
BOOL g_bRun = TRUE;
BOOL g_bService = TRUE;
SERVICE_STATUS_HANDLE g_hServiceStatus = NULL;
///////////////////////////////////////////////////////////////////////////////
VOID main() {
BOOL bRet;
bRet = StartServiceCtrlDispatcher(ServiceTable);
assert(bRet);
}
////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI HandlerEx(
DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext) {
SERVICE_STATUS ss;
BOOL bRet;
// Initialize Variables for Service Control
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ss.dwWin32ExitCode = NO_ERROR;
ss.dwServiceSpecificExitCode = 0;
ss.dwCheckPoint = 1;
ss.dwWaitHint = 3000;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
switch (dwControl) {
case SERVICE_CONTROL_STOP:
DebugPrint(TEXT("SERVICE_CONTROL_STOP\n"));
// Set STOP_PENDING status.
ss.dwCurrentState = SERVICE_STOP_PENDING;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
// SERVICE SPECIFIC STOPPING CODE HERE.
// ...
// ...
g_bService = FALSE;
Sleep(3 * 1000);
// Set STOPPED status.
ss.dwCurrentState = SERVICE_STOPPED;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
break;
case SERVICE_CONTROL_PAUSE:
DebugPrint(TEXT("SERVICE_CONTROL_PAUSE\n"));
// Set PAUSE_PENDING status.
ss.dwCurrentState = SERVICE_PAUSE_PENDING;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
// APPLICATION SPECIFIC PAUSE_PENDING CODE HERE.
// ...
// ...
g_bRun = FALSE;
// Set PAUSE_PENDING status.
ss.dwCurrentState = SERVICE_PAUSED;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
break;
case SERVICE_CONTROL_CONTINUE:
DebugPrint(TEXT("SERVICE_CONTROL_CONTINUE\n"));
// Set PAUSE_PENDING status.
ss.dwCurrentState = SERVICE_START_PENDING;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
// APPLICATION SPECIFIC START_PENDING CODE HERE.
// ...
// ...
g_bRun = TRUE;
// Set RUNNING status.
ss.dwCurrentState = SERVICE_RUNNING;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
break;
}
break;
default:
return ERROR_CALL_NOT_IMPLEMENTED;
}
return NO_ERROR;
}
///////////////////////////////////////////////////////////////////////////////
VOID WINAPI ServiceMain(DWORD dwArgc, PTSTR* pszArgv) {
BOOL bRet;
SERVICE_STATUS ss;
// Initialize Variables for Service Control
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ss.dwWin32ExitCode = NO_ERROR;
ss.dwServiceSpecificExitCode = 0;
ss.dwCheckPoint = 1;
ss.dwWaitHint = 1000;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
// Register Service Control Handler
g_hServiceStatus =
RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL);
if (0 == g_hServiceStatus) {
DebugPrint(
TEXT("RegisterServiceCtrlHandler failed. %u\n"),
GetLastError());
return;
}
// Entering Starting Service.
DebugPrint(TEXT("SERVICE_START_PENDING...\n"));
ss.dwCurrentState = SERVICE_START_PENDING;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
return;
}
// APPLICATION SPECIFIC INITIALIZATION CODE
// ...
// ...
// Finish Initializing.
DebugPrint(TEXT("SERVICE_RUNNING.\n"));
ss.dwCurrentState = SERVICE_RUNNING;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
ss.dwControlsAccepted =
SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_STOP;
bRet = SetServiceStatus(g_hServiceStatus, &ss);
if (!bRet) {
DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError());
return;
}
//
// Service Main Code.
//
{
std::ofstream ofs("C:\\tools\\result.txt");
HCERTSTORE hStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY");
if (hStore) {
ofs << "Succeeded to call ::CertOpenStore()." << std::endl;
std::cout << "Succeeded to call ::CertOpenStore()." << std::endl;
::CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
hStore = NULL;
}
else {
DWORD dwMessageID = ::GetLastError();
LPVOID lpMessageBuffer;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwMessageID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMessageBuffer,
0,
NULL);
ofs << "Failed to call::CertOpenStore().dwMessageID = " << dwMessageID << " lpMessageBuffer=" << lpMessageBuffer << std::endl;
std::cout << "Failed to call::CertOpenStore().dwMessageID = " << dwMessageID << " lpMessageBuffer=" << lpMessageBuffer << std::endl;
LocalFree(lpMessageBuffer);
lpMessageBuffer = NULL;
}
}
while (g_bService) {
if (g_bRun) {
DebugPrint(TEXT("%s is running.\n"), SERVICE_NAME);
}
Sleep(2 * 1000);
}
DebugPrint(TEXT("END OF ServiceMain\n"));
}
///////////////////////////////////////////////////////////////////////////////
VOID DebugPrint(LPTSTR szFormat, ...) {
TCHAR szBuffer[DEBUG_BUFF_SIZE + 1];
INT nWritten;
va_list args;
::ZeroMemory(szBuffer, sizeof(szBuffer));
// Format error message like printf()
va_start(args, szFormat);
nWritten = _vsntprintf(szBuffer, DEBUG_BUFF_SIZE, szFormat, args);
va_end(args);
// Output debug string
::OutputDebugString(szBuffer);
}
Dockerfile находится ниже:
FROM microsoft/windowsservercore
COPY tools C:/tools/
WORKDIR C:/tools/
RUN rktools.exe /Q
RUN net user admin 9dm1n9dm1n! /add
RUN net localgroup administrators admin /add
RUN NTRights.Exe -u admin +r SeServiceLogonRight
CMD [ "powershell" ]
Вывод, когда служба выполняется с учетной записью Local System в Docker Windows.
C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe
sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe
[SC] CreateService SUCCESS
C:\tools>net start DEMO_SERVICE
net start DEMO_SERVICE
The DEMO_SERVICE service is starting.
The DEMO_SERVICE service was started successfully.
C:\tools>net stop DEMO_SERVICE
net stop DEMO_SERVICE
The DEMO_SERVICE service is stopping.
The DEMO_SERVICE service was stopped successfully.
C:\tools>TYPE result.txt
TYPE result.txt
Succeeded to call ::CertOpenStore().
Вывод, когда служба выполняется с учетной записью администратора в Docker Windows.
C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= ".\admin" password= "9dm1n9dm1n!"
sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= ".\admin" password= "9dm1n9dm1n!"
[SC] CreateService SUCCESS
C:\tools>net start DEMO_SERVICE
net start DEMO_SERVICE
The DEMO_SERVICE service is starting.
The DEMO_SERVICE service was started successfully.
C:\tools>net stop DEMO_SERVICE
net stop DEMO_SERVICE
The DEMO_SERVICE service is stopping.
The DEMO_SERVICE service was stopped successfully.
C:\tools>TYPE result.txt
TYPE result.txt
Succeeded to call ::CertOpenStore().
Вывод, когда служба выполняется с учетной записью "Сетевая служба" в Docker Windows.
C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service"
sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service"
[SC] CreateService SUCCESS
C:\tools>net start DEMO_SERVICE
net start DEMO_SERVICE
The DEMO_SERVICE service is starting.
The DEMO_SERVICE service was started successfully.
C:\tools>net stop DEMO_SERVICE
net stop DEMO_SERVICE
The DEMO_SERVICE service is stopping.
The DEMO_SERVICE service was stopped successfully.
C:\tools>TYPE result.txt
TYPE result.txt
Failed to call::CertOpenStore().dwMessageID = 5 lpMessageBuffer=000001FD0C99A760
Выходные данные, когда служба выполняется с учетной записью "Сетевая служба" на хост-компьютере (Windows 10).
c:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service"
[SC] CreateService SUCCESS
c:\tools>net start DEMO_SERVICE
The DEMO_SERVICE service is starting.
The DEMO_SERVICE service was started successfully.
c:\tools>net stop DEMO_SERVICE
The DEMO_SERVICE service was stopped successfully.
c:\tools>TYPE result.txt
Succeeded to call ::CertOpenStore().
Я хочу вызвать::CertOpenStore() из службы Windows, выполняемой с помощью "Сетевой сервис" в Docker Windows. Как я могу это сделать?