Oracle® Fusion Middleware Oracle Directory Server Enterprise Edition開発者ガイド 11g リリース1 (11.1.1.7.0) B72440-01 |
|
前 |
次 |
この章では、LDAP v3の拡張操作を活用するためのプラグインの作成方法について説明します。拡張操作は、RFC 4511 (http://www.ietf.org/rfc/rfc4511.txt
)で定義されています。RFCには、「デジタル署名操作や結果など、このプロトコルの他の場所で使用できないサービス向けに定義されるその他の操作」と定義されています。
この章の内容は、次のとおりです。
この項では、拡張操作がDirectory Serverによって処理される仕組みについて説明します。また、拡張操作プラグインに設定される要件も説明します。
Directory Serverは、オブジェクト識別子(OID)によって拡張操作を識別します。クライアントは、次の項目を指定し、拡張操作リクエストを送信して操作を要求します。
拡張操作のOID
拡張操作に特有のデータ
拡張操作リクエストを受け取ると、Directory Serverは登録されたプラグインをコールして、リクエストで送信されるOIDを処理します。リクエストを処理するプラグイン関数は、OIDと操作特有のデータを取得します。プラグインは、情報を処理し、OIDと拡張操作に関係するその他のデータを含むクライアントにレスポンスを送信します。
拡張操作のサポートを実装するときは、使用するOIDを決定する必要があります。Internet Assigned Numbers Authorityは、公式OIDの登録に役立ちます。独自のOIDを選択する場合は、他のOIDと競合するOIDを避ける必要があります。特に、Directory Serverによって使用されるLDAPスキーマで定義されたOIDと競合するOIDは使用しないでください。
Directory Serverは、どの拡張操作プラグインがどの拡張操作OIDを起動時に処理するのかを決定します。その後、Directory Serverは、各プラグインの初期化関数をコールします。拡張操作プラグインは、「拡張操作プラグインの初期化」での説明に従って、プラグインが初期化関数の一部として処理する拡張操作OIDを登録します。
起動時にDirectory Serverがプラグイン初期化関数に渡すパラメータを、プラグインの構成エントリに含めることができます。これらのパラメータについては、「プラグインに渡される引数の取得」を参照してください。パラメータでは、プラグイン関数の作成後にOIDが決定される可能性が考慮されます。このようなOIDは、構成エントリ引数として渡されることがあります。
この項では、拡張操作をトリガーするために、基本の拡張操作プラグインとクライアント・アプリケーションを実装する方法を示します。
クライアントは、拡張操作を識別するOID (今回は1.2.3.4
)を使用して、サーバーに拡張操作リクエストを送信します。また、文字列を保持する値も送信します。サンプル・プラグインでは、クライアントにOIDを送信することによって拡張操作リクエストに応答しています。また、プラグインは、クライアントがリクエストとともに送信した文字列の変更されたバージョンも送信します。
この章の残りについては、install-path
/examples/testextendedop.c
のプラグイン・コードと、install-path
/examples/clients/reqextop.c
のクライアント・コードを参照してください。
この項では、拡張操作プラグインの動作の仕組みについて説明します。
ここでの説明に従ってプラグイン関数を使用する前に、プラグインを構築します。また、プラグインをロードするようにDirectory Serverも構成します。
OID 1.2.3.4
は、構成エントリを介して引数として渡されることに注意してください。たとえば、個別のOIDによってそれぞれが識別されている複数の拡張操作をプラグインがサポートしている場合、構成エントリは2つ以上のnsslapd-pluginarg
属性を指定できます。
実行済でない場合には、サンプルのプラグイン・ライブラリを作成し、プラグイン情報のロギングとサンプル・プラグインの両方をアクティブ化します。
プラグインを構築します。
ヒント: 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
他のプラグイン・タイプに関しては、拡張操作プラグインに、プラグインの他の関数をDirectory Serverに登録する初期化関数が含まれています。拡張操作プラグインの場合、この初期化関数は、プラグインによって操作されるOIDも登録します。関数は、関数が初期化関数に渡すパラメータ・ブロックのDirectory Serverで、SLAPI_PLUGIN_EXT_OP_OIDLIST
を設定することによってOIDを登録します。
例9-1 プラグイン関数とOIDの登録(testextendedop.c
)
この例では、OIDリストの構築方法と登録方法について説明します。
#include "slapi-plugin.h" Slapi_PluginDesc expdesc = { "test-extendedop", /* plug-in identifier */ "Oracle Corporation (test)", /* vendor name */ "11.1.1.3.0", /* plug-in revision number */ "Sample extended operation plug-in"/* plug-in description */ }; #ifdef _WIN32 __declspec(dllexport) #endif int testexop_init(Slapi_PBlock * pb) { char ** argv; /* Args from configuration */ int argc; /* entry for plug-in. */ char ** oid_list; /* OIDs supported */ int rc = 0; /* 0 means success */ int i; /* Get the arguments from the configuration entry. */ rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv); rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc); if (rc != 0) { slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, SLAPI_LOG_NO_MSGID, SLAPI_LOG_NO_CONNID, SLAPI_LOG_NO_OPID, "testexop_init in test-extendedop plug-in", "Could not get plug-in arguments.\n" ); return (rc); } /* Extended operation plug-ins may handle a range of OIDs. */ oid_list = (char **)slapi_ch_malloc((argc + 1) * sizeof(char *)); for (i = 0; i < argc; ++i) { oid_list[i] = slapi_ch_strdup(argv[i]); slapi_log_info_ex( SLAPI_LOG_INFO_AREA_PLUGIN, SLAPI_LOG_INFO_LEVEL_DEFAULT, SLAPI_LOG_NO_MSGID, SLAPI_LOG_NO_CONNID, SLAPI_LOG_NO_OPID, "testexop_init in test-extendedop plug-in", "Registering plug-in for extended operation %s.\n", oid_list[i] ); } oid_list[argc] = NULL; 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 *) &expdesc ); rc |= slapi_pblock_set( /* Extended op. handler */ pb, SLAPI_PLUGIN_EXT_OP_FN, (void *) test_extendedop ); rc |= slapi_pblock_set( /* List of OIDs handled */ pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, oid_list ); return (rc); }
Directory Serverによって渡される引数からOIDを抽出することに注意してください。Directory Serverは、各argv[]
要素でslapi_ch_strdup()
を使用することによって、構成エントリからパラメータ・ブロックに引数を渡します。OIDリストは、slapi_ch_malloc ()
を使用して配列にスペースを割り当て、各oid_list[]
要素にOIDを配置することによって構築されます。SLAPI_PLUGIN_EXT_OP_OIDLIST
を使用してプラグインOIDリストを登録します。表示のように、SLAPI_PLUGIN_EXT_OP_FN
を使用して拡張操作ハンドラ関数test_extendedop ()
を登録します。
パラメータ・ブロックの引数とプラグインAPI関数の詳細は、「プラグインAPIリファレンス」を参照してください。
プラグイン関数test_extendedop()
は、クライアント・リクエストから操作のOIDと値を取得します。その後、関数は、「拡張操作クライアントの開発」に示されているように、クライアントにレスポンスを送信します。
関数がSLAPI_EXT_OP_REQ_OID
とSLAPI_EXT_OP_REQ_VALUE
を使用してリクエストからOIDと値を取得する方法に注意してください。関数は、slapi_ch_malloc()
を使用し、berval
構造体result_bval
へのポインタを介してクライアントに戻す文字列を構成します。異なる拡張操作プラグインは、この時点で完全に異なる内容を実行することがあります。
また、関数は、クライアント・リクエストのOIDとは異なるOIDもクライアントに返信します。たとえば、返信されたOIDを使用して、クライアントに特定の結果を示すことができます。関数は、slapi_send_ldap_result()
を使用して成功したことを示し、クライアントにOIDと値も送信します。その後、関数は割り当てられたメモリーを解放します。最後に、関数は、SLAPI_PLUGIN_EXTENDED_SENT_RESULT
を戻して、プラグイン関数の処理が完了したことをDirectory Serverに示します。
関数は、クライアントに結果コードを送信しなかった場合、LDAP結果コードをDirectory Serverに戻します。Directory Serverが結果コードをクライアントに送信します。
関数は、指定のOIDを持つ拡張操作を処理できない場合は、SLAPI_PLUGIN_EXTENDED_NOT_HANDLED
を戻します。Directory Serverは、LDAP_PROTOCOL_ERROR
結果コードをクライアントに送信します。
プラグインをテストするには、OID 1.2.3.4
を持つ拡張操作を要求するクライアントが必要です。ここで説明する例(reqextop.c
)は、製品とともに提供されています。
クライアントは、拡張操作リクエストでDirectory Serverに送信するための短い文字列を設定します。その後、クライアントは、LDAPバージョン3をサポートしているLDAP接続を取得し、Directory Serverにバインドします。クライアントは、拡張操作リクエストを送信し、STDOUT
で結果を表示します。
例9-2 拡張操作を要求するクライアント(clients/reqextop.c
)
#include <stdlib.h> #include "ldap.h" /* Global variables for client connection information. * You may set these here or on the command line. */ static char * host = "localhost"; /* Server hostname */ static int port = 389; /* Server port */ static char * bind_DN = "cn=Directory Manager"; /* DN to bind as */ static char * bind_pwd = "23skidoo"; /* Password for bind DN */ /* Check for connection info as command line arguments. */ int get_user_args(int argc, char ** argv); int main(int argc, char ** argv) { /* OID of the extended operation that you are requesting */ const char * oidrequest = "1.2.3.4"; /* Ext op OID */ char * oidresult; /* OID in reply from server */ struct berval valrequest; /* Request sent */ struct berval * valresult; /* Reply received */ LDAP * ld; /* Handle to connection */ int version; /* LDAP version */ /* Use default connection arguments unless all four are * provided as arguments on the command line. */ if (get_user_args(argc, argv) != 0) return 1; /* Usage error */ /* Set up the value that you want to pass to the server */ printf("Setting up value to pass to server...\n"); valrequest.bv_val = "My Value"; valrequest.bv_len = strlen("My Value"); /* Get a handle to an LDAP connection */ printf("Getting the handle to the LDAP connection...\n"); if ((ld = ldap_init(host, port)) == NULL) { perror("ldap_init"); ldap_unbind(ld); return 1; } /* Set the LDAP protocol version supported by the client to 3. (By default, this is set to 2. Extended operations are part of version 3 of the LDAP protocol.) */ printf("Resetting version %d to 3.0...\n", version); version = LDAP_VERSION3; ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); /* Authenticate to the directory as the Directory Manager */ printf("Binding to the directory...\n"); if (ldap_simple_bind_s(ld, bind_DN, bind_pwd) != LDAP_SUCCESS) { ldap_perror(ld, "ldap_simple_bind_s"); ldap_unbind(ld); return 1; } /* Initiate the extended operation */ printf( "Initiating the extended operation...\n" ); if (ldap_extended_operation_s( ld, oidrequest, &valrequest, NULL, NULL, &oidresult, &valresult ) != LDAP_SUCCESS) { ldap_perror(ld, "ldap_extended_operation_s failed: "); ldap_unbind(ld); return 1; } /* Get OID and value from result returned by server. */ printf("Operation successful.\n"); printf("\tReturned OID: %s\n", oidresult); printf("\tReturned value: %s\n", valresult->bv_val); /* Disconnect from the server. */ ldap_unbind(ld); return 0; }
この例では、クライアントはOIDからのリクエストを識別しています。また、クライアントは、プロトコルでの拡張操作のサポートを確実にするために、プロトコル・バージョンをLDAP_VERSION3
にリセットすることにも注意してください。クライアントがリクエストとともに送信する値valrequest
は、berval
構造体を指します。また、バインドと拡張操作に使用されるコールは同期であることにも注意してください。非同期のバージョンも使用できます。
サーバーでプラグインをアクティブ化した後、クライアント・コードreqextop.c
をコンパイルします。
構成のcn=features
の下にエントリを追加し、ユーザーが拡張操作にアクセスするようにします。
$ cat myextop.ldif dn: oid=1.2.3.4,cn=features,cn=config objectClass: top objectClass: directoryServerFeature oid: 1.2.3.4 cn: Fake extended operation aci: (targetattr != "aci")(version 3.0;acl "Fake extended operation"; allow ( read, search, compare, proxy ) userdn = "ldap:///all";) $ ldapmodify -h localhost -p 389 -a -D cn=directory\ manager -w - -f myextop.ldif Enter bind password: adding new entry uid=qcubbins,ou=People,dc=example,dc=com $ dsadm restart /local/ds Waiting for server to stop... Server stopped Server started: pid=5658 $
クライアントを実行して拡張操作リクエストを送信し、結果を表示します。
$ ./reqextop -w password Using the following connection info: host: localhost port: 389 bind DN: cn=Directory Manager pwd: password Setting up value to pass to server... Getting the handle to the LDAP connection... Resetting version 2 to 3.0... Binding to the directory... Initiating the extended operation... Operation successful. Returned OID: 5.6.7.8 Returned value: Value from client: My Value
Directory Server側で、ロギングを有効にします。
errors
ログの次の内容に似たメッセージに、プラグインがクライアント・リクエストを処理したことが表示されます。
[22/May/2112:08:54:15 +0200] - INFORMATION - test_extendedop in test-extendedop plug-in - conn=0 op=1 msgId=2 - Request with OID: 1.2.3.4 Value from client: My Value [22/May/2112:08:54:15 +0200] - INFORMATION - test_extendedop in test-extendedop plug-in - conn=0 op=1 msgId=2 - OID sent to client: 5.6.7.8 Value sent to client: Value from client: My Value
これで、サンプルの拡張操作プラグインがOID 1.2.3.4
を持つ拡張操作に対するリクエストを処理することが説明されました。