QLocalSocket::connectToServer failed with QLocalSocket::SocketAccessError if server is running with administrative privileges (Windows 7)

StackOverflow https://stackoverflow.com/questions/10719487

Pergunta

Following problem occurs in Microsoft Windows 7 Implementation of Qt 4.8.1:

A QLocalServer (named pipe) is waiting for clients to connect, and it is running as an server application that runs with administrative privileges (system service for example).

How is it possible to allow an non privileged QLocalSocket client to connect to that server? Connection attempts are always denied with error code 3 (QLocalSocket::SocketAccessError). Is there a solution?

Edit: As I found out, the solution is to change pipe security by allowing full access to "Everyone" Sid. The only problem here is, that a call to SetSecurityInfo always fails with "access denied" error. First we have to obtain a pipe handle. Since the pipe is already created by Qt, we will open it with 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
}

Even if NewAcl is set to NULL the call fails. So what could cause that "access denied" error?

Foi útil?

Solução 3

I found a solution for the Qt problem. Since one can not use the handle created by CreateNamedPipe after calling QLocalServer::listen(), we can call CreateNamedPipe before Qt is doing it. If we call it with WRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE we can change anything.

Then we can change security settings as stated by Chris Dickson.

Outras dicas

I know, it's a little to late now, but this may help other people with the same Problem. Please notice this solution only works, if the server is your application to.

If thats the case, simply call server.setSocketOptions(QLocalServer::WorldAccessOption); or one of the other values of QLocalServer::​SocketOption before you call listen.

I am not familiar with Qt and so don't know what security characteristics are created by default when you use QtLocalServer in this way. However, in general there are two distinct mechanisms which could be causing the "Access denied" error.

The first is the DACL (Discretionary Access Control List) associated with the pipe. This works the same way as DACLs on any securable object in Windows (c.f. file security). There has to be an access control entry (ACE) in the list which grants your client user the desired type of access to the pipe. As you correctly indicate, adding an ACE for the "EVERYONE" SID allowing read/write access would remove any DACL barrier confronting your client. However, note that the code which amends the DACL will have to have WRITE_DAC access to the pipe already, otherwise it will be unable to open a handle through which the DACL can be amended. Your code doesn't even request WRITE_DAC access in the call to CreateNamedPipe, so this is a further reason why your call to SetSecurityInfo is failing.

The second mechanism is the Mandatory Integrity Control mechanism introduced in Windows Vista and later versions. It is not clear from your description whether this is in play here, but in general a client process can never have write access to a securable resource which is associated with a lower integrity level than that of the resource. If that is the issue here (and since your title refers specifically to Windows 7, I guess it might be) the only solution is to change the Mandatory Integrity Label on the pipe to lower the pipe's integrity level to that of your client. To do that you need to have access to the first pipe handle opened by the server (this Q&A explains why) because the integrity label is a special ACE contained in the System Access Control List (SACL) of the pipe, which you need WRITE_OWNER premission to change. Whether it is at all feasible in Qt to get hold of this pipe handle is something I have no knowledge of.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top