3

Qt4.8.1のMicrosoftWindows7実装で次の問題が発生します。

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
}

NewAclNULLに設定されている場合でも、呼び出しは失敗します。では、その「アクセス拒否」エラーの原因は何でしょうか。

4

3 に答える 3

7

今は少し遅いですが、これは同じ問題を抱えている他の人々を助けるかもしれません。このソリューションは、サーバーがアプリケーションである場合にのみ機能することに注意してください。

その場合は、を呼び出す前にserver.setSocketOptions(QLocalServer::WorldAccessOption);、またはの他の値の1つを呼び出すだけです。QLocalServer::​SocketOptionlisten

于 2015-02-01T17:27:04.663 に答える
2

私はQtに精通していないため、このようにQtLocalServerを使用した場合にデフォルトで作成されるセキュリティ特性がわかりません。ただし、一般に、「アクセスが拒否されました」エラーを引き起こす可能性のある2つの異なるメカニズムがあります。

1つ目は、パイプに関連付けられたDACL(任意アクセス制御リスト)です。これは、Windowsのセキュリティ保護可能なオブジェクトのDACLと同じように機能します(ファイルセキュリティを参照)。リストには、クライアントユーザーにパイプへの目的のタイプのアクセスを許可するアクセス制御エントリ(ACE)が含まれている必要があります。正しく示しているように、読み取り/書き込みアクセスを許可する「EVERYONE」SIDにACEを追加すると、クライアントが直面しているDACLバリアがすべて削除されます。ただし、DACLを修正するコードは、パイプへのWRITE_DACアクセスをすでに持っている必要があることに注意してください。そうしないと、DACLを修正できるハンドルを開くことができません。あなたのコードはCreateNamedPipeへの呼び出しでWRITE_DACアクセスさえ要求しないので、これがSetSecurityInfoへの呼び出しが失敗するさらなる理由です。

2番目のメカニズムは、WindowsVista以降のバージョンで導入された必須整合性制御メカニズムです。これがここで機能しているかどうかは説明からは明らかではありませんが、一般に、クライアントプロセスは、リソースよりも低い整合性レベルに関連付けられているセキュリティ保護可能なリソースへの書き込みアクセス権を持つことはできません。それがここでの問題である場合(そして、タイトルが特にWindows 7を参照しているため、おそらくそうかもしれません)、唯一の解決策は、パイプの必須整合性ラベルを変更して、パイプの整合性レベルをクライアントの整合性レベルに下げることです。これを行うには、サーバーによって開かれた最初のパイプハンドルにアクセスする必要があります(このQ&Aは理由を説明しています)整合性ラベルは、パイプのシステムアクセス制御リスト(SACL)に含まれる特別なACEであるため、変更するにはWRITE_OWNER権限が必要です。Qtでこのパイプハンドルを手に入れることがまったく可能かどうかは、私にはわかりません。

于 2012-05-25T07:27:26.793 に答える
1

Qtの問題の解決策を見つけました。CreateNamedPipeQLocalServer :: listen()を呼び出した後に作成されたハンドルを使用できないため、CreateNamedPipeQtが実行する前に呼び出すことができます。と呼べばWRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE何でも変えられます。

次に、ChrisDicksonが述べたようにセキュリティ設定を変更できます。

于 2012-05-29T06:02:35.400 に答える