::CertOpenStore() не работает в Docker Windows

Я позвонил::CertOpenStore() из службы Windows, работающей под учетной записью "Сетевая служба" и Docker Windows. Но это не удалось с "Доступ запрещен".

Хост Windows 10.

Действия по воспроизведению:

  1. Создайте Dockerfile.
  2. Docker build -t пример.
  3. Docker run --name sample -i --rm sample
  4. sc create DEMO_SERVICE binPath = C: \ tools \ CertOpenStoreExperimental.exe obj = "nt полномочия \ сетевая служба"
  5. чистый старт DEMO_SERVICE
  6. чистый стоп DEMO_SERVICE
  7. 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. Как я могу это сделать?

0 ответов

Другие вопросы по тегам