A.5 PL/SQLサーバー・プラグイン開発者リファレンス
次の各項では、これについてさらに詳しく説明しています。
A.5.1 PL/SQLサーバー・プラグインの設計、作成および使用
PL/SQLサーバー・プラグインを設計、作成および使用できます。
この項では、次の項目について説明します。
A.5.1.1 PL/SQLプラグインの注意事項
PL/SQLプラグインは、特定の操作にのみ関連付けることができます。また、プラグインが他のプラグインやストアド・プロシージャと同じデータベース・スキーマを共有する場合、そのプラグインの名前(PL/SQLパッケージ名)は一意であることが必要です。次の各項では、これについてさらに詳しく説明しています。
A.5.1.1.1 PL/SQLプラグイン操作のタイプ
PL/SQLプラグインは、ldapbind
、ldapadd
、ldapmodify
、ldapcompare
、ldapsearch
およびldapdelete
の各操作にのみ関連付けることができます。PL/SQLプラグインをmoddn
に関連付けることはできません。プラグインをmoddn
に関連付ける場合には、Javaプラグインを使用する必要があります。
A.5.1.2 PL/SQLプラグインのパッケージ名とプロシージャの仕様
PL/SQLプラグイン・モジュールの作成は、PL/SQLパッケージの作成と似ています。いずれも、仕様部分と本文に分かれています。この仕様はOracle Internet Directoryとカスタム・プラグインを接続するインタフェースの役割を果たすため、プラグインではなくディレクトリによってプラグインの仕様が決まります。
セキュリティ上およびLDAPサーバーの整合性の理由から、PL/SQLプラグインをコンパイルできるのはODSデータベース・スキーマにおいてのみです。これらを、Oracle Internet Directoryのバックエンド・データベースの役割を果すデータベースにコンパイルする必要があります。次の各項で、さらに詳しく説明します。
A.5.1.2.1 プラグイン・パッケージ名の仕様
パッケージ仕様はプラグインによって異なります。表A-19に示すように、プラグイン・パッケージには名前を指定できます。ただし、プラグイン・プロシージャの各タイプに定義されているシグネチャには従う必要があります。詳細は、「PL/SQLプラグイン・プロシージャの仕様」を参照してください。
表A-19 プラグイン・モジュール・インタフェース
プラグイン項目 | ユーザー定義 | Oracle Internet Directoryで定義 |
---|---|---|
プラグイン・パッケージ名 |
X |
|
プラグイン・プロシージャ名 |
X |
|
プラグイン・プロシージャのシグネチャ |
X |
A.5.1.2.2 プラグイン・プロシージャの仕様
表A-20に、様々なプラグイン・プロシージャを示します。また、各プロシージャで使用されるパラメータについても説明します。
表A-20 操作ベースと属性ベースのプラグイン・プロシージャのシグネチャ
起動コンテキスト | プロシージャ名 | INパラメータ | OUTパラメータ |
---|---|---|---|
|
PRE_BIND |
ldapcontext、Bind DN、Password |
return code、error message |
|
WHEN_BIND_REPLACE |
ldapcontext、bind result、DN、userpassword |
bind result、return code、error message |
|
POST_BIND |
ldapcontext、Bind result、Bind DN、Password |
return code、error message |
|
PRE_MODIFY |
ldapcontext、DN、Mod structure |
return code、error message |
|
WHEN_MODIFY |
ldapcontext、DN、Mod structure |
return code、error message |
|
WHEN_MODIFY_REPLACE |
ldapcontext、DN、Mod structure |
return code、error message |
|
POST_MODIFY |
ldapcontext、Modify result、DN、Mod structure |
return code、error message |
|
PRE_COMPARE |
ldapcontext、DN、attribute、value |
return code、error message |
|
WHEN_COMPARE_REPLACE |
ldapcontext、Compare result、DN、attribute、value |
compare result、return code、error message |
|
POST_COMPARE |
ldapcontext、Compare result、DN、attribute、value |
return code、error message |
|
PRE_ADD |
ldapcontext、DN、Entry |
return code、error message |
|
WHEN_ADD |
ldapcontext、DN、Entry |
return code、error message |
|
WHEN_ADD_REPLACE |
ldapcontext、DN、Entry |
return code、error message |
|
POST_ADD |
ldapcontext、Add result、DN、Entry |
return code、error message |
|
PRE_DELETE |
ldapcontext、DN |
return code、error message |
|
WHEN_DELETE |
ldapcontext、DN |
return code、error message |
|
WHEN_DELETE |
ldapcontext、DN |
return code、error message |
|
POST_DELETE |
ldapcontext、Delete result、DN |
return code、error message |
|
PRE_SEARCH |
ldapcontext、Base DN、scope、filter |
return code、error message |
|
POST_SEARCH |
Ldap context、Search result、Base DN、scope、filter |
return code、error message |
関連項目:
-
リターン・コードとエラー・メッセージの有効な値については、「OIDのエラー・メッセージとリターン・コード」を参照してください。
-
サポート対象のプロシージャ・シグネチャの詳細は、「PL/SQLプラグイン・プロシージャの仕様」を参照してください。
A.5.1.3 PL/SQLプラグインのコンパイル
Oracle Internet Directoryのバックエンド・データベースと同じ役割を果たすデータベースに対して、プラグイン・モジュールをコンパイルする必要があります。プラグインのコンパイルは、PL/SQLストアド・プロシージャと同じです。無名PL/SQLブロックは、メモリーにロードされるたびにコンパイルされます。
すべてのプラグイン・モジュールは、ODSデータベース・スキーマでコンパイルする必要があります。次の各項で、さらに詳しく説明します。
A.5.1.3.1 プラグイン・コンパイルの段階の概要
コンパイルは3つの段階を踏んで実行されます。これらのツールは、次のとおりです。
-
構文チェック: PL/SQL構文がチェックされ、解析ツリーが生成されます。
-
セマンティック・チェック: 型チェックおよび解析ツリーに対する追加処理が行われます。
-
コード生成: Pコードが生成されます。
A.5.1.3.2 プラグインのコンパイル中に発生したエラーの表示
プラグインのコンパイル中にエラーが発生した場合、そのプラグインは作成されません。プラグイン作成時のコンパイル・エラーを参照するには、SQL*PlusまたはEnterprise ManagerでSHOW ERRORS
文を使用するか、あるいはSELECT
文を使用してUSER_ERRORS
ビューからエラーを選択できます。
A.5.1.3.3 コンパイル済プラグインの依存性
コンパイル済プラグインには依存性があります。依存オブジェクト(プラグイン本体からコールされるストアド・プロシージャやファンクションなど)が変更された場合、プラグインは無効になります。依存性の理由から無効となったプラグインは、次回起動するまでに再コンパイルする必要があります。
A.5.1.4 PL/SQLプラグインの管理
次のトピックでは、プラグインの変更およびデバッグ方法について説明します。
A.5.1.4.1 プラグインの変更
ストアド・プロシージャと同様、プラグインは明示的に変更できません。これは、新しい定義で置換する必要があります。
プラグインを置換する場合は、CREATE PACKAGE
文にOR REPLACE
オプションを指定する必要があります。このOR REPLACE
オプションによって、既存のプラグインの新規バージョンは、プラグインの元のバージョンに付与されている権限に影響を与えることなく古いバージョンを置換できます。
DROP PACKAGE
文を使用してプラグインを削除してから、CREATE PACKAGE
文を再実行することもできます。
プラグイン名(パッケージ名)が変更されている場合は、新規プラグインを再度登録する必要があります。
A.5.1.5 PL/SQLプラグインの有効化と無効化
プラグインをオンまたはオフに切り替えるには、プラグイン構成オブジェクトのorclPluginEnable
の値を変更します。たとえば、cn=post_mod_plugin,cn=plugins,cn=subconfigsubentry
でorclPluginEnable
の値を1
または0
(ゼロ)に変更します。
A.5.1.6 PL/SQLプラグインにおける例外処理
PL/SQLプラグインの各プロシージャには、エラーを処理し、可能な場合にはリカバリを行うための例外処理ブロックが必要です。次の各項で、さらに詳しく説明します。
A.5.1.6.1 OIDのエラー・メッセージとリターン・コード
Oracle Internet Directoryでは、リターン・コード(rc
)とエラー・メッセージ(errmsg
)がプラグイン・プロシージャに正しく設定されている必要があります。
A.5.1.6.1.1 エラー処理のリターン・コード
表A-21にリターン・コードの有効な値を示します。
表A-21 プラグインのリターン・コードの有効な値
エラー・コード | 説明 |
---|---|
0 |
成功 |
0(ゼロ)より大きい数値 |
失敗 |
-1 |
警告 |
A.5.1.6.1.2 エラー・メッセージの表示とロギング
errmsg
パラメータは、ユーザーのカスタム・エラー・メッセージをOracle Internet Directoryサーバーに戻すことができる文字列値です。errmsg
のサイズ制限は、1024バイトです。Oracle Internet Directoryは、プラグイン・プログラムを実行するたびに、リターン・コードを検査し、エラー・メッセージの表示が必要かどうかを判断します。
たとえば、リターン・コードの値が0
(ゼロ)の場合、エラー・メッセージの値は無視されます。リターン・コードの値が-1
または0(ゼロ)よりも大きい場合は、次のメッセージがログ・ファイルに記録されるか、標準出力に表示(リクエスト元がLDAPコマンド行ツールの場合)されます。
ldap addition info: customized error
A.5.1.6.2 プラグインの例外または失敗に応じたOracle Internet Directoryサーバーのアクション
Oracle Internet Directoryサーバーは、例外を様々な方法で処理します。次の各項で、さらに詳しく説明します。
A.5.1.6.2.1 プラグイン例外発生時のOracle Internet Directoryサーバーのアクション
表A-22に、プラグイン例外の発生場所とディレクトリによる処理方法を示します。
表A-22 プラグイン例外発生時のプログラム制御処理
プラグイン例外の発生場所 | Oracle Internet Directoryサーバーによる処理 |
---|---|
|
リターン・コードに従います。処理は次のとおりです。
|
|
LDAP操作を完了します。ロールバックは実行されません。 |
|
LDAP操作をロールバックします。 |
A.5.1.6.2.2 LDAP操作障害時のOracle Internet Directoryサーバーのアクション
表A-23に、LDAP操作障害時のディレクトリの対応を示します。
表A-23 LDAP操作障害時のプログラム制御処理
LDAP操作障害の発生場所 | Oracle Internet Directoryサーバーによる処理 |
---|---|
|
操作前プラグインを完了します。ロールバックは実行されません。 |
|
操作後プラグインが続行されます。LDAP操作結果は |
|
操作時タイプのプラグインの変更はロールバックされます。 |
|
プラグイン・プログラム本体への変更はロールバックされます。 |
A.5.1.7 PL/SQLプラグインLDAP API
APIアクセスを提供するには、次のように様々な方法があります。
-
ユーザーは標準LDAP PL/SQL APIを利用できます。ただし、プログラム・ロジックを慎重に計画しないと、プラグインの実行で無限ループが発生する可能性があることに注意してください。
-
Oracle Internet DirectoryはプラグインLDAP APIを提供します。LDAPリクエストに関連付けられている構成済のプラグインがある場合、このプラグインは、ディレクトリ・サーバー内の一連のプラグイン・アクションを実行しません。
プラグインLDAP APIでは、プラグイン・モジュールで指定されたディレクトリ・サーバーに接続するためのAPIがディレクトリにより提供されます。プラグインを実行するサーバーに接続する場合、このAPIを使用する必要があります。外部サーバーに接続する場合、DBMS_LDAP APIを使用できます。
各プラグイン・モジュールでは、ldapcontext
がOracleディレクトリ・サーバーから渡されます。プラグインLDAP APIがコールされると、セキュリティおよびバインドの目的でldapcontext
が渡されます。このldapcontext
を使用してバインドすると、Oracle Internet Directoryで、LDAPリクエストがプラグイン・モジュールからのリクエストであることが認識されます。このタイプのプラグイン・バインドの場合、ディレクトリによって後続のプラグインがトリガーされることはありません。プラグイン・バインドは、スーパーユーザー・バインドとして処理されます。このプラグイン・バインドは慎重に使用してください。
関連項目:
A.5.1.9 PL/SQLプラグインのセキュリティの確保
一部のOracle Internet Directoryサーバーのプラグインでは、厳重なセキュリティを保持するコードをユーザーが用意する必要があります。たとえば、ディレクトリのldapcompare
またはldapbind
操作をユーザー独自のプラグイン・モジュールで置換する場合、ユーザーは、セキュリティを維持するための機能が、この操作の実装によって除外されないことを確認する必要があります。
厳重なセキュリティを確保するには、次の処理を実行する必要があります。
-
プラグイン・パッケージを作成します。
-
LDAP管理者のみがデータベース・ユーザーを制限できるように指定します。
-
アクセス制御リスト(ACL)を使用して、LDAP管理者のみがプラグイン構成エントリにアクセスできるように設定します。
-
異なる複数のプラグイン間におけるプログラムの関連性に注意します。
A.5.1.10 PL/SQLプラグインのデバッグ
プラグインの処理および内容を検証するには、Oracle Internet Directoryのプラグイン・デバッグ・メカニズムを使用します。次のコマンドは、サーバーのデバッグ処理の操作を制御します。
-
プラグインのデバッグを設定するには、次のコマンドを実行します。
% sqlplus ods @$ORACLE/ldap/admin/oidspdsu.pls
-
プラグインのデバッグを有効にするには、次のコマンドを実行します。
% sqlplus ods @$ORACLE/ldap/admin/oidspdon.pls
-
プラグインのデバッグを有効にした後は、プラグイン・モジュール・コードで次のコマンドを使用できます。
plg_debug('debuggingmessage');
生成されたデバッグ・メッセージは、プラグイン・デバッグ表に格納されます。
-
デバッグを無効にするには、次のコマンドを実行します。
% sqlplus ods @$ORACLE/ldap/admin/oidspdof.pls
-
プラグイン・モジュールに設定したデバッグ・メッセージを表示するには、次のコマンドを実行します。
% sqlplus ods @$ORACLE/ldap/admin/oidspdsh.pls
-
デバッグ表からすべてのデバッグ・メッセージを削除するには、次のコマンドを実行します。
% sqlplus ods @$ORACLE/ldap/admin/oidspdde.pls
A.5.1.11 PL/SQLプラグインLDAP APIの仕様
Oracle Internet Directoryが提供するPL/SQLプラグインLDAP APIのパッケージ仕様は次のとおりです。
CREATE OR REPLACE PACKAGE LDAP_PLUGIN AS SUBTYPE SESSION IS RAW(32); -- Initializes the LDAP library and return a session handler -- for use in subsequent calls. FUNCTION init (ldappluginctx IN ODS.plugincontext) RETURN SESSION; -- Synchronously authenticates to the directory server using -- a Distinguished Name and password. FUNCTION simple_bind_s (ldappluginctx IN ODS.plugincontext, ld IN SESSION) RETURN PLS_INTEGER; -- Get requester info from the plug-in context FUNCTION get_requester (ldappluginctx IN ODS.plugincontext) RETURN VARCHAR2; END LDAP_PLUGIN;
A.5.2 PL/SQLプラグインの使用
例を使用してPL/SQLプラグインについて理解します。この項では、2つのサンプル・プラグインを示します。一方は、すべてのldapsearch
コマンドを記録します。もう一方は、2つのディレクトリ情報ツリー(DIT)を同期化します。
この項では、次の項目について説明します。
A.5.2.1 プラグインを介したすべてのldapsearchコマンドの記録
状況: すべてのldapsearch
コマンドを記録できるかどうかについて、あるユーザーが疑問を持っています。
解答: 記録できます。これには、ldapsearch
操作後構成プラグインを使用できます。リクエストをすべて記録することも、検索対象のDNで発生したリクエストのみを記録することも可能です。
すべてのldapsearch
コマンドを記録するには:
A.5.2.2 プラグインを介した2つのDITの同期化
状況: 相互に依存する2つの製品がcn=Products
、cn=oraclecontext
にあります。この相互依存性は、これらの製品のコンテナ内のユーザーにも適用されます。最初のDIT(製品1)のユーザーが削除された場合、もう一方のDIT(製品2)の対応するユーザーを削除する必要があります。
トリガーを設定して、最初のDITのユーザーが削除された場合に2番目のDITのユーザーを削除するトリガーをコールする、または渡すことは可能でしょうか。
解答: 可能です。ldapdelete
操作後プラグインを使用して、2番目のDITで発生する2番目の削除を処理できます。
最初のDITにcn=DIT1,cn=products,cn=oraclecontext
というネーミング・コンテキストがあり、2番目のDITにcn=DIT2,cn=products,cn=oraclecontext
というネーミング・コンテキストがある場合、2人のユーザーは同一のID属性を共有します。ldapdelete
操作後プラグイン・モジュール内で、LDAP_PLUGIN
とDBMS_LDAP
のAPIを使用して、2番目のDIT内のユーザーを削除できます。
orclPluginSubscriberDNList
をcn=DIT1,cn=products,cn=oraclecontext
に設定する必要があります。これによって、cn=DIT1,cn=products,cn=oraclecontext
のエントリを削除すると、常にプラグイン・モジュールが起動されるようになります。
ノート:
ldapmodify
操作後プラグインを使用して2つのOracle Internet Directoryのノード間で変更を同期化する場合、一方のノードから他方のノードへすべての属性をプッシュすることはできません。これは、プラグイン・モジュールで取得された変更(変更構造体)に操作属性が含まれているためです。このような操作属性は各ノードで生成されるものであり、標準のLDAPメソッドを使用して変更できません。
プラグイン・プログラムを記述する際には、操作属性authPassword
、creatorsname
、createtimestamp
、modifiersname
、modifytimestamp
、orcllastlogintime
、pwdchangedtime
、pwdfailuretime
、pwdaccountlockedtime
、pwdexpirationwarned
、pwdreset
、pwdhistory
、pwdgraceusetime
を同期化の対象から除外します。
同期するには:
A.5.3 PL/SQLプラグインを使用したバイナリ操作の実行
リリース10.1.2から、プラグインLDAP APIのオブジェクト定義によって、ldapmodify
、ldapadd
およびldapcompare
のプラグインがディレクトリ・データベース内のバイナリ属性にアクセスできるようになりました。
これまでは、アクセスできるのはタイプVARCHAR2
の属性のみでした。これらのオブジェクト定義では、リリース10.1.2より前のプラグイン・コードは無効化されません。このコードを変更する必要はありません。新しい定義は、「LDAP APIプラグインのオブジェクト型定義」に記載されています。
この項では、3種類のプラグインが関係するバイナリ操作について説明します。これらのプラグインの例も示します。新しいオブジェクト定義は、3つすべてについて操作前、操作後および操作時のバージョンに適用されます。
3つの例では、LOBのかわりにRAWファンクションおよび変数を使用していることに注意してください。次の各項では、これについてさらに詳しく説明しています。
A.5.3.1 ldapmodifyプラグインを使用した別のディレクトリのエントリの変更
プラグイン・フレームワークがldapmodify
のプラグインに渡すmodobj
オブジェクトに、バイナリ属性の値がbinvals
として格納されるようになりました。この変数は、binvalobj
オブジェクトの表です。
このプラグインでは、modobj
のoperation
フィールドを調べて、バイナリ操作が実行されているかどうかを判断します。これにより、値DBMS_LDAP.MOD_ADD
、DBMS_LDAP.MOD_DELETE
およびDBMS_LDAP.MOD_REPLACE
のいずれかが、DBMS_LDAP.MOD_BVALUES
と組み合されているかどうかがチェックされます。たとえば、DBMS_LDAP.MOD_ADD+DBMS_LDAP.MOD_BVALUES
の組合せは、変更操作におけるバイナリの追加を示します。
次の例は、別のディレクトリのエントリを変更する、ldapmodify
操作後プラグインを示しています。このプラグインは、ldapmodify
がプラグイン・ディレクトリの同じエントリに同じ変更を適用した後、起動されます。もう一方のディレクトリのエントリは、DIT cn=users,dc=us,dc=example,dc=com
にあります。
create or replace package moduser as
procedure post_modify(ldapplugincontext IN ODS.plugincontext,
result IN integer,
dn IN varchar2,
mods IN ODS.modlist,
rc OUT integer,
errormsg OUT varchar2);
end moduser;
/
show error
CREATE OR REPLACE PACKAGE BODY moduser AS
procedure post_modify(ldapplugincontext IN ODS.plugincontext,
result IN integer,
dn IN varchar2,
mods IN ODS.modlist,
rc OUT integer,
errormsg OUT varchar2)
is
counter1 pls_integer;
counter2 pls_integer;
retval pls_integer := -1;
user_session DBMS_LDAP.session;
user_dn varchar(256);
user_array DBMS_LDAP.mod_array;
user_vals DBMS_LDAP.string_collection;
user_binvals DBMS_LDAP.blob_collection;
ldap_host varchar(256);
ldap_port varchar(256);
ldap_user varchar(256);
ldap_passwd varchar(256);
begin
ldap_host :='backup.us.example.com';
ldap_port :='4000';
ldap_user :='cn=orcladmin';
ldap_passwd :='password';
plg_debug('START MODIFYING THE ENTRY');
-- Get a session
user_session := dbms_ldap.init(ldap_host, ldap_port);
-- Bind to the directory
retval := dbms_ldap.simple_bind_s(user_session, ldap_user,
ldap_passwd);
-- Create a mod_array
user_array := dbms_ldap.create_mod_array(mods.count);
-- Create a user_dn
user_dn := substr(dn,1,instr(dn,',',1,1))||'cn=users,dc=us,dc=example,
dc=com';
plg_debug('THE CREATED DN IS'||user_dn);
-- Iterate through the modlist
for counter1 in 1..mods.count loop
-- Log the attribute name and operation
if (mods(counter1).operation > DBMS_LDAP.MOD_BVALUES) then
plg_debug('THE NAME OF THE BINARY ATTR. IS'||mods(counter1).type);
else
plg_debug('THE NAME OF THE NORMAL ATTR. IS'||mods(counter1).type);
end if;
plg_debug('THE OPERATION IS'||mods(counter1).operation);
-- Add the attribute values to the collection
for counter2 in 1..mods(counter1).vals.count loop
user_vals(counter2) := mods(counter1).vals(counter2).val;
end loop;
-- Add the attribute values to the collection
for counter2 in 1..mods(counter1).binvals.count loop
plg_debug('THE NO. OF BYTES OF THE BINARY ATTR. VALUE IS'
||mods(counter1).binvals(counter2).length);
user_binvals(counter2) := mods(counter1).binvals(counter2).binval;
end loop;
-- Populate the mod_array accordingly with binary/normal attributes
if (mods(counter1).operation >= DBMS_LDAP.MOD_BVALUES) then
dbms_ldap.populate_mod_array(user_array,mods(counter1).operation -
DBMS_LDAP.MOD_BVALUES,mods(counter1).type,user_binvals);
user_binvals.delete;
else
dbms_ldap.populate_mod_array(user_array,mods(counter1).operation,
mods(counter1).type,user_vals);
user_vals.delete;
end if;
end loop;
-- Modify the entry
retval := dbms_ldap.modify_s(user_session,user_dn,user_array);
if retval = 0 then
rc := 0;
errormsg:='No error occurred while modifying the entry';
else
rc := retval;
errormsg :='Error code'||rc||' while modifying the entry';
end if;
-- Free the mod_array
dbms_ldap.free_mod_array(user_array);
plg_debug('FINISHED MODIFYING THE ENTRY');
exception
WHEN others THEN
plg_debug (SQLERRM);
end;
end moduser;
/
show error
exit;
A.5.3.2 ldapaddプラグインを使用した別のディレクトリへの変更の伝播
プラグイン・フレームワークがldapadd
のプラグインに渡すentryobj
オブジェクトに、バイナリ属性がbinattr
として格納されるようになりました。この変数は、binattrobj
オブジェクトの表です。次の例は、プラグイン・ディレクトリの変更(追加されたユーザー)を別のディレクトリに伝播する追加後プラグインを示しています。後者のディレクトリのエントリは、DIT cn=users,dc=us,dc=example,dc=com
にあります。
create or replace package adduser as
procedure post_add(ldapplugincontext IN ODS.plugincontext,
result IN integer,
dn IN varchar2,
entry IN ODS.entryobj,
rc OUT integer,
errormsg OUT varchar2);
end adduser;
/
show error
CREATE OR REPLACE PACKAGE BODY adduser AS
procedure post_add(ldapplugincontext IN ODS.plugincontext,
result IN integer,
dn IN varchar2,
entry IN ODS.entryobj,
rc OUT integer,
errormsg OUT varchar2)
is
counter1 pls_integer;
counter2 pls_integer;
retval pls_integer := -1;
s integer;
user_session DBMS_LDAP.session;
user_dn varchar(256);
user_array DBMS_LDAP.mod_array;
user_vals DBMS_LDAP.string_collection;
user_binvals DBMS_LDAP.blob_collection;
ldap_host varchar(256);
ldap_port varchar(256);
ldap_user varchar(256);
ldap_passwd varchar(256);
begin
ldap_host :='backup.us.example.com';
ldap_port :='4000';
ldap_user :='cn=orcladmin';
ldap_passwd :='password';
plg_debug('START ADDING THE ENTRY');
-- Get a session
user_session := dbms_ldap.init(ldap_host, ldap_port);
-- Bind to the directory
retval := dbms_ldap.simple_bind_s(user_session, ldap_user, ldap_passwd);
-- Create a mod_array
user_array := dbms_ldap.create_mod_array(entry.binattr.count +
entry.attr.count);
-- Create a user_dn
user_dn := substr(dn,1,instr(dn,',',1,1))||'cn=users,dc=us,dc=example,
dc=com';
plg_debug('THE CREATED DN IS'||user_dn);
-- Populate the mod_array with binary attributes
for counter1 in 1..entry.binattr.count loop
for counter2 in 1..entry.binattr(counter1).binattrval.count loop
plg_debug('THE NAME OF THE BINARY ATTR. IS'||
entry.binattr(counter1).binattrname);
s := dbms_lob.getlength(entry.binattr(counter1).
binattrval(counter2));
plg_debug('THE NO. OF BYTES OF THE BINARY ATTR. VALUE IS'||s);
user_binvals(counter2) := entry.binattr(counter1).
binattrval(counter2);
end loop;
dbms_ldap.populate_mod_array(user_array,DBMS_LDAP.MOD_ADD,
entry.binattr(counter1).binattrname,user_binvals);
user_binvals.delete;
end loop;
-- Populate the mod_array with attributes
for counter1 in 1..entry.attr.count loop
for counter2 in 1..entry.attr(counter1).attrval.count loop
plg_debug('THE NORMAL ATTRIBUTE'||entry.attr(counter1).attrname||'
HAS THE VALUE'||entry.attr(counter1).attrval(counter2));
user_vals(counter2) := entry.attr(counter1).attrval(counter2);
end loop;
dbms_ldap.populate_mod_array(user_array,DBMS_LDAP.MOD_ADD,
entry.attr(counter1).attrname,user_vals);
user_vals.delete;
end loop;
-- Add the entry
retval := dbms_ldap.add_s(user_session,user_dn,user_array);
plg_debug('THE RETURN VALUE IS'||retval);
if retval = 0 then
rc := 0;
errormsg:='No error occurred while adding the entry';
else
rc := retval;
errormsg :='Error code'||rc||' while adding the entry';
end if;
-- Free the mod_array
dbms_ldap.free_mod_array(user_array);
retval := dbms_ldap.unbind_s(user_session);
plg_debug('FINISHED ADDING THE ENTRY');
exception
WHEN others THEN
plg_debug (SQLERRM);
end;
end adduser;
/
show error
exit;
A.5.3.3 ldapcompareプラグインを使用したバイナリ属性の比較
ldapcompare
のプラグインは、オーバーロードされた3つの新しいモジュール・インタフェースを使用してバイナリ属性を比較できます。これらのインタフェースを使用して、バイナリと非バイナリ両方の属性を処理するプラグイン・パッケージを開発する場合、パッケージに2つの別々のプロシージャを含める必要があります。orclPluginName
はプラグイン・エントリに1つしか登録できないため、2つのプロシージャのパッケージ名は同じです。
既存のプラグイン・パッケージを更新してバイナリ属性を比較するプロシージャを含めた後、パッケージを再インストールします。そのプラグイン・パッケージに依存するパッケージを再コンパイルします。
3つの新しいインタフェースは次のようになります。
PROCEDURE pre_compare (ldapplugincontext IN ODS.plugincontext, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 ); PROCEDURE when_compare_replace (ldapplugincontext IN ODS.plugincontext, result OUT INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 ); PROCEDURE post_compare (ldapplugincontext IN ODS.plugincontext, result IN INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 );
次の例では、プラグイン・ディレクトリのエントリのバイナリ属性と別のディレクトリのエントリのバイナリ属性を比較します。このパッケージは、サーバーの比較コードをプラグインの比較コードに置き換えます。また、バイナリと非バイナリ両方の属性を処理します。そのため、2つの別々のプロシージャが含まれています。
create or replace package compareattr as
procedure when_compare_replace(ldapplugincontext IN ODS.plugincontext,
result OUT integer,
dn IN varchar2,
attrname IN VARCHAR2,
attrval IN BLOB,
rc OUT integer,
errormsg OUT varchar2);
procedure when_compare_replace(ldapplugincontext IN ODS.plugincontext,
result OUT integer,
dn IN varchar2,
attrname IN VARCHAR2,
attrval IN varchar2,
rc OUT integer,
errormsg OUT varchar2);
end compareattr;
/
show error
CREATE OR REPLACE PACKAGE BODY compareattr AS
procedure when_compare_replace(ldapplugincontext IN ODS.plugincontext,
result OUT integer,
dn IN varchar2,
attrname IN VARCHAR2,
attrval IN varchar2,
rc OUT integer,
errormsg OUT varchar2)
is
pos INTEGER := 2147483647;
begin
plg_debug('START');
plg_debug('THE ATTRNAME IS'||attrname||' AND THE VALUE IS'||attrval);
plg_debug('END');
rc := 0;
errormsg :='No error!!!';
exception
WHEN others THEN
plg_debug ('Unknown UTL_FILE Error');
end;
procedure when_compare_replace(ldapplugincontext IN ODS.plugincontext,
result OUT integer,
dn IN varchar2,
attrname IN VARCHAR2,
attrval IN BLOB,
rc OUT integer,
errormsg OUT varchar2)
is
counter pls_integer;
retval pls_integer := -1;
cmp_result integer;
s integer;
user_session DBMS_LDAP.session;
user_entry DBMS_LDAP.message;
user_message DBMS_LDAP.message;
user_dn varchar(256);
user_attrs DBMS_LDAP.string_collection;
user_attr_name VARCHAR2(256);
user_ber_elmt DBMS_LDAP.ber_element;
user_vals DBMS_LDAP.blob_collection;
ldap_host varchar(256);
ldap_port varchar(256);
ldap_user varchar(256);
ldap_passwd varchar(256);
ldap_base varchar(256);
begin
ldap_host :='backup.us.example.com';
ldap_port :='4000';
ldap_user :='cn=orcladmin';
ldap_passwd :='password';
ldap_base := dn;
plg_debug('STARTING COMPARISON IN WHEN REPLACE PLUG-IN');
s := dbms_lob.getlength(attrval);
plg_debug('THE NUMBER OF BYTES OF ATTRVAL'||s);
-- Get a session
user_session := dbms_ldap.init(ldap_host, ldap_port);
-- Bind to the directory
retval := dbms_ldap.simple_bind_s(user_session, ldap_user, ldap_passwd);
-- issue the search
user_attrs(1) := attrname;
retval := DBMS_LDAP.search_s(user_session, ldap_base,
DBMS_LDAP.SCOPE_BASE,
'objectclass=*',
user_attrs,
0,
user_message);
-- Get the entry in the other OID server
user_entry := DBMS_LDAP.first_entry(user_session, user_message);
-- Log the DN and the Attribute name
user_dn := DBMS_LDAP.get_dn(user_session, user_entry);
plg_debug('THE DN IS'||user_dn);
user_attr_name := DBMS_LDAP.first_attribute(user_session,user_entry,
user_ber_elmt);
-- Get the values of the attribute
user_vals := DBMS_LDAP.get_values_blob(user_session, user_entry,
user_attr_name);
-- Start the binary comparison between the ATTRVAL and the attribute
-- values
if user_vals.count > 0 then
for counter in user_vals.first..user_vals.last loop
cmp_result := dbms_lob.compare(user_vals(counter),attrval,
dbms_lob.getlength(user_vals(counter)),1,1);
if cmp_result = 0 then
rc := 0;
-- Return LDAP_COMPARE_TRUE
result := 6;
plg_debug('THE LENGTH OF THE ATTR.'||user_attr_name||' IN THE
ENTRY IS'||dbms_lob.getlength(user_vals(counter)));
errormsg :='NO ERROR. THE COMPARISON HAS SUCCEEDED.';
plg_debug(errormsg);
plg_debug('FINISHED COMPARISON');
return;
end if;
end loop;
end if;
rc := 1;
-- Return LDAP_COMPARE_FALSE
result := 5;
errormsg :='ERROR. THE COMPARISON HAS FAILED.';
plg_debug('THE LENGTH OF THE ATTR.'||user_attr_name||' IN THE ENTRY IS'
||dbms_lob.getlength(user_vals(user_vals.last)));
plg_debug(errormsg);
plg_debug('FINISHED COMPARISON');
-- Free user_vals
dbms_ldap.value_free_blob(user_vals);
exception
WHEN others THEN
plg_debug (SQLERRM);
end;
end compareattr;
/
show error
exit;
A.5.4 LDAP APIプラグインのオブジェクト型定義
プラグインLDAP APIに導入されたオブジェクト型について理解します。これらの定義は、すべてOracle Directory Serverのデータベース・スキーマにあります。APIにはプラグインがデータベースからバイナリ・データを抽出するためのオブジェクト型が含まれていることに注意してください。
create or replace type strCollection as TABLE of VARCHAR2(512); / create or replace type pluginContext as TABLE of VARCHAR2(512); / create or replace type attrvalType as TABLE OF VARCHAR2(4000); / create or replace type attrobj as object ( attrname varchar2(2000), attrval attrvalType ); / create or replace type attrlist as table of attrobj; / create or replace type binattrvalType as TABLE OF BLOB; / create or replace type binattrobj as object ( binattrname varchar2(2000), binattrval binattrvalType ); / create or replace type binattrlist as table of binattrobj; / create or replace type entryobj as object ( entryname varchar2(2000), attr attrlist, binattr binattrlist ); / create or replace type entrylist as table of entryobj; / create or replace type bvalobj as object ( length integer, val varchar2(4000) ); / create or replace type bvallist as table of bvalobj; / create or replace type binvalobj as object ( length integer, binval blob ); / create or replace type binvallist as table of binvalobj; / create or replace type modobj as object ( operation integer, type varchar2(256), vals bvallist, binvals binvallist ); / create or replace type modlist as table of modobj;
A.5.5 PL/SQLプラグイン・プロシージャの仕様
プラグインを使用する場合、各プラグインに定義されたシグネチャに従う必要があります。次に各シグネチャを示します。
PROCEDURE pre_add (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, entry IN ODS.entryobj, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE when_add (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, entry IN ODS.entryobj, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE when_add_replace (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, entry IN ODS.entryobj, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE post_add (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, 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);
PROCEDURE when_modify (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, mods IN ODS.modlist, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE when_modify_replace (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, mods IN ODS.modlist, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE post_modify (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, dn IN VARCHAR2, mods IN ODS.modlist, rc OUT INTEGER, errormsg OUT VARCHAR2);
PROCEDURE pre_compare (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE pre_compare (ldapplugincontext IN ODS.plugincontext, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 ); PROCEDURE when_compare_replace (ldapplugincontext IN ODS.plugincontext,
result OUT INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 ); PROCEDURE when_compare_replace (ldapplugincontext IN ODS.plugincontext, result OUT INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE post_compare (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 ); PROCEDURE post_compare (ldapplugincontext IN ODS.plugincontext, result IN INTEGER, dn IN VARCHAR2, attrname IN VARCHAR2, attrval IN BLOB, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE pre_delete (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE when_delete (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE when_delete_replace (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE post_delete (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE pre_search (ldapplugincontext IN ODS.plugincontext,
baseDN IN VARCHAR2, scope IN INTEGER, filterStr IN VARCHAR2, requiredAttr IN ODS.strCollection, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE post_search (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, baseDN IN VARCHAR2, scope IN INTEGER, filterStr IN VARCHAR2, requiredAttr IN ODS.strCollection, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE pre_bind (ldapplugincontext IN ODS.plugincontext,
dn IN VARCHAR2, passwd IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE when_bind_replace (ldapplugincontext IN ODS.plugincontext,
result OUT INTEGER, dn IN VARCHAR2, passwd IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );
PROCEDURE post_bind (ldapplugincontext IN ODS.plugincontext,
result IN INTEGER, dn IN VARCHAR2, passwd IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 );