ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Directory Server Enterprise Edition開発者ガイド
11g リリース1 (11.1.1.7.0)
B72440-01
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

9 拡張操作プラグインの作成

この章では、LDAP v3の拡張操作を活用するためのプラグインの作成方法について説明します。拡張操作は、RFC 4511 (http://www.ietf.org/rfc/rfc4511.txt)で定義されています。RFCには、「デジタル署名操作や結果など、このプロトコルの他の場所で使用できないサービス向けに定義されるその他の操作」と定義されています。

この章の内容は、次のとおりです。

9.1 拡張操作プラグインのコール

この項では、拡張操作がDirectory Serverによって処理される仕組みについて説明します。また、拡張操作プラグインに設定される要件も説明します。

Directory Serverは、オブジェクト識別子(OID)によって拡張操作を識別します。クライアントは、次の項目を指定し、拡張操作リクエストを送信して操作を要求します。

9.2 拡張操作プラグインの実装

この項では、拡張操作をトリガーするために、基本の拡張操作プラグインとクライアント・アプリケーションを実装する方法を示します。

クライアントは、拡張操作を識別するOID (今回は1.2.3.4)を使用して、サーバーに拡張操作リクエストを送信します。また、文字列を保持する値も送信します。サンプル・プラグインでは、クライアントにOIDを送信することによって拡張操作リクエストに応答しています。また、プラグインは、クライアントがリクエストとともに送信した文字列の変更されたバージョンも送信します。

9.2.1 拡張操作の検索例

この章の残りについては、install-path/examples/testextendedop.cのプラグイン・コードと、install-path/examples/clients/reqextop.cのクライアント・コードを参照してください。

9.2.2 拡張操作プラグインの例

この項では、拡張操作プラグインの動作の仕組みについて説明します。

9.2.2.1 拡張操作プラグインの登録

ここでの説明に従ってプラグイン関数を使用する前に、プラグインを構築します。また、プラグインをロードするようにDirectory Serverも構成します。

OID 1.2.3.4は、構成エントリを介して引数として渡されることに注意してください。たとえば、個別のOIDによってそれぞれが識別されている複数の拡張操作をプラグインがサポートしている場合、構成エントリは2つ以上のnsslapd-pluginarg属性を指定できます。

9.2.2.1.1 プラグインを登録するには

実行済でない場合には、サンプルのプラグイン・ライブラリを作成し、プラグイン情報のロギングとサンプル・プラグインの両方をアクティブ化します。

  1. プラグインを構築します。

    ヒント: install-path/examples/Makefileまたはinstall-path/examples/Makefile64を使用します。

  2. プラグイン情報メッセージがログに記録されるように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"
    

    ヒント: 詳細は、プラグインのソース・ファイルに指定されたコマンドを使用して参照してください。

  3. Directory Serverを再起動します。

    $ dsadm restart instance-path
    

9.2.2.2 拡張操作プラグインの初期化

他のプラグイン・タイプに関しては、拡張操作プラグインに、プラグインの他の関数を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リファレンス」を参照してください。

9.2.2.3 拡張操作の処理

プラグイン関数test_extendedop()は、クライアント・リクエストから操作のOIDと値を取得します。その後、関数は、「拡張操作クライアントの開発」に示されているように、クライアントにレスポンスを送信します。

関数がSLAPI_EXT_OP_REQ_OIDSLAPI_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結果コードをクライアントに送信します。

9.2.3 拡張操作クライアントの開発

プラグインをテストするには、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構造体を指します。また、バインドと拡張操作に使用されるコールは同期であることにも注意してください。非同期のバージョンも使用できます。

9.2.4 拡張操作の試行例

  1. サーバーでプラグインをアクティブ化した後、クライアント・コードreqextop.cをコンパイルします。

  2. 構成の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
    $ 
    
  3. クライアントを実行して拡張操作リクエストを送信し、結果を表示します。

    $ ./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
    
  4. 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を持つ拡張操作に対するリクエストを処理することが説明されました。