14

OLE オートメーション マーシャラーを使用する DCOM クライアントおよびサーバー アプリケーションがあります。同じ PC で実行すると正常に動作しますが、サーバーが同じドメインにない別の PC にある場合、E_ACCESSDENIED (0x80070005) が発生します。

サーバー PC は dcomcnfg で構成され、クライアントで指定したログインとパスワードを持つユーザーに、任意の DCOM オブジェクトへのすべてのアクセスを許可します。ServerApp とそのタイプ ライブラリは、サーバー pc に登録されます。

タイプ ライブラリもクライアント PC に登録されます。ClientApp でサーバー名を直接指定するので、私が理解している限り、クライアント PC で dcomcnfg の構成は必要ありません。

サーバー名、ログイン、ドメイン、およびパスワードを指定した CreateInstanceEx() は正常に機能します。IUnknown を返すと同時に、サーバー PC で ServerApp を起動します。

しかし、サーバーがサポートするインターフェースに対して QueryInterface() を実行しようとすると、E_ACCESSDENIED が返されます。

セキュリティ イベント ログを分析すると、次の 2 つのレコードがあります。

まず、ClientApp で指定した資格情報を持つユーザーによるネットワーク ログインが成功します。これは、CreateInstanceEx() を呼び出したときに発生します。

次に、クライアント PC にログインしているユーザーによるログイン試行の失敗。2 台の PC はドメインに属していないため、このユーザーはサーバー PC に認識されません。

さて、特に私がすべてのものの QueryInterface を呼び出すとき、なぜこのユーザーがサーバーにログインするのでしょうか?

CreateInterfaceEx パラメータを調べると、ある種のなりすましメカニズムが進行しているようです。しかし、誰が誰を偽装しているかは不明です。関連する 3 つのユーザー資格情報があります。

  1. サーバー PC で ServerApp を実行するユーザー (dcomcnfg で構成)。

  2. 接続時に ClientApp が指定する資格情報を持つユーザー。

  3. クライアント PC で ClientApp を実行する資格情報を持つユーザー。

どう見ても3番が絡むと1ユーザー多すぎ。とにかく DCOM がサーバー PC で #3 を識別/偽装する場合、なぜ #2 の資格情報を指定する必要があるのですか? どこまで?

DCOM が #2 になりすますのは理にかなっているように思えます。これは、資格情報として明示的に指定したものだからです。しかし、なぜ 2 回目のログイン試行を行うのでしょうか?

偽装がどのように機能するか、またそれを無視して dcomcnfg で指定されたユーザーとして実行する方法があるかどうかを誰かが説明してもらえますか?

4

2 に答える 2

13

私自身の質問に答えます。多くの調査の後、 DCOM には 2 つの異なる識別ケースがあることが明らかになりました。

  1. オブジェクト作成の認可 (CoCreateInstanceEx)
  2. メソッド呼び出しの承認。

理由は不明ですが、#2 は #1 の設定を継承しません。デフォルトでは、クライアント プロセスの資格情報を使用するため、奇妙なログインが発生します。

#2 の資格情報を指定するには、2 つの方法があります。最初のものはCoSetProxyBlanketです。指定されたプロキシ (マーシャラー-アンマーシャラー) のみの資格情報を設定します。

CoCreateInstanceEx(IID_IObject1, /*login, pass*/, obj1); //Success!
//Logged in and recevied IObject1 proxy in obj1

obj1->DoSomething();
//IObject1 proxy in obj1 now tries to login under process credentials.
//Failure! E_ACCESSDENIED

CoSetProxyBlanket(obj1, /*login, pass*/); //Success!
//IObject1 proxy is now authorized.

obj1->DoSomething(); //Success!
obj1->QueryInterface(IID_IObject2, obj2); //Success!

obj2->DoSomethingElse(); //Failure!
//This different proxy for IObject2 have not yet been authorized.

CoSetProxyBlanket(obj2, /*login, pass*/);
//etc.

CoCreateInstanceEx では偽装レベルが少なくとも IMPERSONATE である必要がありますが、CoSetProxyBlanket は IDENTIFY 以外では機能しないようです。

もう 1 つのオプションは、CoInitializeSecurityを使用して、プロセス全体の既定の資格情報を設定することです。次に、すべてのプロキシで CoSetProxyBlanket を呼び出す必要はありません。

CoInitializeSecurity(/* login, pass */);
CoCreateInstanceEx(IID_IUnknown, /*login, pass*/, obj); //Success!
obj->DoSomething(); //Success!

クライアントで CoInitializeSecurity を使用する場合は、asAuthSvcも指定する必要がありますが、MSDN では指定しないでください。

この方法の欠点は明らかに、異なる PC からの複数の DCOM オブジェクトがある場合、この呼び出しですべての資格情報を指定する必要があり、別のプロキシを開くたびにすべてのコンピューターに対してそれらの資格情報が試行されることです。

また、DLL から実行している場合も信頼できません (プロセスの既定のセキュリティが異なる場合はどうなるでしょうか?)。したがって、すべての呼び出しから戻る前に、CoSetsProxyBlanket を実行する QueryInterface ラッパーを実装する方がよいでしょう。

于 2011-05-25T13:37:17.567 に答える