3

在 Qt 4.8.1 的 Microsoft Windows 7 实现中出现以下问题:

QLocalServer(命名管道)正在等待客户端连接,它作为以管理权限运行的服务器应用程序(例如系统服务)运行。

如何允许非特权QLocalSocket 客户端连接到该服务器?连接尝试总是被拒绝,错误代码为 3 (QLocalSocket::SocketAccessError)。有解决办法吗?

编辑:正如我所发现的,解决方案是通过允许完全访问“每个人”Sid 来更改管道安全性。这里唯一的问题是,调用SetSecurityInfo总是失败并出现“拒绝访问”错误。首先,我们必须获得一个管道句柄。由于管道已经由 Qt 创建,我们将使用CreateNamedPipe.

HANDLE hPipe = CreateNamedPipe(
    (const wchar_t *)_Server->fullServerName().utf16(), // pipe name
    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,       // read/write access
    PIPE_TYPE_BYTE |          // byte type pipe
    PIPE_READMODE_BYTE |      // byte-read mode
    PIPE_WAIT,                // blocking mode
    PIPE_UNLIMITED_INSTANCES, // max. instances
    0,                  // output buffer size
    0,                  // input buffer size
    3000,                     // client time-out
    0 // Default Security
);
// Same call to open/create pipe as in qlocalserver_win.cpp
// Code here to add/change ACEs
if (SetSecurityInfo(hPipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
    0, 0, NewAcl, 0) == ERROR_SUCCESS) {
    // Success
}

即使NewAcl设置为 NULL,调用也会失败。那么什么会导致“拒绝访问”错误呢?

4

3 回答 3

7

我知道,现在有点晚了,但这可能会帮助其他有同样问题的人。请注意,此解决方案仅适用于服务器是您的应用程序的情况。

如果是这种情况,只需调用或调用之前server.setSocketOptions(QLocalServer::WorldAccessOption);的其他值之一。QLocalServer::​SocketOptionlisten

于 2015-02-01T17:27:04.663 回答
2

我对 Qt 不熟悉,因此不知道以这种方式使用 QtLocalServer 时会默认创建哪些安全特性。但是,通常有两种不同的机制可能导致“访问被拒绝”错误。

第一个是与管道关联的 DACL(自由访问控制列表)。这与 Windows 中任何安全对象上的 DACL 的工作方式相同(cf 文件安全)。列表中必须有一个访问控制条目 (ACE),它授予您的客户端用户所需的管道访问类型。正如您正确指出的那样,为“EVERYONE”SID 添加一个允许读/写访问的 ACE 将消除您的客户端面临的任何 DACL 障碍。但是,请注意,修改 DACL 的代码必须已经拥有对管道的 WRITE_DAC 访问权限,否则它将无法打开可以修改 DACL 的句柄。您的代码在对 CreateNamedPipe 的调用中甚至没有请求 WRITE_DAC 访问权限,因此这是您对 SetSecurityInfo 的调用失败的另一个原因。

第二种机制是在 Windows Vista 及更高版本中引入的强制完整性控制机制。从您的描述中不清楚这是否在这里起作用,但一般来说,客户端进程永远不能对与完整性级别低于资源的完整性级别相关联的安全资源具有写访问权限。如果这是这里的问题(并且由于您的标题专门针对 Windows 7,我猜它可能是)唯一的解决方案是更改管道上的强制完整性标签以将管道的完整性级别降低到您的客户端的完整性级别。为此,您需要访问服务器打开的第一个管道句柄(此问答解释了原因) 因为完整性标签是包含在管道的系统访问控制列表 (SACL) 中的特殊 ACE,您需要 WRITE_OWNER 权限才能更改。我不知道在 Qt 中获取这个管道句柄是否可行。

于 2012-05-25T07:27:26.793 回答
1

我找到了 Qt 问题的解决方案。由于不能使用CreateNamedPipe调用 QLocalServer::listen() 后创建的句柄,我们可以CreateNamedPipe在 Qt 执行之前调用。如果我们调用它,WRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE我们可以改变任何东西。

然后我们可以更改 Chris Dickson 所述的安全设置。

于 2012-05-29T06:02:35.400 回答