この付録では、PL/SQLのプラグイン・フレームワークを使用する方法について説明し、Oracle Internet DirectoryでPL/SQLサーバー・プラグインを設計、作成および使用する方法について説明します。
この付録の内容は次のとおりです。
この項の項目は次のとおりです。
PL/SQLプラグインには、次の注意事項があります。
PL/SQLプラグイン・モジュールの作成は、PL/SQLパッケージの作成と似ています。いずれも、仕様部分と本文に分かれています。この仕様はOracle Internet Directoryとカスタム・プラグインを接続するインタフェースの役割を果すため、プラグインではなくディレクトリによってプラグインの仕様が決まります。
セキュリティ上およびLDAPサーバーの整合性の理由から、PL/SQLプラグインをコンパイルできるのはODSデータベース・スキーマにおいてのみです。これらを、Oracle Internet Directoryのバックエンド・データベースの役割を果すデータベースにコンパイルする必要があります。
パッケージ仕様はプラグインによって異なります。表F-1に示すように、プラグイン・パッケージには名前を指定できます。ただし、プラグイン・プロシージャの各タイプに定義されているシグネチャには従う必要があります。詳細は、第F.5項「PL/SQLプラグイン・プロシージャの仕様」を参照してください。
表F-1 プラグイン・モジュール・インタフェース
プラグイン項目 | ユーザー定義 | Oracle Internet Directoryで定義 |
---|---|---|
プラグイン・パッケージ名 |
X |
|
プラグイン・プロシージャ名 |
X |
|
プラグイン・プロシージャのシグネチャ |
X |
表F-2に、様々なプラグイン・プロシージャを示します。また、各プロシージャで使用されるパラメータについても説明します。
表F-2 操作ベースと属性ベースのプラグイン・プロシージャのシグネチャ
起動コンテキスト | プロシージャ名 | 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 |
関連項目:
|
Oracle Internet Directoryのバックエンド・データベースと同じ役割を果すデータベースに対して、プラグイン・モジュールをコンパイルする必要があります。プラグインのコンパイルは、PL/SQLストアド・プロシージャと同じです。無名PL/SQLブロックは、メモリーにロードされるたびにコンパイルされます。コンパイルは次の段階を踏んで実行されます。
構文検査: PL/SQLの構文がチェックされ、解析ツリーが生成されます。
意味検査: 型がチェックされ、解析ツリーでさらに処理されます。
コード生成: Pコードが生成されます。
プラグインのコンパイル中にエラーが発生した場合、そのプラグインは作成されません。プラグイン作成時のコンパイル・エラーを参照するには、SQL*PlusまたはEnterprise ManagerでSHOW ERRORS
文を使用するか、あるいはSELECT
文を使用してUSER_ERRORS
ビューからエラーを選択できます。
すべてのプラグイン・モジュールは、ODSデータベース・スキーマでコンパイルする必要があります。
この項では、プラグインの変更およびデバッグ方法について説明します。
ストアド・プロシージャと同様、プラグインは明示的に変更できません。これは、新しい定義で置換する必要があります。
プラグインを置換する場合は、CREATE PACKAGE
文にOR REPLACE
オプションを指定する必要があります。このOR REPLACE
オプションによって、既存のプラグインの新規バージョンは、プラグインの元のバージョンに付与されている権限に影響を与えることなく古いバージョンを置換できます。
DROP PACKAGE
文を使用してプラグインを削除してから、CREATE PACKAGE
文を再実行することもできます。
プラグイン名(パッケージ名)が変更されている場合は、新規プラグインを再度登録する必要があります。
プラグインをオンまたはオフに切り替えるには、プラグイン構成オブジェクトのorclPluginEnable
の値を変更します。たとえば、cn=post_mod_plugin,cn=plugins,cn=subconfigsubentry
でorclPluginEnable
の値を1
または0
(ゼロ)に変更します。
PL/SQLプラグインの各プロシージャには、エラーを処理し、可能な場合にはリカバリを行うための例外処理ブロックが必要です。
Oracle Internet Directoryでは、リターン・コード(rc
)とエラー・メッセージ(errmsg
)がプラグイン・プロシージャに正しく設定されている必要があります。
表F-3にリターン・コードの有効な値を示します。
errmsg
パラメータは、ユーザーのカスタム・エラー・メッセージをOracle Internet Directoryサーバーに戻すことができる文字列値です。errmsg
のサイズ制限は、1024バイトです。Oracle Internet Directoryは、プラグイン・プログラムを実行するたびに、リターン・コードを検査し、エラー・メッセージの表示が必要かどうかを判断します。
たとえば、リターン・コードの値が0
(ゼロ)の場合、エラー・メッセージの値は無視されます。リターン・コードの値が-1
または0(ゼロ)よりも大きい場合は、次のメッセージがログ・ファイルに記録されるか、標準出力に表示(リクエスト元がLDAPコマンド行ツールの場合)されます。
ldap addition info: customized error
表F-4に、プラグイン例外の発生場所とディレクトリによる処理方法を示します。
表F-4 プラグイン例外発生時のプログラム制御処理
プラグイン例外の発生場所 | Oracle Internet Directoryサーバーによる処理 |
---|---|
|
リターン・コードに従います。処理は次のとおりです。
|
|
LDAP操作を完了します。ロールバックは実行されません。 |
|
LDAP操作をロールバックします。 |
表F-5に、LDAP操作障害時のディレクトリの対応を示します。
表F-5 LDAP操作障害時のプログラム制御処理
LDAP操作障害の発生場所 | Oracle Internet Directoryサーバーによる処理 |
---|---|
|
操作前プラグインを完了します。ロールバックは実行されません。 |
|
操作後プラグインが続行されます。LDAP操作結果は |
|
操作時タイプのプラグインの変更はロールバックされます。 |
|
プラグイン・プログラム本体への変更はロールバックされます。 |
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リクエストがプラグイン・モジュールからのリクエストであることが認識されます。このタイプのプラグイン・バインドの場合、ディレクトリによって後続のプラグインがトリガーされることはありません。プラグイン・バインドは、スーパーユーザー・バインドとして処理されます。このプラグイン・バインドは慎重に使用してください。
バルク・ツールは、サーバー・プラグインをサポートしていません。
一部のOracle Internet Directoryサーバーのプラグインでは、厳重なセキュリティを保持するコードをユーザーが用意する必要があります。たとえば、ディレクトリのldapcompare
またはldapbind
操作をユーザー独自のプラグイン・モジュールで置換する場合、ユーザーは、セキュリティを維持するための機能が、この操作の実装によって除外されないことを確認する必要があります。
厳重なセキュリティを確保するには、次の処理を実行する必要があります。
プラグイン・パッケージを作成します。
LDAP管理者のみがデータベース・ユーザーを制限できるように指定します。
アクセス制御リスト(ACL)を使用して、LDAP管理者のみがプラグイン構成エントリにアクセスできるように設定します。
異なる複数のプラグイン間におけるプログラムの関連性に注意します。
プラグインの処理および内容を検証するには、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
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;
この項では、2つのサンプル・プラグインを示します。一方は、すべてのldapsearch
コマンドを記録します。もう一方は、2つのディレクトリ情報ツリー(DIT)を同期化します。
状況: すべてのldapsearch
コマンドを記録できるかどうかについて、あるユーザーが疑問を持っています。
解答: 記録できます。これには、ldapsearch
操作後構成プラグインを使用できます。リクエストをすべて記録することも、検索対象のDNで発生したリクエストのみを記録することも可能です。
すべてのldapsearch
コマンドを記録するには、次の手順を実行します。
すべてのldapsearch
結果をデータベース表に記録します。このログ表には次の列があります。
タイムスタンプ
ベースDN
検索範囲
検索フィルタ
必須属性
検索結果
表を作成するには、次のSQLスクリプトを使用します。
drop table search_log; create table search_log (timestamp varchar2(50), basedn varchar2(256), searchscope number(1); searchfilter varchar2(256); searchresult number(1)); drop table simple_tab; create table simple_tab (id NUMBER(7), dump varchar2(256)); DROP sequence seq; CREATE sequence seq START WITH 10000; commit;
プラグイン・パッケージ仕様を作成します。
CREATE OR REPLACE PACKAGE LDAP_PLUGIN_EXAMPLE1 AS 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 ); END LDAP_PLUGIN_EXAMPLE1; /
プラグイン・パッケージ本体を作成します。
CREATE OR REPLACE PACKAGE BODY LDAP_PLUGIN_EXAMPLE1 AS 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 ) IS BEGIN INSERT INTO simple_tab VALUES (to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'), baseDN, scope, filterStr, result); -- The following code segment demonstrate how to iterate -- the ODS.strCollection FOR l_counter1 IN 1..requiredAttr.COUNT LOOP INSERT INTO simple_tab values (seq.NEXTVAL, 'req attr ' || l_counter1 || ' = ' || requiredAttr(l_counter1)); END LOOP; rc := 0; errormsg := 'no post_search plug-in error msg'; COMMIT; EXCEPTION WHEN others THEN rc := 1; errormsg := 'exception: post_search plug-in'; END; END LDAP_PLUGIN_EXAMPLE1; /
プラグイン・エントリをOracle Internet Directoryに登録します。
dn: cn=post_search,cn=plugin,cn=subconfigsubentry objectclass: orclPluginConfig objectclass: top orclPluginName: ldap_plugin_example1 orclPluginType: configuration orclPluginTiming: post orclPluginLDAPOperation: ldapsearch orclPluginEnable: 1 orclPluginVersion: 1.0.1 cn: post_search orclPluginKind: PLSQL
ldapadd
コマンド行ツールを使用して、このエントリを追加します。
% ldapadd –p port_number –h host_name –D bind_dn –q –v \ –f register_post_search.ldif
状況: 相互に依存する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メソッドを使用して変更できません。
プラグイン・プログラムを記述する際には、操作属性 |
両方のDITのエントリはディレクトリに追加されていると仮定します。たとえば、エントリid=12345,cn=DIT1,cn=products,cn=oraclecontext
はDIT1
に、エントリid=12345,cn=DIT2,cn=products,cn=oraclecontext
はDIT2
にあります。
プラグイン・パッケージ仕様を作成します。
CREATE OR REPLACE PACKAGE LDAP_PLUGIN_EXAMPLE2 AS PROCEDURE post_delete (ldapplugincontext IN ODS.plugincontext, result IN INTEGER, dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 ); END LDAP_PLUGIN_EXAMPLE2; /
プラグイン・パッケージ本体を作成します。
CREATE OR REPLACE PACKAGE BODY LDAP_PLUGIN_EXAMPLE2 AS PROCEDURE post_delete (ldapplugincontext IN ODS.plugincontext, result IN INTEGER, dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 ) IS retval PLS_INTEGER; my_session DBMS_LDAP.session; newDN VARCHAR2(256); BEGIN retval := -1; my_session := LDAP_PLUGIN.init(ldapplugincontext); -- bind to the directory retval := LDAP_PLUGIN.simple_bind_s(ldapplugincontext, my_session); -- if retval is not 0, then raise exception newDN := REPLACE(dn,'DIT1','DIT2'); retval := DBMS_LDAP.delete_s(my_session, newDN); -- if retval is not 0, then raise exception rc := 0; errormsg := 'no post_delete plug-in error msg'; EXCEPTION WHEN others THEN rc := 1; errormsg := 'exception: post_delete plug-in'; END; END LDAP_PLUGIN_EXAMPLE2; / (ldapplugincontext IN ODS.plugincontext, result IN INTEGER, dn IN VARCHAR2, rc OUT INTEGER, errormsg OUT VARCHAR2 ) IS retval PLS_INTEGER; my_session DBMS_LDAP.session; newDN VARCHAR2(256); BEGIN retval := -1; my_session := LDAP_PLUGIN.init(ldapplugincontext); -- bind to the directory retval := LDAP_PLUGIN.simple_bind_s(ldapplugincontext, my_session); -- if retval is not 0, then raise exception newDN := REPLACE(dn,'DIT1','DIT2'); retval := DBMS_LDAP.delete_s(my_session, newDN); -- if retval is not 0, then raise exception rc := 0; errormsg := 'no post_delete plug-in error msg'; EXCEPTION WHEN others THEN rc := 1; errormsg := 'exception: post_delete plug-in'; END; END LDAP_PLUGIN_EXAMPLE2; /
プラグイン・エントリをOracle Internet Directoryに登録します。
LDIFファイルregister_post_delete.ldif
を構成します。
dn: cn=post_delete,cn=plugin,cn=subconfigsubentry objectclass: orclPluginConfig objectclass: top orclPluginName: ldap_plugin_example2 orclPluginType: configuration orclPluginTiming: post orclPluginLDAPOperation: ldapdelete orclPluginEnable: 1 orclPluginSubscriberDNList: cn=DIT1,cn=oraclecontext,cn=products orclPluginVersion: 1.0.1 cn: post_delete orclPluginKind: PLSQL
ldapadd
コマンド行ツールを使用して、このエントリを追加します。
% ldapadd –p port_number –h host_name –D bind_dn –q –v –f register_ post_delete.ldif
リリース10.1.2から、プラグインLDAP APIのオブジェクト定義によって、ldapmodify
、ldapadd
およびldapcompare
のプラグインがディレクトリ・データベース内のバイナリ属性にアクセスできるようになりました。これまでは、アクセスできるのはタイプVARCHAR2
の属性のみでした。これらのオブジェクト定義では、リリース10.1.2より前のプラグイン・コードは無効化されません。このコードを変更する必要はありません。新しい定義は、第F.4項「データベース・オブジェクト・タイプの定義」に記載されています。
この項では、3種類のプラグインが関係するバイナリ操作について説明します。これらのプラグインの例も示します。新しいオブジェクト定義は、3つすべてについて操作前、操作後および操作時のバージョンに適用されます。
3つの例では、LOBのかわりにRAWファンクションおよび変数を使用していることに注意してください。
プラグイン・フレームワークが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;
プラグイン・フレームワークが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;
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;
この項では、プラグイン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;
プラグインを使用する場合、各プラグインに定義されたシグネチャに従う必要があります。次に各シグネチャを示します。
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 );