IClientSecurity
COM公式ドキュメント
オブジェクトの各インターフェイスプロキシごとに、セキュリティ設定をクライアントが制御できるようにします。
解説(Remarks)
すべてのオブジェクトは 1 つのプロキシマネージャーを持ち、すべてのプロキシマネージャーは IClientSecurity インターフェイスを自動的に公開します。したがって、クライアントはオブジェクト上の任意のインターフェイスポインターを使用して、そのオブジェクトのプロキシマネージャーに対し IClientSecurity を照会できます。QueryInterface 呼び出しが成功すると、その IClientSecurity ポインターを使用して IClientSecurity のメソッドを呼び出し、クライアントが対象とするインターフェイスプロキシへのポインターを渡すことができます。IClientSecurity に対する QueryInterface の呼び出しが失敗した場合、そのオブジェクトはインプロセスで実装されているか、セキュリティをサポートしないカスタムマーシャラーによってリモート化されているかのいずれかです。(カスタムマーシャラーは、IClientSecurity インターフェイスをクライアントに提供することでセキュリティをサポートできます。)
IClientSecurity のメソッドにパラメーターとして渡すインターフェイスプロキシは、IClientSecurity インターフェイスと同じオブジェクトのものでなければなりません。つまり、各オブジェクトはそれぞれ固有の IClientSecurity インターフェイスを持ち、あるオブジェクトの IClientSecurity を呼び出す際に別のオブジェクトのプロキシを渡しても機能しません。また、プロキシを使用しないインターフェイスを IClientSecurity のメソッドに渡すことはできません。これは、プロキシマネージャーによってローカルに実装されるインターフェイスを IClientSecurity のメソッドに渡すことができないことを意味します。ただし、この規則の例外である IUnknown は除きます。
メソッド 3
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
指定したプロキシに対して呼び出しを行うためにクライアントが使用する認証情報を取得します。
| pProxy | IUnknown* | in | プロキシへのポインター。このパラメーターを NULL にすることはできません。詳細については、「解説」セクションを参照してください。 |
| pAuthnSvc | DWORD* | out | 現在の認証サービス。これは 認証サービス定数 の一覧から取得された単一の値になります。このパラメーターを NULL にすることはできません。 |
| pAuthzSvc | DWORD* | outoptional | 現在の承認サービス。これは 承認定数 の一覧から取得された単一の値になります。このパラメーターを NULL にすることはできません。 |
| pServerPrincName | WORD** | out | 現在のプリンシパル名。この文字列は CoTaskMemAlloc 関数を使用して呼び出し先によって割り当てられ、呼び出し元が CoTaskMemFree 関数を使用して解放する必要があります。実際のプリンシパル名が返される点に注意してください。プリンシパル名を変換するための EOAC_MAKE_FULLSIC フラグは受け付けられません。呼び出し元が NULL を指定した場合、現在のプリンシパル名は取得されません。 |
| pAuthnLevel | RPC_C_AUTHN_LEVEL* | outoptional | 現在の認証レベル。これは 認証レベル定数 の一覧から取得された単一の値になります。このパラメーターが NULL の場合、現在の認証レベルは取得されません。 |
| pImpLevel | RPC_C_IMP_LEVEL* | outoptional | 現在の偽装レベル。これは 偽装レベル定数 の一覧から取得された単一の値になります。このパラメーターが NULL の場合、現在の偽装レベルは取得されません。 |
| pAuthInfo | void** | out | 直近の IClientSecurity::SetBlanket 呼び出しで渡されたクライアントの識別情報 (または既定値) を示すハンドルへのポインター。既定値は、プロキシが解放されるまでの間のみ有効です。呼び出し元が NULL を指定した場合、クライアントの識別情報は取得されません。 返されたハンドルが参照する構造体の形式は、認証サービスによって異なります。NTLMSSP および Kerberos の場合、クライアントが CoInitializeSecurity の pAuthInfo パラメーターで構造体を指定していれば、その値が返されます。Schannel の場合、証明書マネージャーからクライアントの証明書を取得できたときは、その値がここに返されます。それ以外の場合は NULL が返されます。これは値そのものを指しておりコピーではないため、操作したり解放したりしてはなりません。 |
| pCapabilites | DWORD* | outoptional | プロキシの機能。これらのフラグは EOLE_AUTHENTICATION_CAPABILITIES 列挙体で定義されています。このパラメーターが NULL の場合、現在の機能フラグは取得されません。 |
戻り値
このメソッドは次の値を返すことがあります。
| 戻り値コード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 1 つ以上の引数が無効です。 | |
| pServerPrincName バッファーを作成するためのメモリが不足しています。 |
解説(Remarks)
QueryBlanket は、指定したインターフェイスプロキシから行われる呼び出しに COM が使用する認証情報を取得するために、クライアントから呼び出されます。プロキシ上のインターフェイスへのポインターを使って、クライアントはまず IClientSecurity へのポインターを得るために QueryInterface を呼び出します。次に、このポインターを使って QueryBlanket を呼び出し、その後ポインターを解放します。この一連の呼び出しは、ヘルパー関数 CoQueryProxyBlanket にカプセル化されています。
pProxy にはインターフェイスポインターを渡します。ただし、プロキシを使用しないインターフェイスへのポインターを渡すことはできません。したがって、インターフェイス定義に local キーワードが指定されたインターフェイスへのポインターを渡すことはできません。そのようなインターフェイスに対してはプロキシが作成されないためです。IUnknown はこの規則の例外です。
指定したプロキシに対して呼び出しを行う際に使用する認証情報 (セキュリティブランケット) を設定します。
| pProxy | IUnknown* | in | プロキシへのポインター。 |
| dwAuthnSvc | DWORD | in | 認証サービス。これは 認証サービス定数 の一覧から取得された単一の値になります。認証が不要な場合は RPC_C_AUTHN_NONE を使用します。RPC_C_AUTHN_DEFAULT を指定した場合、COM は通常のセキュリティブランケットネゴシエーションアルゴリズムに従って認証サービスを選択します。 |
| dwAuthzSvc | DWORD | in | 承認サービス。これは 承認定数 の一覧から取得された単一の値になります。RPC_C_AUTHZ_DEFAULT を指定した場合、COM は通常のセキュリティブランケットネゴシエーションアルゴリズムに従って承認サービスを選択します。認証サービスとして NTLMSSP、Kerberos、または Schannel を使用する場合は、承認サービスとして RPC_C_AUTHZ_NONE を使用してください。 |
| pServerPrincName | LPWSTR | inoptional | サーバープリンシパル名。COLE_DEFAULT_PRINCIPAL を指定した場合、DCOM はセキュリティブランケットネゴシエーションアルゴリズムを使用してプリンシパル名を選択します。認証サービスとして Kerberos を使用する場合、このパラメーターはサーバーの正しいプリンシパル名でなければならず、そうでない場合は呼び出しが失敗します。 認証サービスとして Schannel を使用する場合、この値は Principal Names で説明されている msstd 形式または fullsic 形式のいずれかであるか、相互認証を必要としない場合は NULL でなければなりません。 一般に、NULL を指定してもプロキシのサーバープリンシパル名はリセットされず、以前の設定が保持されます。プロキシに対して異なる認証サービスを選択する際に pServerPrincName として NULL を使用する場合は注意が必要です。以前に設定されたプリンシパル名が、新たに選択された認証サービスに対して有効であるという保証がないためです。 |
| dwAuthnLevel | RPC_C_AUTHN_LEVEL | in | 認証レベル。これは 認証レベル定数 の一覧から取得された単一の値になります。RPC_C_AUTHN_LEVEL_DEFAULT を指定した場合、COM は通常のセキュリティブランケットネゴシエーションアルゴリズムに従って認証レベルを選択します。この値を RPC_C_AUTHN_LEVEL_NONE に設定した場合、認証サービスは RPC_C_AUTHN_NONE でなければなりません。各認証サービスは、指定された認証レベルよりも高いセキュリティの認証レベルを使用することを選択する場合があります。 |
| dwImpLevel | RPC_C_IMP_LEVEL | in | 偽装レベル。これは 偽装レベル定数 の一覧から取得された単一の値になります。RPC_C_IMP_LEVEL_DEFAULT を指定した場合、COM は通常のセキュリティブランケットネゴシエーションアルゴリズムに従って偽装レベルを選択します。NTLMSSP をリモートで使用する場合、この値は RPC_C_IMP_LEVEL_IMPERSONATE または RPC_C_IMP_LEVEL_IDENTIFY でなければなりません。同一コンピューター上で NTLMSSP を使用する場合は、RPC_C_IMP_LEVEL_DELEGATE もサポートされます。Kerberos の場合、この値は RPC_C_IMP_LEVEL_IDENTIFY、RPC_C_IMP_LEVEL_IMPERSONATE、または RPC_C_IMP_LEVEL_DELEGATE のいずれかにできます。Schannel の場合、この値は RPC_C_IMP_LEVEL_IMPERSONATE でなければなりません。 |
| pAuthInfo | void* | inoptional | クライアントの識別情報を示す RPC_AUTH_IDENTITY_HANDLE 値。このパラメーターは、同一コンピューター上での呼び出しでは使用されません。pAuthInfo が NULL の場合、COM は現在のプロキシ識別情報を使用します。これはプロセストークン、偽装トークン、または CoInitializeSecurity 関数からの認証識別情報のいずれかです。ハンドルが NULL でない場合は、その識別情報が使用されます。ハンドルが参照する構造体の形式は、認証サービスのプロバイダーによって異なります。 NTLMSSP または Kerberos の場合、この構造体は SEC_WINNT_AUTH_IDENTITY 構造体または SEC_WINNT_AUTH_IDENTITY_EX 構造体です。クライアントが CoQueryProxyBlanket を呼び出してプロキシに設定された資格情報を取得する場合は、別の識別情報がプロキシに設定されるか、そのオブジェクトのすべてのプロキシが解放されるまで、そのメモリが有効で変更されないままであることを保証しなければなりません。 このパラメーターが NULL の場合、COM は現在のプロキシ識別情報 (プロセストークンまたは偽装トークンのいずれか) を使用します。ハンドルが構造体を参照している場合は、その識別情報が使用されます。 Schannel の場合、このパラメーターは、クライアントの X.509 証明書を含む CERT_CONTEXT 構造体へのポインターであるか、クライアントがサーバーへの匿名接続を行いたい場合は NULL でなければなりません。証明書を指定する場合、呼び出し元は、現在のアパートメント内にそのオブジェクトへのプロキシが存在する限り、それを解放してはなりません。 Snego の場合、このメンバーは NULL であるか、SEC_WINNT_AUTH_IDENTITY 構造体を指すか、SEC_WINNT_AUTH_IDENTITY_EX 構造体を指します。NULL の場合、Snego はクライアントコンピューターで利用可能なものに基づいて認証サービスの一覧を選択します。SEC_WINNT_AUTH_IDENTITY_EX 構造体を指す場合、その構造体の PackageList メンバーは、認証サービス名をコンマ区切りにした一覧を含む文字列を指す必要があり、PackageListLength メンバーはその PackageList 文字列のバイト数を示す必要があります。PackageList が NULL の場合、Snego を使用するすべての呼び出しは失敗します。 COLE_DEFAULT_AUTHINFO を指定した場合、COM は通常のセキュリティブランケットネゴシエーションアルゴリズムに従って認証情報を選択します。 pAuthInfo が設定されており、かつ dwCapabilities にクローキングフラグのいずれかが設定されている場合、SetBlanket はエラーを返します。 |
| dwCapabilities | DWORD | in | このプロキシの機能。機能フラグは EOLE_AUTHENTICATION_CAPABILITIES 列挙体で定義されています。このメソッドで設定できるフラグは、EOAC_MUTUAL_AUTH、EOAC_STATIC_CLOAKING、EOAC_DYNAMIC_CLOAKING、EOAC_ANY_AUTHORITY (このフラグは非推奨)、EOAC_MAKE_FULLSIC、および EOAC_DEFAULT のみです。pAuthInfo が設定されておらず、かつ認証サービスが Schannel でない場合は、EOAC_STATIC_CLOAKING または EOAC_DYNAMIC_CLOAKING のいずれかを設定できます。(詳細については「Cloaking」を参照してください。) ここに記載されていない機能フラグが指定された場合、SetBlanket はエラーを返します。 |
戻り値
このメソッドは次の値を返すことがあります。
| 戻り値コード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 1 つ以上の引数が無効です。 |
解説(Remarks)
SetBlanket は、指定したインターフェイスプロキシに対して呼び出しを行う際に使用される認証情報を設定します。ここで指定された値は、自動セキュリティによって選択された値を上書きします。このメソッドを呼び出すと、指定したプロキシを使用する他のすべての利用者に対してもセキュリティ値が変更されます。変更を特定のプロキシインスタンスにのみ適用したい場合は、IClientSecurity::CopyProxy を呼び出してプロキシのプライベートなコピーを作成し、そのコピーに対して SetBlanket を呼び出します。
このメソッドが呼び出されるたびに、DCOM はプロキシに識別情報を設定し、このプロキシを使用して以降に行われる呼び出しではこの識別情報が使用されます。SetBlanket が呼び出された時点で進行中の呼び出しは、呼び出し開始時にプロキシに設定されていた認証情報を使用します。pAuthInfo が NULL の場合、プロキシの識別情報は既定で現在のプロセストークンになります (ただし、CoInitializeSecurity の呼び出しで認証識別情報が指定されていた場合を除く)。pAuthInfo が NULL のときにクローキングフラグがプロキシにどのように影響するかについては、「Cloaking」を参照してください。
既定では、COM はクライアントコンピューターとサーバーコンピューターの両方で利用可能な最初の認証サービスおよび承認サービスと、その認証サービスに対してサーバーが登録したプリンシパル名を選択します。現在のところ、COM は最初の認証サービスが失敗しても別の認証サービスを試行しません。
SetBlanket で dwImpLevel に既定の定数が指定された場合、このパラメーターは CoInitializeSecurity に指定された値を既定とします。CoInitializeSecurity が呼び出されていない場合は、既定で RPC_C_IMP_LEVEL_IDENTIFY になります。
プロキシ上の dwAuthnLevel の初期値は、クライアントの CoInitializeSecurity 呼び出しで設定された値と、サーバーの CoInitializeSecurity 呼び出しで設定された値のうち、高い方になります。CoInitializeSecurity を呼び出さなかったプロセスの場合、既定の認証レベルは RPC_C_AUTHN_CONNECT です。
CoInitializeSecurity を呼び出さないプロセスの既定の認証レベルおよび偽装レベルは、DCOMCNFG で設定できます。
dwCapabilities に EOAC_DEFAULT を指定した場合、CoInitializeSecurity の有効な機能が使用されます。CoInitializeSecurity が呼び出されていない場合、機能フラグには EOAC_NONE が使用されます。
同じプロキシに対して 2 つのスレッドで同時に SetBlanket が呼び出された場合、適用される変更は 1 組のみです。同じプロキシに対して 2 つのスレッドで SetBlanket と CRpcOptions::Set が同時に呼び出された場合、両方の変更が適用されることもあれば、片方のみが適用されることもあります。
IClientSecurity インターフェイスのようなローカルインターフェイスには、セキュリティ情報を設定できません。ただし、そのインターフェイスはローカルでのみサポートされるため、セキュリティは不要です。IUnknown と IMultiQI は特別なケースです。ロケーション実装は、これらのインターフェイスをサポートするためにリモート呼び出しを行います。SetBlanket は IUnknown に対して使用できます。IMultiQI は IUnknown のセキュリティ設定を使用します。
SetBlanket の 1 つのパラメーターを他のパラメーターに対処せずに変更するには、他のパラメーターに既定の定数を指定できます。アプリケーションは、他のすべてのパラメーターを既定の定数に設定することで、認証サービスを含む他のパラメーターを無視して、あるパラメーター (認証レベルなど) を変更できます。
既定値は明白でないことが多いため、使用しないパラメーターはすべて既定の定数に設定することが重要である点に注意してください。特に、認証サービスを既定に設定する場合は、認証情報とプリンシパル名も既定に設定すべきです。その理由は 2 つあります。第 1 に、認証情報の型は DCOM が選択する認証サービスに依存します。第 2 に、DCOM は特定の認証サービスに対して複雑な認証情報を渡す必要があるため、認証サービスを既定に設定し、認証情報を NULL に設定すると、機能しないセキュリティ設定になる可能性があるためです。
指定したインターフェイスのプロキシのプライベートなコピーを作成します。
| pProxy | IUnknown* | in | プロキシをコピーする対象のインターフェイスへのポインター。このパラメーターを NULL にすることはできません。 |
| ppCopy | IUnknown** | out | プロキシのコピーを受け取る IUnknown インターフェイスポインターへのポインター。このパラメーターを NULL にすることはできません。 |
戻り値
このメソッドは次の値を返すことがあります。
| 戻り値コード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 1 つ以上の引数が無効です。 |
解説(Remarks)
CopyProxy は、指定したインターフェイスのプロキシのプライベートなコピーを作成するために、クライアントから呼び出されます。プロキシのコピーは、認証情報に既定値を持ちます。その認証情報は、元のプロキシの他のクライアントに影響を与えることなく、IClientSecurity::SetBlanket の呼び出しによって変更できます。コピーは参照カウントを 1 つ持ち、CopyProxy の呼び出し元は、そのプロキシのコピーが確実に解放されるようにしなければなりません。
IUnknown や IClientSecurity のようなローカルインターフェイスはコピーできません。CopyProxy を使用してプロキシマネージャーを複製することはできません。
同じプロキシのコピーどうしは、QueryInterface に関して特別な関係を持ちます。リモートオブジェクトの IA インターフェイスのプロキシを a とし、a のコピーを作成して b と呼ぶとします。この場合、b プロキシから IID_IA に対して QueryInterface を呼び出すと、b 上の IA インターフェイスではなく、元のプロキシである a 上の IA インターフェイスが取得されます。
誰でもプロキシを照会し、SetBlanket を使用してそのセキュリティを変更できる点に注意してください。ただし、プロキシのコピーを作成した場合、それを他者に渡さない限り、誰もそのコピーを取得できません。そのコピーを持つ者だけが、そのコピーにセキュリティを設定できます。
ヘルパー関数 CoCopyProxy は、IClientSecurity へのポインターに対する QueryInterface 呼び出し、その IClientSecurity ポインターを使用した CopyProxy の呼び出し、および IClientSecurity ポインターの解放をカプセル化します。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IClientSecurity "{0000013D-0000-0000-C000-000000000046}" #usecom global IClientSecurity IID_IClientSecurity "{}" #comfunc global IClientSecurity_QueryBlanket 3 sptr,var,var,var,var,var,sptr,var #comfunc global IClientSecurity_SetBlanket 4 sptr,int,int,wstr,int,int,sptr,int #comfunc global IClientSecurity_CopyProxy 5 sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IClientSecurity "{0000013D-0000-0000-C000-000000000046}" #usecom global IClientSecurity IID_IClientSecurity "{}" #comfunc global IClientSecurity_QueryBlanket 3 sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #comfunc global IClientSecurity_SetBlanket 4 sptr,int,int,wstr,int,int,sptr,int #comfunc global IClientSecurity_CopyProxy 5 sptr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。