Skip to content

Commit

Permalink
Remove external subprocess code
Browse files Browse the repository at this point in the history
Using a thirdparty library just for starting and stopping a process is
a bit overkill so just use the Win32 API functions for that.

Declare the funtions and structs needed in the file needed them to
avoid including Windows headers.

If some more functionality related to process handling is needed a
dedicated process library (eg. Boost.Process) can be introduced.
  • Loading branch information
laudrup committed Jan 28, 2024
1 parent ba4b059 commit b514295
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1,215 deletions.
2 changes: 0 additions & 2 deletions test/certificate_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,6 @@ TEST_CASE("check certificate revocation (integration test)", "[.integration]") {

// success case: cert_ocsp is fine
ocsp_responder responder{};
// 'running()' does not mean that it is responding yet, but that we did start the process correctly
CHECK(responder.running());
// It takes a few seconds for the OCSP responder to become available.
// Therefore, we try to verify the certificate in a loop, but for at most 30 seconds.
auto res_with_responder = CRYPT_E_REVOCATION_OFFLINE;
Expand Down
104 changes: 81 additions & 23 deletions test/ocsp_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,94 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include "utils/subprocess.h"

#include "ocsp_responder.hpp"

struct ocsp_responder::ocsp_responder_impl {
struct subprocess_s child;
};
#include <string>
#include <system_error>

extern "C" {
typedef struct _PROCESS_INFORMATION *LPPROCESS_INFORMATION;
typedef struct _SECURITY_ATTRIBUTES *LPSECURITY_ATTRIBUTES;
typedef struct _STARTUPINFOA *LPSTARTUPINFOA;

__declspec(dllimport) unsigned long __stdcall GetLastError(void);
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall TerminateProcess(void*, unsigned int);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*, unsigned long);
__declspec(dllimport) int __stdcall CreateProcessA(const char*,
char*,
LPSECURITY_ATTRIBUTES,
LPSECURITY_ATTRIBUTES,
int,
unsigned long,
void*,
const char*,
LPSTARTUPINFOA,
LPPROCESS_INFORMATION);
}

// Start an OCSP responder at http://localhost:5000 that can provide OCSP responses for
// test certificates signed by test_certificates/ca_intermediate.crt.
ocsp_responder::ocsp_responder() {
const char *command_line[] = {"openssl.exe",
"ocsp",
"-CApath", TEST_CERTIFICATES_PATH,
"-index", TEST_CERTIFICATES_PATH "certindex",
"-port", "5000",
"-nmin", "1",
"-rkey", TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.key",
"-rsigner", TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.crt",
"-CA", TEST_CERTIFICATES_PATH "ca_intermediate.crt",
NULL};

impl_ = std::make_unique<ocsp_responder::ocsp_responder_impl>();
subprocess_create(command_line, subprocess_option_inherit_environment, &impl_->child);
}
std::string command_line{
"openssl.exe "
"ocsp "
"-CApath " TEST_CERTIFICATES_PATH " "
"-index " TEST_CERTIFICATES_PATH "certindex "
"-port 5000 "
"-nmin 1 "
"-rkey " TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.key "
"-rsigner " TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.crt "
" -CA " TEST_CERTIFICATES_PATH "ca_intermediate.crt"
};

ocsp_responder::~ocsp_responder() {
subprocess_terminate(&impl_->child);
struct startup_info {
unsigned long cb;
char* lpReserved;
char* lpDesktop;
char* lpTitle;
unsigned long dwX;
unsigned long dwY;
unsigned long dwXSize;
unsigned long dwYSize;
unsigned long dwXCountChars;
unsigned long dwYCountChars;
unsigned long dwFillAttribute;
unsigned long dwFlags;
unsigned short wShowWindow;
unsigned short cbReserved2;
unsigned char *lpReserved2;
void* hStdInput;
void* hStdOutput;
void* hStdError;
} start_info{};

struct process_information {
void* hProcess;
void* hThread;
unsigned long dwProcessId;
unsigned long dwThreadId;
} proc_info{};

if (!CreateProcessA(nullptr,
&command_line[0],
nullptr,
nullptr,
0,
0,
nullptr,
nullptr,
reinterpret_cast<LPSTARTUPINFOA>(&start_info),
reinterpret_cast<LPPROCESS_INFORMATION>(&proc_info))) {
throw std::system_error{std::error_code{static_cast<int>(GetLastError()), std::system_category()}, "CreateProcessA"};
}
CloseHandle(proc_info.hThread );
proc_handle_ = proc_info.hProcess;
}

bool ocsp_responder::running() {
return subprocess_alive(&impl_->child) != 0;
ocsp_responder::~ocsp_responder() {
const unsigned long infinite_timeout = 0xFFFFFFFF;
TerminateProcess(proc_handle_, 0);
WaitForSingleObject(proc_handle_, infinite_timeout);
CloseHandle(proc_handle_);
}
9 changes: 3 additions & 6 deletions test/ocsp_responder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
#ifndef BOOST_WINTLS_OCSP_RESPONDER_HPP
#define BOOST_WINTLS_OCSP_RESPONDER_HPP

#include <memory>

class ocsp_responder {
protected:
struct ocsp_responder_impl;
std::unique_ptr<ocsp_responder_impl> impl_;
public:
ocsp_responder();
~ocsp_responder();
bool running();

private:
void* proc_handle_ = nullptr;
};

#endif
Loading

0 comments on commit b514295

Please sign in to comment.