2012-05-23 60 views
3

如下問題QLocalSocket :: SocketAccessError(Windows 7)中:QLocalSocket :: connectToServer失敗,如果服務器使用管理權限運行在微軟Windows 7的Qt 4.8.1的實施發生

一個QLocalServer(命名管道)正在等待客戶端進行連接,並且正在作爲以管理權限運行的服務器應用程序(例如,系統服務)運行。

怎麼可能允許非特權 QLocalSocket客戶端連接到該服務器?連接嘗試總是被錯誤代碼3(QLocalSocket :: SocketAccessError)拒絕。有解決方案嗎?

編輯:我發現,解決方案是通過允許完全訪問「Everyone」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調用失敗。那麼,什麼會導致「訪問被拒絕」錯誤?

+0

嘗試在同一個用戶下同時運行服務器和客戶端(包括您的用戶或兩者都以管理員身份)。這可能是命名管道嚴格綁定到創建管道的用戶的問題 - 在本例中是管理員 - 因此沒有其他人可以訪問此管道。 (但我不確定Windows中命名管道的權限系統如何。) – leemes

回答

1

我找到了Qt問題的解決方案。由於在調用QLocalServer :: listen()之後不能使用由CreateNamedPipe創建的句柄,因此我們可以在Qt執行之前調用CreateNamedPipe。如果我們用WRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE來稱呼它,我們可以改變任何東西。

然後我們可以按照Chris Dickson的說法更改安全設置。

+0

你能發佈完整的代碼嗎? – Alexey

+0

@Alexey:你只需要在你自己調用Qt代碼之前,Qt會使用附加標誌'WRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE'。 – bkausbk

2

我對Qt並不熟悉,所以不知道當以這種方式使用QtLocalServer時默認會創建哪些安全特性。但是,通常有兩種不同的機制可能導致「訪問被拒絕」錯誤。

第一個是與管道關聯的DACL(自由訪問控制列表)。這與Windows中任何安全對象上的DACL相同(c.f.文件安全性)。在列表中必須有一個訪問控制條目(ACE),授予您的客戶端用戶對管道的所需類型的訪問權限。正如您正確地指出的那樣,爲允許讀/寫訪問的「EVERYONE」SID添加ACE可以消除客戶端面臨的任何DACL障礙。但是,請注意,修改DACL的代碼必須已經具有WRITE_DAC對管道的訪問權限,否則將無法打開DACL可以修改的句柄。你的代碼甚至不會在對CreateNamedPipe的調用中請求WRITE_DAC訪問,所以這是你對SetSecurityInfo的調用失敗的另一個原因。

第二種機制是Windows Vista及更高版本中引入的強制性完整性控制機制。從您的描述中不清楚這是否正在發揮作用,但通常客戶端進程永遠不能寫入與低於該資源的完整性級別關聯的安全資源。如果這是問題(因爲您的標題專門針對Windows 7,我想它可能是)唯一的解決方案是更改管道上的強制完整性標籤以將管道的完整性等級降低到客戶端的完整性等級。爲此,您需要訪問由服務器打開的第一個管道句柄(this Q&A explains why),因爲完整性標籤是管道的系統訪問控制列表(SACL)中包含的特殊ACE,您需要WRITE_OWNER准予更改。是否在Qt中完全可行以獲得這個管柄是我不知道的東西。

+0

非常感謝那個提示。你說只有CreateNamedPipe的第一個實例的句柄具有WRITE_DAC/WRITE_OWNER權限。這意味着我無法改變Qt中管道的安全性,因爲我無法獲得該句柄。也許可以通過在用QLocalServer創建命名管道之前以某種方式更改進程標記來隱式設置MIC?那麼MIC是否會被管道繼承?似乎不可能用SetTokenInformation來改變MIC,還是我錯了? – bkausbk

7

我知道,現在有點晚了,但這可能會幫助其他人有同樣的問題。請注意,只有服務器是您的應用程序才能使用此解決方案。

如果是這種情況,只需在致電listen之前致電server.setSocketOptions(QLocalServer::WorldAccessOption);或其他值QLocalServer::​SocketOption之一。

+0

這是最好的解決方案 –

+0

謝謝,它工作。 – Szpaqn

+0

@Felix:這個解決方案在Qt 4中是不可能的。但是它可能會用在Qt 5和更新的版本中。 – bkausbk

相關問題