| Oracle® Fusion Middleware Oracle Directory Server Enterprise Edition開発者ガイド 11g リリース1 (11.1.1.7.0) B72440-01 |
|
![]() 前 |
![]() 次 |
この章では、クライアント向けの操作を実行する前後にDirectory Serverが行う内容を変更するためのプラグインAPIでのサポートについて説明します。
認証はバインド操作に関連していますが、このことについては第6章「プラグインを使用した認証の処理」で個別に説明します。
この章の内容は、次のとおりです。
Directory Serverでは、クライアント・リクエストを処理するとき、およびクライアントに情報を送信するときに、事前操作プラグイン関数と事後操作プラグイン関数をコールします。
事前操作プラグインは、クライアント・リクエストが処理される前にコールされます。たとえば、属性値を検証し、リクエストで指定された属性に追加および削除するには、事前操作プラグインを使用します。
事後操作プラグインは、操作が正常に完了したかどうかに関係なく、クライアント・リクエストが処理され、すべての結果がクライアントに送信された後にコールされます。アラートまたはアラームを送信するには、事後操作プラグインを使用します。また、監査作業またはクリーンアップ作業を実行するためにも、事後操作プラグインを使用します。
|
注意: Directory Serverは、外部クライアントが関与する場合にのみ、事前操作および事後操作プラグインをコールします。内部的に、Directory Serverは、外部クライアントによって要求されなかった操作も実行します。 これを可能にするために、Directory Serverは外部操作と内部操作を識別します。外部操作は、受信したクライアント・リクエストに応答します。内部操作は、対応するクライアント・リクエストなしで実行されるアクションです。 |
一部の操作では、事前操作および事後操作プラグイン関数の使用がサポートされています。操作には、中止、追加、バインド、比較、削除、変更、RDNの変更、検索、エントリの送信、参照の送信、結果の送信およびバインド解除が含まれています。プラグインは、クライアント・アプリケーションによって接続されたDirectory Serverフロントエンドに関係なく機能します。
他のプラグイン関数の場合のように、slapi_pblock_set()をプラグインの初期化関数で使用して、事前操作および事後操作プラグイン関数を登録します。slapi_pblock_set()の詳細は、「プラグインAPIリファレンス」を参照してください。
事前操作プラグインの登録では、SLAPI_PLUGIN_PRE_operation_FNの形式のIDを使用します。事後操作の登録では、SLAPI_PLUGIN_POST_operation_FNの形式のIDを使用します。ここで、operationは、ABANDON、ADD、BIND、COMPARE、DELETE、ENTRY (エントリをクライアントに送信)、MODIFY、MODRDN、REFERRAL (参照をクライアントに送信)、RESULT (結果をクライアントに送信)、SEARCHまたはUNBINDのいずれかになります。
|
注意: 事前操作および事後操作プラグインでは、 |
これらのIDの詳細は、「プラグインAPIリファレンス」を参照してください。構築時に使用されるIDの完全なリストは、install-path/include/slapi-plugin.hも参照してください。
次の例は、適切な登録IDを使用して関数がDirectory Serverに登録される仕組みを示しています。
例5-1 事後操作関数の登録(testpostop.c)
#include "slapi-plugin.h"
Slapi_PluginDesc postop_desc = {
"test-postop", /* plug-in identifier */
"Oracle Corporation (test)", /* vendor name */
"11.1.1.3.0", /* plug-in revision number */
"Sample post-operation plug-in" /* plug-in description */
};
static Slapi_ComponentId * postop_id; /* Used to set log */
/* Register the plug-in with the server. */
#ifdef _WIN32
__declspec(dllexport)
#endif
int
testpostop_init(Slapi_PBlock * pb)
{
int rc = 0; /* 0 means success */
rc |= slapi_pblock_set( /* Plug-in API version */
pb,
SLAPI_PLUGIN_VERSION,
SLAPI_PLUGIN_CURRENT_VERSION
);
rc |= slapi_pblock_set( /* Plug-in description */
pb,
SLAPI_PLUGIN_DESCRIPTION,
(void *) &postop_desc
);
rc |= slapi_pblock_set( /* Open log at startup */
pb,
SLAPI_PLUGIN_START_FN,
(void *) testpostop_set_log
);
rc |= slapi_pblock_set( /* Post-op add function */
pb,
SLAPI_PLUGIN_POST_ADD_FN,
(void *) testpostop_add
);
rc |= slapi_pblock_set( /* Post-op modify function */
pb,
SLAPI_PLUGIN_POST_MODIFY_FN,
(void *) testpostop_mod
);
rc |= slapi_pblock_set( /* Post-op delete function */
pb,
SLAPI_PLUGIN_POST_DELETE_FN,
(void *) testpostop_del
);
rc |= slapi_pblock_set( /* Post-op modrdn function */
pb,
SLAPI_PLUGIN_POST_MODRDN_FN,
(void *) testpostop_modrdn
);
rc |= slapi_pblock_set( /* Close log on shutdown */
pb,
SLAPI_PLUGIN_CLOSE_FN,
(void *) testpostop_free_log
);
/* Plug-in identifier is required for internal search. */
rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &postop_id);
return (rc);
}
事後操作関数に加えて、前述の例に示したプラグインが関数を登録します。プラグインは、起動時にログ・ファイルを開きます。プラグインは、停止時にログ・ファイルを閉じます。詳細は、install-path/examples/testpostop.cを参照してください。
プラグインの例は、install-path/examples/にあります。
この項では、クライアントのバインド操作の前にDirectory Serverによってコールされる機能を開発する方法について説明します。
|
注意: バインド前プラグイン関数は、認証に対する拡張機能の処理によく使用されます。ただし、ディレクトリのスーパーユーザーと匿名ユーザーによるバインドなどの特別なケースを考慮することが必要となることがあります。場合によっては、同じ事前操作または事後操作プラグイン関数に対する複数のコールを考慮する必要があります。 |
実行済でない場合には、サフィックスdc=example,dc=comを使用して、サンプルのLDIFファイルinstall-path/resources/ldif/Example.ldifからロードされたデータを含むディレクトリ・インスタンスを設定します。
新規Directory Serverインスタンスを作成します。
次に例を示します。
$ dsadm create -h localhost -p 1389 /local/ds Choose the Directory Manager password: Confirm the Directory Manager password: $
新規Directory Serverインスタンスを開始します。
次に例を示します。
$ dsadm start /local/ds Server started: pid=4705 $
サフィックスdc=example,dc=comを作成します。
たとえば、長い行は印刷ページに合わせて折り返します。
$ dsconf create-suffix -h localhost -p 1389 dc=example,dc=com Enter "cn=directory manager" password: Certificate "CN=defaultCert, CN=hostname:1636" presented by the server is not trusted. Type "Y" to accept, "y" to accept just once, "n" to refuse, "d" for more details: Y $
サンプルLDIFをロードします。
たとえば、長い行は印刷ページに合わせて折り返します。
$ dsconf import -h localhost -p 1389 \ install-path/resources/ldif/Example.ldif dc=example,dc=com Enter "cn=directory manager" password: New data will override existing data of the suffix "dc=example,dc=com". Initialization will have to be performed on replicated suffixes. Do you want to continue [y/n] ? y ## Index buffering enabled with bucket size 16 ## Beginning import job... ## Processing file "install-path/resources/ldif/Example.ldif" ## Finished scanning file "install-path/resources/ldif/Example.ldif" (160 entries) ## Workers finished; cleaning up... ## Workers cleaned up. ## Cleaning up producer thread... ## Indexing complete. ## Starting numsubordinates attribute generation. This may take a while, please wait for further activity reports. ## Numsubordinates attribute generation complete. Flushing caches... ## Closing files... ## Import complete. Processed 160 entries in 5 seconds. (32.00 entries/sec) Task completed (slapd exit code: 0). $
関連項目
Directory Service Control Centerを使用して、このタスクを実行できます。
次の例では、バインド認証方式をログに記録しています。完全なサンプル・コードは、install-path/examples/testpreop.cを参照してください。
例5-2 認証方式のロギング(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_bind(Slapi_PBlock * pb)
{
char * auth; /* Authentication type */
char * dn; /* Target DN */
int method; /* Authentication method */
int connId, opId, rc = 0;
long msgId;
/* Get target DN for bind and authentication method used. */
rc |= slapi_pblock_get(pb, SLAPI_BIND_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
if (rc == 0) {
switch (method) {
case LDAP_AUTH_NONE: auth = "No authentication";
break;
case LDAP_AUTH_SIMPLE: auth = "Simple authentication";
break;
case LDAP_AUTH_SASL: auth = "SASL authentication";
break;
default: auth = "Unknown authentication method";
break;
}
} else {
return (rc);
}
/* Log target DN and authentication method info. */
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpreop_bind in test-preop plug-in",
"Target DN: %s\tAuthentication method: %s\n", dn, auth
);
return (rc);
}
このプラグイン関数によって、認証methodに基づいてauthメッセージが設定されます。この関数による処理は、Directory Serverがバインドを処理する方法に影響しません。
実行済でない場合には、サンプルのプラグイン・ライブラリを作成し、プラグイン情報のロギングとサンプル・プラグインの両方をアクティブ化します。
プラグインを構築します。
ヒント: install-path/examples/Makefileまたはinstall-path/examples/Makefile64を使用します。
プラグイン情報メッセージがログに記録されるようにDirectory Serverを構成し、プラグインをロードします。
$ dsconf create-plugin -F custom-plugin-init-function -G custom-plugin-argument -H lib-path \
-Y custom-plugin-type "Custom Plugin"
$ dsconf enable-plugin "Custom Plugin"
ヒント: 詳細は、プラグインのソース・ファイルに指定されたコマンドを使用して参照してください。
Directory Serverを再起動します。
$ dsadm restart instance-path
Kirsten Vaughan (例)としてバインドします。
$ ldapsearch -h localhost -p 1389 -b "dc=example,dc=com" \ -D "uid=kvaughan,ou=people,dc=example,dc=com" -w bribery "(uid=*)"
instance-path/logs/errorsで、testpreop_bind()関数からの結果メッセージを検索します。
エントリのハウスキーピング情報を無視すると、次の内容に類似した出力が表示されます。
Target DN: uid=kvaughan,ou=people,dc=example,dc=com Authentication method: Simple authentication
注意が必要なバインド前プラグイン関数の詳細は、第6章「プラグインを使用した認証の処理」を参照してください。
プラグインが0を戻すと、Directory Serverはバインドを処理し続けます。Directory Serverのバインド処理をバイパスするには、パラメータ・ブロックでSLAPI_CONN_DNを設定し、1などの正の値を戻します。
Directory Serverは、LDAPバインド・モデルに従います。少なくとも、サーバーはクライアントを認証します。また、サーバーは、バインド・レスポンスを送信して認証ステータスも示します。詳細は、RFC 1777 (http://www.ietf.org/rfc/rfc1777.txt)『Lightweight Directory Access Protocol』およびRFC 45111 (http://www.ietf.org/rfc/rfc4511.txt)『Lightweight Directory Access Protocol (v3)』を参照してください。
|
注意: Lightweight Directory Access Protocol (v2)は廃止されたため、Lightweight Directory Access Protocol (v3)が推奨プロトコルになります。 |
この項では、LDAP検索操作の前にDirectory Serverによってコールされる機能を開発する方法について説明します。
次の例では、検索をリクエストするクライアントのDNをログに記録しています。完全なサンプル・コードは、install-path/examples/testbind.cを参照してください。
この項の内容に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。前述の「バインド操作の拡張」と「プラグインを登録するには」を参照してください。プラグインTest Bindにも、事前検索関数があります。
test_search()関数は、次の例に示すようにリクエストをログに記録します。
例5-3 検索を要求するクライアントのDNの取得(testbind.c)
#include "slapi-plugin.h"
int
test_search(Slapi_PBlock * pb)
{
char * requestor_dn; /* DN of client searching */
int is_repl; /* Is this replication? */
int is_intl; /* Is this an internal op? */
int connId, opId, rc = 0;
long msgId;
rc |=slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |=slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |=slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |=slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &requestor_dn);
rc |=slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
rc |=slapi_pblock_get(pb, SLAPI_IS_INTERNAL_OPERATION, &is_intl);
if (rc != 0) return (rc);
/* Do not interfere with replication and internal operations. */
if (is_repl || is_intl) return 0;
if (requestor_dn != NULL && *requestor_dn != '\0') {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_search in test-bind plug-in",
"Search requested by %s\n", requestor_dn
);
} else {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"test_search in test-bind plug-in",
"Search requested by anonymous client.\n"
);
}
return (rc);
}
サーバーでプラグインをアクティブ化した後に検索を実行します。
$ ldapsearch -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ -h localhost -p 1389 -b dc=example,dc=com uid=bjensen
instance-path/logs/errorsで、結果メッセージを検索します。ログ・エントリの最終フィールドに次のように表示されます。
Directory Serverでアクティブ化されたプラグインを使用して、Kirsten Vaughanとして検索を実行します。
Authenticated: uid=kvaughan,ou=people,dc=example,dc=com
検索フィルタの分類では、検索フィルタを分類して、フィルタのコンポーネント部分をログに記録します。完全なサンプル・コードは、install-path/examples/testpreop.cを参照してください。
SLAPI_PLUGIN_PRE_SEARCH_FN関数のコードtestpreop_search()の前には、3つのマクロが付きます。testpreop.cで#define LOG1(format)を検索します。これらのマクロの目的は、その後のロギング文をよりコンパクトにしてコードを解読しやすくすることのみです。LOG1、LOG2およびLOG3の桁は、各マクロが取るパラメータ数を反映しています。ログ関数によってprintf ()のスタイルで文字列をフォーマットできるため、ログ関数に渡す実際のパラメータ数は様々に異なります。
検索前関数に渡されるパラメータ・ブロックには、検索のターゲットと範囲の情報が含まれます。次の例は、この情報を取得する方法を示しています。RFC 4511 (http://www.ietf.org/rfc/rfc4511.txt)『Lightweight Directory Access Protocol (v3)』で指定されているように、範囲に次のいずれかを含めることができます。
ベース・オブジェクト(ベースDNエントリ)
ベースDNの下の単一レベル
ベースDNの下のサブツリー全体
例5-4 検索のベースおよび範囲のロギング(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_search(Slapi_PBlock * pb)
{
char * base = NULL;/* Base DN for search */
int scope; /* Base, 1 level, subtree */
int rc = 0;
rc |= slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &base);
rc |= slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
if (rc == 0) {
switch (scope) {
case LDAP_SCOPE_BASE:
LOG2("Target DN: %s\tScope: LDAP_SCOPE_BASE\n", base);
break;
case LDAP_SCOPE_ONELEVEL:
LOG2("Target DN: %s\tScope: LDAP_SCOPE_ONELEVEL\n", base);
break;
case LDAP_SCOPE_SUBTREE:
LOG2("Target DN: %s\tScope: LDAP_SCOPE_SUBTREE\n", base);
break;
default:
LOG3("Target DN: %s\tScope: unknown value %d\n", base, scope);
break;
}
} /* Continue processing... */
return 0;
}
X.500検索ターゲットをLDAP検索ターゲットにマップするプラグインの作成中に、検索のためにベースDNを分析して変換することを選択できます。
パラメータ・ブロックには、次の情報も含まれます。
検索中に別名が解決される時期
検索が消費するように設定されたDirectory Serverリソース
戻される属性タイプ
パラメータ・ブロックから取得する検索フィルタを考慮する必要があります。testpreop_search()は、Slapi_Filter構造体のfilterと文字列filter_strの両方としてパラメータ・ブロックからフィルタを取得します。Directory Serverに渡され、Slapi_Filter構造体で取得される検索フィルタの種類に応じて、プラグインは様々な方法でフィルタを分類します。関数が検索前ではなく検索後だった場合、パラメータ・ブロックを介して戻される結果にアクセスすることになります。結果へのアクセスの手順は、「プラグインAPIリファレンス」を参照してください。
プラグインAPIは、検索フィルタを操作するための様々な関数を提供しています。testpreop_search()は、slapi_filter_get_choice ()を使用して、使用されるフィルタの種類を決定します。事前操作検索関数も、slapi_filter_get_subfilt()を使用してフィルタで使用される部分文字列を分類します。事前操作検索関数は、さらに、slapi_filter_get_type()を使用して、属性の有無を検索するときに属性タイプを検出します。事前操作検索関数は、slapi_filter_get_ava()を使用して、比較に使用される属性の型と値を取得します。
次の例は、検索フィルタから情報を取得するコードを示しています。
例5-5 フィルタ情報の取得(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_search(Slapi_PBlock * pb)
{
char * attr_type = NULL;/* For substr and compare */
char * substr_init= NULL;/* For substring filters */
char * substr_final=NULL;
char ** substr_any = NULL;
int i, rc =0;
Slapi_Filter * filter;
rc |= slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
if (rc == 0) {
filter_type = slapi_filter_get_choice(filter);
switch (filter_type) {
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
case LDAP_FILTER_NOT:
LOG1("Search filter: complex boolean\n");
break;
case LDAP_FILTER_EQUALITY:
LOG1("Search filter: LDAP_FILTER_EQUALITY\n");
break;
case LDAP_FILTER_GE:
LOG1("Search filter: LDAP_FILTER_GE\n");
break;
case LDAP_FILTER_LE:
LOG1("Search filter: LDAP_FILTER_LE\n");
break;
case LDAP_FILTER_APPROX:
LOG1("Search filter: LDAP_FILTER_APPROX\n");
break;
case LDAP_FILTER_SUBSTRINGS:
LOG1("Search filter: LDAP_FILTER_SUBSTRINGS\n");
slapi_filter_get_subfilt(
filter,
&attr_type,
&substr_init,
&substr_any,
&substr_final
);
if (attr_type != NULL)
LOG2("\tAttribute type: %s\n", attr_type);
if (substr_init != NULL)
LOG2("\tInitial substring: %s\n", substr_init);
if (substr_any != NULL)
for (i = 0; substr_any[i] != NULL; ++i) {
LOG3("\tSubstring# %d: %s\n", i, substr_any[i]);
}
if (substr_final != NULL)
LOG2("\tFinal substring: %s\n", substr_final);
break;
case LDAP_FILTER_PRESENT:
LOG1("Search filter: LDAP_FILTER_PRESENT\n");
slapi_filter_get_attribute_type(filter, &attr_type);
LOG2("\tAttribute type: %s\n", attr_type);
break;
case LDAP_FILTER_EXTENDED:
LOG1("Search filter: LDAP_FILTER_EXTENDED\n");
break;
default:
LOG2("Search filter: unknown type %d\n", filter_type);
break;
}
}
return (rc);
}
ここでの説明に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。前述の「バインド操作の拡張」と「プラグインを登録するには」を参照してください。
サンプル・サフィックスとプラグインをディレクトリにロードしたら、検索を実行してinstance-path/logs/errorsに出力を生成します。
$ ldapsearch -h localhost -p 1389 -b "dc=example,dc=com" "(uid=*go*iv*)"
エラー・ログのハウスキーピング情報を無視すると、次の例に示すように検索フィルタのブレークダウンが発生します。
例5-6 検索フィルタのブレークダウン
*** PREOPERATION SEARCH PLUG-IN - START ***
Target DN: dc=example,dc=com Scope: LDAP_SCOPE_SUBTREE
Dereference setting: LDAP_DEREF_NEVER
Search filter: LDAP_FILTER_SUBSTRINGS
Attribute type: uid
Substring# 0: go
Substring# 1: iv
String representation of search filter: (uid=*go*iv*)
*** PREOPERATION SEARCH PLUG-IN - END ***
フィルタを構築するとき、プラグインAPIは、文字列をSlapi_Filterデータ型に変換するためのslapi_str2filter ()と、単純なフィルタをブール演算子AND、ORまたはNOTと結合するためのslapi_filter_join()を提供します。slapi_filter_free()を使用してフィルタを解放します。詳細は、「プラグインAPIリファレンス」を参照してください。
Directory Serverは、候補エントリのリストを取得し、リストに対して処理を繰り返して検索条件と一致するエントリを確認します。プラグインは、一連の結果をパラメータ・ブロックに配置します。ほとんどの場合、プラグイン内での検索は、一般的に、slapi_search_internal*()のコールを使用して実行されます。
この項では、クライアントの比較操作の前にDirectory Serverによってコールされる機能を開発する方法について説明します。次の例では、ターゲットDNと、値と比較するエントリの属性をログに記録しています。完全なサンプル・コードは、install-path/examples/testpreop.cを参照してください。
例5-7 プラグインの比較関数(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_cmp(Slapi_PBlock * pb)
{
char * dn; /* Target DN */
char * attr_type; /* Type of attr to compare */
/* Attribute value could be lots of things, even a binary file.
* Here, do not try to retrieve the value to compare. */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_COMPARE_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_COMPARE_TYPE, &attr_type);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
if (rc == 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpreop_cmp in test-preop plug-in",
"Target DN: %s\tAttribute type: %s\n", dn, attr_type
);
}
return (rc);
}
プラグイン関数は、比較に使用するために属性値にアクセスできます。パラメータ・ブロックの属性値は、berval構造体にあります。そのため、値はJPEGイメージなどのバイナリ・データである可能性があります。ログに値は書き込まれません。
次の例は、属性値の取得に使用されるslapi_pblock_get()のコールを示しています。
例5-8 属性値の取得
#include "slapi-plugin.h"
int
my_compare_fn(Slapi_PBlock * pb)
{
int rc = 0;
struct berval * attr_val;
/* Obtain the attribute value from the parameter block */
rc |= slapi_pblock_get(pb, SLAPI_COMPARE_VALUE, &attr_val);
if (rc != 0) {
rc = LDAP_OPERATIONS_ERROR;
slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
return 0;
}
/* Do something with the value here. */
return 0;
}
ここでの説明に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。前述の「バインド操作の拡張」と「プラグインを登録するには」を参照してください。
Directory Serverリソース・キットと一緒にインストールされるldapcompareツールを使用して、サンプルのプラグイン関数を試します。
例5-9 比較の実行
$ ldapcompare sn:Jensen uid=bjensen,ou=people,dc=example,dc=com comparing type: "sn" value: "Jensen" in entry "uid=bjensen,ou=people,dc=example,dc=com" compare TRUE
instance-path/logs/errorsのログ・エントリには次の結果が表示されますが、ログ・エントリの最初にハウスキーピング情報は含まれません。
Target DN: uid=bjensen,ou=people,dc=example,dc=com Attribute type: sn
この項では、クライアントの追加操作の前後にDirectory Serverによってコールされる機能を開発する方法について説明します。
例39-10では、ディレクトリに追加されるエントリの説明属性の前に文字列ADDを追加しています。完全なサンプル・コードは、instance-path/examples/testpreop.cを参照してください。
ここでの説明に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。前述の「バインド操作の拡張」と「プラグインを登録するには」を参照してください。
事前操作追加関数を試すには、最近Example.comに加わったQuentin Cubbinsのエントリを追加します。QuentinのLDIFエントリquentin.ldifは、次の例のようになります。
例5-10 LDIFエントリ
dn: uid=qcubbins,ou=People,dc=example,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com userPassword: qcubbins secretary: uid=bjensen,ou=People,dc=example,dc=com description: Entry for Quentin Cubbins
次の例では、前への追加を実行しています。
例5-11 エントリの説明の前へのADDの追加(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_add(Slapi_PBlock * pb)
{
Slapi_Entry * entry; /* Entry to add */
Slapi_Attr * attribute; /* Entry attributes */
Slapi_Value ** values; /* Modified, duplicate vals*/
int connId, opId, rc = 0;
long msgId;
/* Get the entry. */
rc |= slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &entry);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
/* Prepend ADD to values of description attribute. */
rc |= slapi_entry_attr_find(entry, "description", &attribute);
if (rc == 0) { /* Found a description, so... */
int nvals, i, count = 0;
const Slapi_Value * value;
slapi_attr_get_numvalues(attribute, &nvals);
values = (Slapi_Value **)
slapi_ch_malloc((nvals+1)*sizeof(Slapi_Value *));
for ( /* ...loop for value... */
i = slapi_attr_first_value_const(attribute, &value);
i != -1;
i = slapi_attr_next_value_const(attribute, i, &value)
) { /* ...prepend "ADD ". */
const char * string;
char * tmp;
values[count] = slapi_value_dup(value);
string = slapi_value_get_string(values[count]);
tmp = slapi_ch_malloc(5+strlen(string));
strcpy(tmp, "ADD ");
strcpy(tmp+4, string);
slapi_value_set_string(values[count], tmp);
slapi_ch_free((void **)&tmp);
++count;
}
values[count] = NULL;
} else { /* entry has no desc. */
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpreop_add in test-preop plug-in",
"Entry has no description attribute.\n"
);
}
rc = slapi_entry_attr_replace_sv(entry, "description", values);
if (rc != 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpreop_add in test-preop plug-in",
"Description attribute(s) not modified.\n"
);
}
slapi_valuearray_free(&values);
return 0;
}
Quentinのエントリをディレクトリに追加します。たとえば、エントリがquentin.ldifにある場合、次のように入力します。
$ ldapmodify -h localhost -p 1389 -a -f quentin.ldif \ -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery adding new entry uid=qcubbins,ou=People,dc=example,dc=com $
ここで、Quentinのエントリについてディレクトリを検索します。
例5-12 エントリの検索
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com uid=qcubbins version: 1 dn: uid=qcubbins,ou=People,dc=example,dc=com objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com secretary: uid=bjensen,ou=People,dc=example,dc=com description: ADD Entry for Quentin Cubbins $
説明属性の値に注意してください。
Quentinのエントリを後で例として再度使用できるように削除します。
$ ldapdelete -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ uid=qcubbins,ou=people,dc=example,dc=com
事前操作プラグインをオフにして、追加するすべてのエントリの前にADDが追加されないようにします。
$ dsconf disable-plugin -h localhost -p 1389 "Test Preop"
$ dsadm restart instance-path
追加するエントリのロギングでは、追加するエントリをログに記録します。完全なサンプル・コードは、instance-path/examples/testpostop.cを参照してください。
ここでの説明に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。「バインド操作の拡張」を参照してください。
testpostop_add()関数は、追加されるエントリのDNをログに記録し、プラグインchangelog.txtによって作成されるログにエントリも書き込みます。changelog.txtの場所は、次の例に示すようにプラットフォームによって異なります。プラグインによって管理されるchangelog.txtファイルは、Directory Serverによって管理される他の変更ログには関連付けられません。
例5-13 追加されたエントリの追跡(testpostop.c)
#include "slapi-plugin.h"
int
testpostop_add(Slapi_PBlock * pb)
{
char * dn; /* DN of entry to add */
Slapi_Entry * entry; /* Entry to add */
int is_repl = 0; /* Is this replication? */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &entry);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
if (rc != 0) return (rc);
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpostop_add in test-postop plug-in",
"Added entry (%s)\n", dn
);
/* In general, do not interfere in replication operations. */
/* Log the DN and the entry to the change log file. */
if (!is_repl) write_changelog(_ADD, dn, (void *) entry, 0);
return (rc);
}
プラグインをアクティブ化した後、Quentinのエントリを追加します。
$ ldapmodify -a -D uid=kvaughan,ou=people,dc=example,dc=com \ -h localhost -p 1389 -w bribery -f quentin.ldif adding new entry uid=qcubbins,ou=People,dc=example,dc=com $
ログ・メッセージについてinstance-path/logs/errorsを検索します。ハウスキーピング情報を無視する場合は、次のメッセージが表示されます。
Added entry (uid=qcubbins,ou=people,dc=example,dc=com)
changelog.txtに記録されるエントリにも注意してください。次の例に示すように内部使用向けに付加されたタイムスタンプが変更ログにあることを除いて、エントリは、追加されたLDIFに類似しています。
例5-14 changelog.txtエントリの例
time: 21120506172445 dn: uid=qcubbins,ou=people,dc=example,dc=com changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com secretary: uid=bjensen,ou=People,dc=example,dc=com userPassword: qcubbins creatorsName: cn=Directory Manager modifiersName: cn=Directory Manager createTimestamp: 21120506152444Z modifyTimestamp: 21120506152444Z
この項では、クライアントの変更操作の後にDirectory Serverによってコールされる機能を開発する方法について説明します。事前操作プラグインは、ここには示されていませんが、install-path/examples/testpreop.cで確認できます。ここで説明されるソース・コードは、install-path/examples/testpostop.cを参照してください。
ここでの説明に従ってプラグイン関数を使用する前に、「追加するエントリのロギング」で説明されているようにDirectory Serverを設定して、Quentinのエントリを忘れずに追加します。
testpostop_mod()関数は、変更されたエントリのDNをログに記録し、プラグインchangelog.txtによって管理されるログにエントリも書き込みます。changelog.txtの場所は、ソース・コードに示すように、プラットフォームによって異なります。
次の例は、ロギングを実行するコードを示しています。
例5-15 変更されたエントリの追跡(testpostop.c)
#include "slapi-plugin.h"
int
testpostop_mod(Slapi_PBlock * pb)
{
char * dn; /* DN of entry to modify */
LDAPMod ** mods; /* Modifications to apply */
int is_repl = 0; /* Is this replication? */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
if (rc != 0) return (rc);
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpostop_mod in test-postop plug-in",
"Modified entry (%s)\n", dn
);
/* In general, do not interfere in replication operations. */
/* Log the DN and the modifications made to the change log file. */
if (!is_repl) write_changelog(_MOD, dn, (void *) mods, 0);
return (rc);
}
まず、Quentinのエントリがディレクトリにあることを確認します。
例5-16 ディレクトリでのエントリの確認
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com uid=qcubbins version: 1 dn: uid=qcubbins,ou=People,dc=example,dc=com objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson uid: qcubbins givenName: Quentin sn: Cubbins cn: Quentin Cubbins mail: qcubbins@example.com secretary: uid=bjensen,ou=People,dc=example,dc=com
プラグインがDirectory Serverでアクティブ化されたら、Quentinのメール・アドレスを変更します。
例5-17 メール・アドレスの変更
$ ldapmodify -h localhost -p 1389 \ -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery dn: uid=qcubbins,ou=People,dc=example,dc=com changetype: modify replace: mail mail: quentin@example.com ^D
ログ・メッセージについてinstance-path/logs/errorsを検索します。ハウスキーピング情報を無視する場合は、次のメッセージが表示されます。
Modified entry (uid=qcubbins,ou=people,dc=example,dc=com)
次の例に示すように、changelog.txtに記録される情報にも注意してください。
この項では、クライアントのRDN変更操作の後にDirectory Serverによってコールされる機能について説明します。事前操作プラグインは、ここには示されていませんが、install-path/examples/testpreop.cで確認できます。ここで説明されるソース・コードは、install-path/examples/testpostop.cを参照してください。
ここでの説明に従ってプラグイン関数を使用する前に、「追加するエントリのロギング」で説明されているようにDirectory Serverを設定して、Quentinのエントリを忘れずに追加します。
testpostop_modrdn()関数は、変更されたエントリのDNをログに記録し、プラグインchangelog.txtによって管理されるログにもエントリを書き込みます。changelog.txtの場所は、ソース・コードに示すように、プラットフォームによって異なります。
次の例は、ロギングを実行するコードを示しています。
例5-19 名前が変更されたエントリの追跡(testpostop.c)
#include "slapi-plugin.h"
int
testpostop_modrdn( Slapi_PBlock *pb )
{
char * dn; /* DN of entry to rename */
char * newrdn; /* New RDN */
int dflag; /* Delete the old RDN? */
int is_repl = 0; /* Is this replication? */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_MODRDN_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
rc |= slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &dflag);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
if (rc != 0) return (rc);
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpostop_modrdn in test-postop plug-in",
"Modrdn entry (%s)\n", dn
);
/* In general, do not interfere in replication operations. */
/* Log the DN of the renamed entry, its new RDN, and the flag
* indicating whether the old RDN was removed to the change log. */
if (!is_repl) write_changelog(_MODRDN, dn, (void *) newrdn, dflag);
return (rc);
}
「変更操作の拡張」に示されているように、Quentinのエントリがディレクトリにあることを確認します。
先週末、Quentinは自分の名前をFredに変更することを決めました。彼のユーザーIDは現在fcubbinsのため、彼のエントリの名前を変更する必要があります。Directory Serverでアクティブ化されたこのプラグインを使用して、エントリを変更します。
例5-20 エントリの名前の変更
$ ldapmodify -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ -h localhost -p 1389 dn: uid=qcubbins,ou=People,dc=example,dc=com changetype: modify replace: givenName givenName: Fred dn: uid=qcubbins,ou=People,dc=example,dc=com changetype: modify replace: mail mail: fcubbins@example.com dn: uid=qcubbins,ou=People,dc=example,dc=com changetype: modify replace: cn cn: Fred Cubbins dn: uid=qcubbins,ou=People,dc=example,dc=com changetype: modrdn newrdn: uid=fcubbins deleteoldrdn: 1 ^D
ログ・メッセージについてinstance-path/logs/errorsを検索します。ハウスキーピング情報を無視する場合は、次のメッセージが表示されます。
Modrdn entry (uid=qcubbins,ou=people,dc=example,dc=com)
changelog.txtに記録される情報にも注意してください。
この項では、クライアントの削除操作の後にDirectory Serverによってコールされる機能を開発する方法について説明します。事前操作プラグインは、ここには示されていませんが、install-path/examples/testpreop.cで確認できます。ここで説明されるソース・コードは、install-path/examples/testpostop.cを参照してください。
ここでの説明に従ってプラグイン関数を使用する前に、「追加するエントリのロギング」で説明されているようにDirectory Serverを設定して、Quentinのエントリを忘れずに追加します。
testpostop_modrdn()関数は、変更されたエントリのDNをログに記録し、プラグインchangelog.txtによって管理されるログにもエントリを書き込みます。changelog.txtの場所は、ソース・コードに示すように、プラットフォームによって異なります。
次の例は、ロギングを実行するコードを示しています。
例5-22 エントリの削除の追跡(testpostop.c)
#include "slapi-plugin.h"
int
testpostop_del( Slapi_PBlock *pb )
{
char * dn; /* DN of entry to delete */
int is_repl = 0; /* Is this replication? */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_DELETE_TARGET, &dn);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
if (rc != 0) return (rc);
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpostop_del in test-postop plug-in",
"Deleted entry (%s)\n", dn
);
/* In general, do not interfere in replication operations. */
/* Log the DN of the deleted entry to the change log. */
if (!is_repl) write_changelog(_DEL, dn, NULL, 0);
return (rc);
}
まず、「変更操作の拡張」に示されているように、Quentinのエントリがディレクトリにあることを確認します。
「名前の変更操作の拡張」の説明に従ってエントリの名前を変更した場合は、Quentinの名前がFredになっている可能性があります。
Quentinは主要な顧客に多くの暴言を吐いてExample.comを解雇されたと仮定します。Directory Serverでアクティブ化されたこのプラグインを使用して、彼のエントリを削除します。
$ ldapdelete -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ uid=qcubbins,ou=People,dc=example,dc=com
ログ・メッセージについてinstance-path/logs/errorsを検索します。ハウスキーピング情報を無視する場合は、次のメッセージが表示されます。
Deleted entry (uid=qcubbins,ou=people,dc=example,dc=com)
次の例に示すように、changelog.txtに記録される情報にも注意してください。
この項では、結果コード、参照またはエントリをクライアント・アプリケーションに送信する前にDirectory Serverによってコールされる機能について説明します。ここで説明されるソース・コードは、install-path/examples/testpreop.cを参照してください。
次の例は、操作番号とユーザーDNをログに記録するコードを示しています。
例5-24 クライアントに対するロギングと応答(testpreop.c)
#include "slapi-plugin.h"
int
testpreop_send(Slapi_PBlock * pb)
{
Slapi_Operation * op; /* Operation in progress */
char * connDn; /* Get DN from connection */
int connId, opId, rc = 0;
long msgId;
rc |= slapi_pblock_get(pb, SLAPI_OPERATION, &op);
rc |= slapi_pblock_get(pb, SLAPI_CONN_DN, &connDn);
rc |= slapi_pblock_get(pb, SLAPI_CONN_ID, &connId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);
rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opId);
if (rc == 0) {
slapi_log_info_ex(
SLAPI_LOG_INFO_AREA_PLUGIN,
SLAPI_LOG_INFO_LEVEL_DEFAULT,
msgId,
connId,
opId,
"testpreop_send in test-preop plug-in",
"Operation: %d\tUser: %s\n", slapi_op_get_type(op), connDn
);
}
slapi_ch_free_string(&connDn);
return (rc);
}
操作IDは、プラグイン・ヘッダー・ファイルinstall-path/include/slapi-plugin.hで定義されています。SLAPI_OPERATION_*を検索します。
ここでの説明に従ってプラグイン関数を使用する前に、サンプル・サフィックスを設定してプラグインを登録します。前述の「バインド操作の拡張」と「プラグインを登録するには」を参照してください。
Directory Serverでアクティブ化されたプラグインを使用して、Kirsten Vaughanとして検索を実行します。
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com \ -D uid=kvaughan,ou=people,dc=example,dc=com -w bribery \ uid=bcubbins
ログ・メッセージについてinstance-path/logs/errorsを検索します。ハウスキーピング情報なしで、最初のメッセージは次のようにバインド結果を反映します。
Operation: 1 User: uid=kvaughan,ou=people,dc=example,dc=com
次のメッセージは、次のように検索を反映します。
Operation: 4 User: uid=kvaughan,ou=people,dc=example,dc=com
プラグイン関数内で、slapi_op_get_type()を使用して操作タイプを決定します。slapi_op_get_type ()の詳細は「プラグインAPIリファレンス」を参照し、操作タイプのリストはプラグイン・ヘッダー・ファイルinstall-path/include/slapi-plugin.hを参照してください。