8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 02:03:04 +01:00

Merge pull request #7213 from FirebirdSQL/work/WinPrivateNS

Use Windows private namespace for kernel objects used in server-to-server IPC.
This commit is contained in:
Vlad Khorsun 2022-06-20 15:30:27 +03:00 committed by GitHub
commit 0c1024345c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 3 deletions

View File

@ -2679,7 +2679,7 @@ static bool make_object_name(TEXT* buffer, size_t bufsize,
// CVC: I'm not convinced that if this call has no space to put the prefix,
// we can ignore that fact, hence I changed that signature, too.
if (!fb_utils::prefix_kernel_object_name(buffer, bufsize))
if (!fb_utils::private_kernel_object_name(buffer, bufsize))
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return false;

View File

@ -200,7 +200,7 @@ HANDLE ISC_make_signal(bool /*create_flag*/, bool manual_reset, int process_idL,
TEXT event_name[BUFFER_TINY];
sprintf(event_name, "_firebird_process%u_signal%d", process_idL, signal_number);
if (!fb_utils::prefix_kernel_object_name(event_name, sizeof(event_name)))
if (!fb_utils::private_kernel_object_name(event_name, sizeof(event_name)))
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return NULL;

View File

@ -43,8 +43,10 @@
#include "../common/gdsassert.h"
#include "../common/utils_proto.h"
#include "../common/classes/auto.h"
#include "../common/classes/locks.h"
#include "../common/classes/init.h"
#include "../common/isc_proto.h"
#include "../jrd/constants.h"
#include "firebird/impl/inf_pub.h"
#include "../jrd/align.h"
@ -60,6 +62,7 @@
#ifdef WIN_NT
#include <direct.h>
#include <io.h> // isatty()
#include <sddl.h>
#endif
#ifdef HAVE_UNISTD_H
@ -555,6 +558,147 @@ bool isGlobalKernelPrefix()
}
// Incapsulates Windows private namespace
class PrivateNamespace
{
public:
PrivateNamespace(MemoryPool& pool) :
m_hNamespace(NULL)
{
try
{
init();
}
catch (const Firebird::Exception& ex)
{
iscLogException("Error creating private namespace", ex);
}
}
~PrivateNamespace()
{
if (m_hNamespace != NULL)
ClosePrivateNamespace(m_hNamespace, 0);
}
// Add namespace prefix to the name, returns true on success.
bool addPrefix(char* name, size_t bufsize)
{
if (m_hNamespace == NULL)
return false;
if (strchr(name, '\\') != 0)
return false;
const size_t prefixLen = strlen(sPrivateNameSpace) + 1;
const size_t nameLen = strlen(name) + 1;
if (prefixLen + nameLen > bufsize)
return false;
memmove(name + prefixLen, name, nameLen + 1);
memcpy(name, sPrivateNameSpace, prefixLen - 1);
name[prefixLen - 1] = '\\';
return true;
}
bool isReady() const
{
return (m_hNamespace != NULL);
}
private:
const char* sPrivateNameSpace = "FirebirdCommon";
const char* sBoundaryName = "FirebirdCommonBoundary";
void raiseError(const char* apiRoutine)
{
(Firebird::Arg::Gds(isc_sys_request) << apiRoutine << Firebird::Arg::OsError()).raise();
}
void init()
{
alignas(SID) char sid[SECURITY_MAX_SID_SIZE];
DWORD cbSid = sizeof(sid);
// For now use EVERYONE, could be changed later
cbSid = sizeof(sid);
if (!CreateWellKnownSid(WinWorldSid, NULL, &sid, &cbSid))
raiseError("CreateWellKnownSid");
// Create security descriptor which allows generic access to the just created SID
SECURITY_ATTRIBUTES sa;
RtlSecureZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
char strSecDesc[255];
LPSTR strSid = NULL;
if (ConvertSidToStringSid(&sid, &strSid))
{
snprintf(strSecDesc, sizeof(strSecDesc), "D:(A;;GA;;;%s)", strSid);
LocalFree(strSid);
}
else
strncpy(strSecDesc, "D:(A;;GA;;;WD)", sizeof(strSecDesc));
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(strSecDesc, SDDL_REVISION_1,
&sa.lpSecurityDescriptor, NULL))
{
raiseError("ConvertStringSecurityDescriptorToSecurityDescriptor");
}
Firebird::Cleanup cleanSecDesc( [&sa] {
LocalFree(sa.lpSecurityDescriptor);
});
HANDLE hBoundaryDesc = CreateBoundaryDescriptor(sBoundaryName, 0);
if (hBoundaryDesc == NULL)
raiseError("CreateBoundaryDescriptor");
Firebird::Cleanup cleanBndDesc( [&hBoundaryDesc] {
DeleteBoundaryDescriptor(hBoundaryDesc);
});
if (!AddSIDToBoundaryDescriptor(&hBoundaryDesc, &sid))
raiseError("AddSIDToBoundaryDescriptor");
m_hNamespace = CreatePrivateNamespace(&sa, hBoundaryDesc, sPrivateNameSpace);
if (m_hNamespace == NULL)
{
const DWORD err = GetLastError();
if (err == ERROR_ALREADY_EXISTS)
{
m_hNamespace = OpenPrivateNamespace(hBoundaryDesc, sPrivateNameSpace);
if (m_hNamespace == NULL)
raiseError("OpenPrivateNamespace");
}
else
raiseError("CreatePrivateNamespace");
}
}
HANDLE m_hNamespace;
};
static Firebird::InitInstance<PrivateNamespace> privateNamespace;
bool private_kernel_object_name(char* name, size_t bufsize)
{
if (!privateNamespace().addPrefix(name, bufsize))
return prefix_kernel_object_name(name, bufsize);
return true;
}
bool privateNameSpaceReady()
{
return privateNamespace().isReady();
}
// This is a very basic registry querying class. Not much validation, but avoids
// leaving the registry open by mistake.

View File

@ -102,6 +102,8 @@ namespace fb_utils
#ifdef WIN_NT
bool prefix_kernel_object_name(char* name, size_t bufsize);
bool isGlobalKernelPrefix();
bool private_kernel_object_name(char* name, size_t bufsize);
bool privateNameSpaceReady();
#endif
// Compare the absolute value of two SINT64 numbers.

View File

@ -103,7 +103,8 @@ ConfigStorage::ConfigStorage()
PFnProcessIdToSessionId pfnProcessIdToSessionId =
(PFnProcessIdToSessionId) GetProcAddress(hmodKernel32, "ProcessIdToSessionId");
if (fb_utils::isGlobalKernelPrefix() ||
if (fb_utils::privateNameSpaceReady() ||
fb_utils::isGlobalKernelPrefix() ||
!pfnProcessIdToSessionId ||
pfnProcessIdToSessionId(GetCurrentProcessId(), &sesID) == 0 ||
sesID == 0)