Credential Provider Filter の作成


新年あけましておめでとうございます。
PlatformSDK( Windows SDK) サポートの mitsuruw です。
本年もどうぞよろしくお願い申し上げます。

この年末年始は実家の奈良に帰郷しました。関東に出てきてもう 10 年以上になりますが、「奈良といえば大仏と鹿と奈良漬しかない」「”京都ではない” ほうの古都」といった内容を耳にする度に、奈良の魅力が正しく伝わっていない気がしてなりません。奈良には京都とはまた違った古都の魅力があるのです。

奈良は都道府県としては日本最多の世界文化遺産と国宝建造物を擁し、イチゴ・スイカ・柿の有数の産地でもあります。また、最近では正倉院展や燈花会などのイベントが目白押し、マニアックなところでは素麺の三大産地の一つでもあります(三輪素麺)。そうそう、全国金魚すくい選手権大会が実施されることも忘れてはなりません。

できればこのまま余すことなく奈良の魅力をお伝えしたいところなのですが、残念ながら本ブログは奈良の魅力をお伝えする趣旨ではありません。とても残念ですが、気を取りなおして前回ご紹介したCredential Provider Filter (CP Filter) についてもう少しお伝えしたいと思います。

 

Credential Provider Filter (CP Filter) について

前回 “Credential Provider による自動ログオン” でも少しご説明しましたが、Credential Provider で自動ログオンを行う場合、自分以外に自動ログオンを行う Credential Provider は存在していないことが前提となっています。これは、もし自分以外の Credential Provider も自動ログオンを実行しようとした場合、どちらのCredential Provider で自動ログオンを行えば良いか決定できず、その結果動作が不定となるためです。自動ログオンを行うことが前提となっているCredential Provider を登録する場合には、その他のCredential Provider を動作しないようにフィルタしておくのがお勧めです。

これを実現するためには ICredentialProviderFilter インターフェースを実装した COM を作成し、作成した COM の CLS ID を対象となるマシンのレジストリに登録する必要があります。

  Title : ICredentialProviderFilter Interface (Windows)
  URL : <http://msdn.microsoft.com/en-us/library/bb776004.aspx>

Credential Provider Filter (CPFilter) は基本的に ICredentialProviderFilter インターフェースのFilter メソッドと UpdateRemoteCredential メソッドを実装していれば問題ありませんが、今回は Visual Studio 2010 の Active Template Library (ATL) を使用した場合の CP Filter の簡単な作成方法についてご紹介したいと思います。

 

シンプルな CP Filter の作成手順 (CPFilter.dll)

Visual Studio 2010 を起動し、以下の手順でプロジェクトを作成します。

1) [ファイル] – [新規作成] – [プロジェクト] – [Visual C++] – [ATL] – [ATLプロジェクト] の作成 -> [完了]

2) [プロジェクト] – [クラスの追加] – [Visual C++] – [ATL] – [ATLシンプルオブジェクト] -> [追加]

3) オブジェクト名 C++ 短い名前 に “CFilterSample” を設定、その他はデフォルトで設定されるもの -> [完了]

4) stdafx.h に Credetial Provider 用のインクルードファイルを追加します。
  ——
  #include <CredentialProvider.h>
  ——

5) CFilterSample.h で CCFilterSample クラスに ICredentialProviderFilter インターフェースを追加します。

    5-1) ICredentialProviderFilter の追加
    ——
    class ATL_NO_VTABLE CCFilterSample :
      public CComObjectRootEx<CComSingleThreadModel>,
      public CComCoClass<CCFilterSample, &CLSID_CFilterSample>,
      public IDispatchImpl<ICFilterSample, &IID_ICFilterSample, &LIBID_filtersampleLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
      public ICredentialProviderFilter // <– 追加
    ——

    5-2) COM_INTERFACE_ENTRY の追加
    ——
    BEGIN_COM_MAP(CCMyFilter)
      COM_INTERFACE_ENTRY(ICMyFilter)
      COM_INTERFACE_ENTRY(IDispatch)
      COM_INTERFACE_ENTRY(ICredentialProviderFilter) //<– 追加
    END_COM_MAP()
    ——

  6) フィルタ処理の実装部分を追加します。

    6-1) Filter メソッドの実装
    ——
    class ATL_NO_VTABLE CCFilterSample :
        :
      void FinalRelease()
      {
      }
    public:
     :
      HRESULT STDMETHODCALLTYPE Filter( CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,DWORD
        dwFlags,GUID *rgclsidProviders, BOOL *rgbAllow, DWORD cProviders)
      {
        DWORD i ;

        // フィルタ対象の Credential Provider を GUID から判定する
        for( i = 0 ; i < cProviders ; i++ ){
          if( rgclsidProviders[ i ] がフィルタ対象の GUID) {
            rgbAllow[ i ] = FALSE ;
          }
        }    
         return S_OK ;
      }
     ——

Filter() メソッドの引数について:
rgclsidProviders には、システムに登録されている CP の GUID の配列が渡されます。rgbAllow は、利用可能かどうかを設定するための BOOL 型配列になります。これは  rgclsidProviders の配列とセットになっています。cProvidersは、配列のサイズです。
つまり、0 ~ cProviders – 1 まで rgclsidProviders[i] を参照して、フィルタしたい Credential Provider  の GUID がヒットした場合は、対応する rgbAllow[i] に FALSE(0) を設定してリターン  することで、対象の Credentil Provider をフィルタすることになります。

    6-2) UpdateRemoteCredential メソッドの実装
    ——
    public:
      HRESULT STDMETHODCALLTYPE UpdateRemoteCredential(
        const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcsIn,
        CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcsOut)
      {
        // 通常 UpdateRemoteCredential メソッドは利用しないため、単S_FALSE を返します。
        return S_FALSE ;
      }
    ——

  7) 上記プロジェクトをビルドします。

  8) コマンド プロンプトを起動し、作成された COM をターゲット環境のレジストリに登録します。
     “regsvr32 CPFilter.dll”

  9) ターゲット環境のレジストリに、CPFilter の CLSID を登録します。
  
     CPFilter の GUID は、プロジェクトの (追加したクラス名).rgs (例: CFilterSample.rgs)
     ファイルに記述されている以下の値になります。

     ForceRemove {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

   – HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters
     下に CPFilter の GUIDキーを追加します。
     
     {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

  10) COM の登録を解除する場合には、コマンド プロンプトを起動し、”regsvr32 /u CPFilter.dll” を実行します

今回は少し長くなってしまいましたが、CP Filter を利用すれば任意の Credentiel Provider のみ動作させることが可能です。自動ログオンを行う Credential Provider の開発を検討されている場合には、CP Filter も併せてご検討いただければと思います。

おまけ:
クイズです。CP Filter を使用してシステムに登録されているすべての Credential Provider をフィルタしてしまった場合、どのような状態になるでしょう?

a) CP Filter はフィルタ処理を行わない。
b) 特定の Credential Provider だけがフィルタしても表示される。
c) ログオン時にタイルが表示されずにログオンできなくなってしまう。
d) 上記以外。


Skip to main content