设置 ACL,指定允许在请求队列上接收 I/O 的工作进程

Set the ACL specifying the worker processes that are allowed to receive I/O on the request queue

本文关键字:进程 工作 队列 ACL 请求 设置      更新时间:2023-10-16

我正在使用WinHTTP Server API 2.0,我正在尝试以下步骤(https://msdn.microsoft.com/en-us/library/windows/desktop/aa364672(v=vs.85).aspx):

  • 创建请求队列并指定名称。
  • 使用HttpSetRequestQueueProperty函数配置请求队列。
  • 使用HttpQueryRequestQueueProperty函数查询请求队列配置参数。
  • 创建 URL 组并将其与请求队列关联。
  • 设置 ACL,指定允许在请求队列上接收 I/O 的工作进程
  • 调用HttpWaitForDemandStart以延迟工作进程的实例化,直到第一个请求到达请求队列。

任何人都可以帮助步骤:

设置 ACL,指定允许在请求队列上接收 I/O 的工作进程

我不确定这到底是什么意思(我从未使用过 ACL API),但我认为我需要在某个时间点调用::GetNamedSecurityInfo()来修改它:

if (NO_ERROR == ::HttpCreateRequestQueue(HTTPAPI_VERSION_2,
requestQueueName,
0,
HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER,
&m_requestQueue))
// setup queue 
if (NO_ERROR == ::HttpCreateUrlGroup(m_sessionId, &m_groupId, 0))
{
HTTP_BINDING_INFO bindingInfo{ 1, m_requestQueue };
if (NO_ERROR == ::HttpSetUrlGroupProperty(m_groupId, 
HttpServerBindingProperty,
&bindingInfo, 
sizeof(bindingInfo)))
{
m_localUrl = (NO_ERROR == (::HttpAddUrlToUrlGroup(m_groupId, localUrl.c_str(), 0, 0)));
m_globalUrl = (NO_ERROR == (::HttpAddUrlToUrlGroup(m_groupId, globalUrl.c_str(), 0, 0)));
PACL pacl = NULL;
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
DWORD result = ::GetNamedSecurityInfo(requestQueueName, 
SE_KERNEL_OBJECT, 
SACL_SECURITY_INFORMATION,
NULL, 
NULL, 
NULL, 
&pacl, 
&securityDescriptor);
// it (result != 0) fails when passing various SE_OBJECT_TYPEs
}
}

设置 ACL,指定允许的工作进程 在请求队列上接收 I/O

寻找其他一个注释:

命名请求队列是使用HttpCreateRequestQueue函数创建的。创建请求队列时,应用程序指定pSecurityAttribute参数中的 ACL。ACL,它只能 在创建请求队列时设置,允许工作进程 打开请求队列、接收请求和发送响应。由 默认情况下,不允许进程打开请求队列,除非它们 已在 ACL 中被授予权限。申请不需要 创建请求队列的管理权限。

所以实际上你可以(但不是必须的,这是可选的)创建和初始化一些安全描述符,并通过In_opt_ PSECURITY_ATTRIBUTES pSecurityAttributes将其传递给 HttpCreateRequestQueue 函数 - 这里绝对没有什么特别的,任何内核对象中使用的SECURITY_ATTRIBUTES创建 API。 例如,CreateEvent(这里是第一个参数)。

如何初始化它,为谁授予访问权限 - 这已经是一个悬而未决的问题 - 边界案例 - 允许所有人这样做:

ULONG cb = MAX_SID_SIZE;
PSID UntrustedLabelSid = (PSID)alloca(MAX_SID_SIZE);
if (CreateWellKnownSid(WinUntrustedLabelSid, 0, UntrustedLabelSid, &cb))
{
PACL Sacl = (PACL)alloca(cb += sizeof(ACL) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
InitializeAcl(Sacl, cb, ACL_REVISION);
if (AddMandatoryAce(Sacl, ACL_REVISION, 0, 0, UntrustedLabelSid))
{
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE);
SECURITY_ATTRIBUTES sa = { sizeof(sa), &sd, FALSE };
if (NO_ERROR == HttpCreateRequestQueue(HTTPAPI_VERSION_2,
requestQueueName,
&sa,
HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER,
&m_requestQueue))
{
}
}
}

作为替代方案,我们可以使用字符串格式的安全描述符,然后使用ConvertStringSecurityDescriptorToSecurityDescriptor进行转换,例如:

SECURITY_ATTRIBUTES sa = { sizeof(sa), 0, FALSE };
ULONG dwError;
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
L"D:NO_ACCESS_CONTROLS:(ML;;;;;LW)", 
SDDL_REVISION_1, &sa.lpSecurityDescriptor, 0))
{           
dwError = HttpCreateRequestQueue(HTTPAPI_VERSION_2,
requestQueueName,
&sa,
HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER,
&m_requestQueue);
LocalFree(sa.lpSecurityDescriptor);
}
else
{
dwError = GetLastError();
}

在这里"D:NO_ACCESS_CONTROLS:(ML;;;;;LW)"允许所有 -NO_ACCESS_CONTROLSLW- LowLabel 的所有访问。(并非像第一个示例那样不受信任)

另一个变体(仅例如)使用说下一个字符串:

"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGX;;;BU)(A;;GRGX;;;AC)S:(ML;;;;;LW)"

在这里,我们允许GENERIC_ALL(GA)到系统(SY)和管理员(BA)和用户(BU)和所有应用程序包(AC)GENERIC_READ|GENERIC_EXECUTE