设置ACL,指定允许在请求队列

时间:2017-06-14 02:47:19

标签: c++ winapi acl

我正在使用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
        }
     }

1 个答案:

答案 0 :(得分:1)

  

设置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))
            {

            }
        }
    }

作为替代方案,我们可以使用string-format security descriptor,然后将其转换为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。 (不像第一个例子那样不受信任)

另一个变体(仅举例)使用say next string:

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

此处我们允许GENERIC_ALLGA系统SY)和管理员BA)和用户GENERIC_READ|GENERIC_EXECUTE)和所有应用程序包<{1>} BU