ヘッダーをスキップ
Oracle Fusion Middleware Oracle Internet Directory管理者ガイド
11gリリース1(11.1.1)
B55919-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

42 カスタマイズされたパスワード・ポリシー・プラグインの構成

Oracle Internet Directoryは、プラグインを使用して、パスワード値のチェックを他のパスワード・ポリシー管理機能に追加します。このプラグインを使用すると、追加または変更されたパスワードが、指定された最小文字数以上であるかどうかなどを確認できます。個別の要件に合せて、パスワード値チェックをカスタマイズできます。

この章の項目は次のとおりです。

42.1 カスタマイズされたパスワード・ポリシー・プラグインの概要

パスワードを追加または変更する場合、カスタマイズされたパスワード値チェックが次のように処理されます。

  1. クライアントが、ldapaddリクエストまたはldapmodifyリクエストをディレクトリ・サーバーに送信します。

  2. ディレクトリ・サーバーは、追加または変更を行う前にパスワード値をプラグインに渡します。

  3. プラグインは次のように動作します。

    1. エントリを解析

    2. クリア・テキストのuserpassword属性値を取得

    3. 指定したパスワード値チェックを実施

  4. パスワードが指定と一致する場合は、そのことがプラグインによってディレクトリ・サーバーに通知され、ディレクトリ・サーバーによって追加または変更が行われます。

    一致しない場合は、次のいずれかのエラー・メッセージがプラグインによってディレクトリ・サーバーに送信され、その後、ディレクトリ・サーバーからクライアントに渡されます。

    ldap_add: UnKnown Error Encountered
    ldap_add: additional info: PASSWORD POLICY VIOLATION:0000X, less than 8 chars
    
    ldap_add: UnKnown Error Encountered
    ldap_add: additional info: PASSWORD POLICY VIOLATION:0000X, contains dictionary word
    

    同じロジックがPRE ldapmodifyプラグインにも適用されます。

パスワード・ポリシー・プラグインが実行できる値チェックには、次のような種類があります。

42.2 カスタマイズされたパスワード・ポリシー・プラグインのインストール、構成および有効化

この例は、PL/SQLプログラムpluginpkg.sqlを使用しています。「サンプルPL/SQLパッケージpluginpkg.sqlの内容」でこのプログラムについて説明します。通常、このパッケージには次のものが含まれます。

この例では、ユーザーが8文字未満のuserpassword値を入力すると、リクエストは拒否されます。同様に、ユーザー・パスワードを変更する際に、新しいパスワード値が8文字未満の場合はリクエストが拒否されます。また、userpasswordの値supersundayを使用してユーザー・パスワードを登録または変更しようとすると、superおよびsundayが辞書にあるため、そのパスワードは拒否されます。

辞書は5文字以上の語句のリストで、最初はwords.txtというファイルに保存されます。プラグインを実装する場合は、その前にデータベース・テーブルを設定し、語句を格納しておきます。テーブルを設定するには、create.sqlを使用します。その内容は次のとおりです。

drop table mydic;
create table mydic (word varchar2(1024));
commit;
exit;

続いて、次のsqlldrコマンドを使用して語句をテーブルに格納します。

sqlldr control=words.txt userid=ods/ods_password

この項の項目は次のとおりです。

42.2.1 PL/SQLプログラムのロードおよび登録

スタンドアロンの値チェックPL/SQLプログラムを実装したら、次の手順を実行します。

  1. プラグイン・パッケージをデータベースにロードします。この例では、次のように入力します。

    sqlplus ods @pluginpkg.sql
    
  2. プラグインを登録します。この例では、次の内容のファイルpluginreg.datを使用します。

    ### add plugin ###
    dn: cn=pre_add_plugin,cn=plugin,cn=subconfigsubentry
    objectclass:orclPluginConfig
    objectclass:top
    orclpluginname:pwd_plugin
    orclplugintype:configuration
    orclplugintiming:pre
    orclpluginldapoperation:ldapadd
    orclpluginenable:1
    orclpluginversion:1.0.1
    cn:pre_add_plugin
    orclpluginsubscriberdnlist:dc=com;o=IMC ,c=US
    
    ### modify plugin ###
    dn: cn=pre_mod_plugin,cn=plugin,cn=subconfigsubentry
    objectclass:orclPluginConfig
    objectclass:top
    orclpluginname:pwd_plugin
    orclplugintype:configuration
    orclplugintiming:pre
    orclpluginldapoperation:ldapmodify
    orclpluginenable:1
    orclpluginversion:1.0.1
    cn:pre_mod_plugin
    orclpluginsubscriberdnlist:dc=com;o=IMC ,c=US
    orclpluginattributelist:userpassword
    

    このプラグインでは、ldapaddリクエストまたはldapmodifyリクエストを受け取った際に起動する2つのプラグイン・モジュールをディレクトリ・サーバーに認識させています。ターゲット・エントリがdc=comまたはo=IMC,c=US下の場合のみプラグインが起動するように、orclpluginsubscriberdnlist:dc=com;o=IMC,c=USを使用しています。

    このファイルをディレクトリに追加するには、次のとおり入力します。

    ldapadd -p portnum -h hostname -D cn=orcladmin -q -v -f pluginreg.dat
    

42.2.2 パスワード・ポリシー・プラグインのコード化

標準PL/SQL文字ファンクションを使用して、パスワード値を処理できます。正規表現を行うPL/SQLプログラムをダウンロードします。値チェック・ファンクションとプラグイン・モジュールを統合することが重要です。

42.2.3 パスワード・ポリシー・プラグインのデバッグ

ディレクトリ・サーバー・プラグインを設定すると、プラグインのプロセスと内容を調べることができます。

ディレクトリ・サーバー・プラグインのデバッグを設定するには、次のコマンドを実行します。

sqlplus ods @$ORACLE_HOME/ldap/admin/oidspdsu.pls

ディレクトリ・サーバー・プラグインのデバッグを有効にするには、次のコマンドを実行します。

sqlplus ods @$ORACLE_HOME/ldap/admin/oidspdon.pls

ディレクトリ・サーバー・プラグインのデバッグを無効にするには、次のコマンドを実行します。

sqlplus ods @$ORACLE_HOME/ldap/admin/oidspdof.pls

ディレクトリ・サーバー・プラグインのデバッグ・メッセージを表示するには、次のコマンドを実行します。

sqlplus ods @$ORACLE_HOME/ldap/admin/oidspdsh.pls

ディレクトリ・サーバー・プラグインのデバッグ・メッセージを削除するには、次のコマンドを実行します。

sqlplus ods @$ORACLE_HOME/ldap/admin/oidspdde.pls

42.2.4 サンプルPL/SQLパッケージpluginpkg.sqlの内容

この例で使用するスクリプトpluginpkg.sqlの内容は次のとおりです。

CREATE OR REPLACE PACKAGE pwd_plugin AS

PROCEDURE pre_add (ldapplugincontext IN  ODS.plugincontext,
                   dn       IN  VARCHAR2,
                   entry    IN  ODS.entryobj,
                   rc       OUT INTEGER,
                   errormsg OUT VARCHAR2
                   );

PROCEDURE pre_modify (ldapplugincontext IN  ODS.plugincontext,
                      dn       IN  VARCHAR2,
                      mods     IN  ODS.modlist,
                      rc       OUT INTEGER,
                      errormsg OUT VARCHAR2
                      );

-- Function: isGoodPwd
-- Parameter: inpwd
-- Purpose: 1. check if the password is at least
--          8 characters long
--          2. check if the password contains a
--          dictionary word (longer than 4 characters)

FUNCTION isGoodPwd(inpwd IN VARCHAR2)
  RETURN INTEGER;


END pwd_plugin;
/

show error

CREATE OR REPLACE PACKAGE BODY pwd_plugin AS

FUNCTION isGoodPwd(inpwd IN VARCHAR2)
  RETURN INTEGER
  IS
     i NUMBER;
     ret NUMBER DEFAULT 1;
     minpwdlen NUMBER DEFAULT 8;
     len       NUMBER DEFAULT 0;
     lcount    NUMBER DEFAULT 0;
     matched   VARCHAR2(1024) DEFAULT NULL;

     CURSOR c1 IS
     SELECT word FROM mydic WHERE length(word) > 4
     AND instr(lower(inpwd), lower(word), 1, 1) > 0;

BEGIN
   plg_debug( '=== begin of ISGOODPWD ===');
   plg_debug( 'password = ' || inpwd);
   len := LENGTH(inpwd);
   plg_debug( 'password length = ' || len);

   IF len < minpwdlen THEN
      RETURN 0;
    ELSE
      OPEN c1;
      LOOP
        FETCH c1 INTO matched;
        EXIT WHEN c1%NOTFOUND;
        lcount := lcount + 1;
      END LOOP;
      plg_debug( 'count = ' || lcount);
      IF lcount > 0 THEN
        RETURN 2;
      ELSE
        RETURN ret;
      END IF;
   END IF;

   plg_debug( '=== end of ISGOODPWD ===');

EXCEPTION
   WHEN OTHERS THEN
      plg_debug( 'Exception in isGoodPwd(). Error code is ' || TO_CHAR(SQLCODE));
      plg_debug( '   ' || Sqlerrm);
      RETURN 0;
END;


PROCEDURE pre_add (ldapplugincontext IN  ODS.plugincontext,
                   dn       IN  VARCHAR2,
                   entry    IN  ODS.entryobj,
                   rc       OUT INTEGER,
                   errormsg OUT VARCHAR2
                   )
  IS
     inpwd VARCHAR2(256) DEFAULT NULL;
     ret   NUMBER        DEFAULT 1;
BEGIN
   plg_debug( '=== begin of PRE_ADD_PLUGIN ===');
   plg_debug( 'dn = ' || dn);

   plg_debug( 'entry obj ' || ':entryname = ' || entry.entryname);

   FOR l_counter1 IN 1..entry.attr.COUNT LOOP
      plg_debug( 'attrname[' || l_counter1 || '] = ' ||
                 entry.attr(l_counter1).attrname);
      FOR l_counter2 IN 1..entry.attr(l_counter1).attrval.COUNT LOOP
         plg_debug( entry.attr(l_counter1).attrname ||
                    '[' || l_counter1 || ']' ||
                    '.val[' || l_counter2 || '] = ' ||
                    entry.attr(l_counter1).attrval(l_counter2));
      END LOOP;

      IF entry.attr(l_counter1).attrname = 'userpassword' THEN
         inpwd := entry.attr(l_counter1).attrval(1);
         -- assuming only one attr val for userpassword
      END IF;

   END LOOP;

   IF (inpwd IS NOT NULL) THEN
      ret := isGoodPwd(inpwd);
   END IF;

   IF (inpwd IS NULL OR ret = 0) THEN
      rc := 1;
      errormsg := 'PASSWORD POLICY VIOLATION:0000X, less than 8 chars';
      plg_debug( ' we got an invalid password, too short ');
    ELSIF (ret = 2) THEN
      rc := 1;
      errormsg := 'PASSWORD POLICY VIOLATION:0000X, contains dictionary word';
      plg_debug( ' we got an invalid password, dictionary word ');
    ELSE
      plg_debug( ' we got a good password ');
      rc := 0;
      errormsg := 'no pre_mod plguin error msg';
   END IF;

   plg_debug( '=== end of PRE_ADD_PLUGIN ===');

EXCEPTION
   WHEN OTHERS THEN
      plg_debug( 'Exception in PRE_ADD plugin. Error code is ' || TO_CHAR(SQLCODE));
      plg_debug( '   ' || Sqlerrm);
      rc := 1;
      errormsg := 'exception: pre_add plguin';
END;

PROCEDURE pre_modify (ldapplugincontext IN  ODS.plugincontext,
                      dn       IN  VARCHAR2,
                      mods     IN  ODS.modlist,
                      rc       OUT INTEGER,
                      errormsg OUT VARCHAR2
                      )
  IS
     old_passwd VARCHAR2(256) DEFAULT NULL;
     new_passwd VARCHAR2(256) DEFAULT NULL;
     ret        NUMBER        DEFAULT 1;

BEGIN
   plg_debug( '=== begin of PRE_MOD_PLUGIN ===');
   plg_debug( dn);

   FOR l_counter1 IN 1..mods.COUNT LOOP
      IF (mods(l_counter1).operation = 2) AND
        (mods(l_counter1).type = 'userpassword') THEN

         FOR l_counter2 IN 1..mods(l_counter1).vals.COUNT LOOP
            new_passwd := mods(l_counter1).vals(l_counter2).val;
         END LOOP;
      END IF;

      IF (mods(l_counter1).operation = 0) AND
        (mods(l_counter1).type = 'userpassword') THEN

         FOR l_counter2 IN 1..mods(l_counter1).vals.COUNT LOOP
            new_passwd := mods(l_counter1).vals(l_counter2).val;
         END LOOP;
      END IF;

      IF (mods(l_counter1).operation = 1) AND
        (mods(l_counter1).type = 'userpassword') THEN

         FOR l_counter2 IN 1..mods(l_counter1).vals.COUNT LOOP
            old_passwd := mods(l_counter1).vals(l_counter2).val;
         END LOOP;
      END IF;
   END LOOP;

   plg_debug(' new password: ' || new_passwd);
   plg_debug(' old password: ' || old_passwd);

   IF (new_passwd IS NOT NULL) THEN
      ret := isGoodPwd(new_passwd);
   END IF;

   IF (new_passwd IS NULL OR ret = 0) THEN
      rc := 1;
      errormsg := 'PASSWORD POLICY VIOLATION:0000X, less than 8 chars';
      plg_debug( ' we got an invalid password, too short ');
    ELSIF (ret = 2) THEN
      rc := 1;
      errormsg := 'PASSWORD POLICY VIOLATION:0000X, contains dictionary word';
      plg_debug( ' we got an invalid password, dictionary word ');
    ELSE
      plg_debug( ' we got a good password ');
      rc := 0;
      errormsg := 'no pre_mod plguin error msg';
   END IF;

   plg_debug( '=== end of PRE_MOD_PLUGIN ===');

EXCEPTION
   WHEN OTHERS THEN
      plg_debug( 'Exception in PRE_MODIFY plugin. Error code is ' || TO_CHAR(SQLCODE));
      plg_debug( '   ' || Sqlerrm);
      rc := 1;
      errormsg := 'exception: pre_mod plguin';
END;

END pwd_plugin;
/
show error


EXIT;