Go to main content
Oracle® Solaris 11 セキュリティー開発者ガイド

印刷ビューの終了

更新: 2016 年 11 月
 
 

サービスプロバイダ用の SASL

このセクションでは、SASL アプリケーションに対してメカニズムやその他のサービスを提供するプラグインの作成方法について説明します。


注 - エクスポート規則のため、Oracle Solaris SASL SPI は、Oracle Solaris 以外のクライアントおよびサーバーメカニズムプラグイン用のセキュリティーレイヤーをサポートしません。このため、Oracle Solaris 以外のクライアントおよびサーバーメカニズムプラグインは、整合性サービスまたは機密性サービスを提供できません。Oracle Solaris のクライアントおよびサーバーメカニズムプラグインには、この制限がありません。

SASL プラグインの概要

SASL サービスプロバイダインタフェース (SPI) を使うと、プラグインと libsasl ライブラリ間の通信が可能となります。SASL プラグインは通常、共有ライブラリとして実装されます。1 つの共有ライブラリには、各種の SASL プラグインを 1 つ以上格納できます。共有ライブラリ内のプラグインは、libsasl によって dlopen(3C) 関数で動的にオープンされます。

また、プラグインは、libsasl を呼び出す特定のアプリケーションに静的にバインドすることも可能です。こうした種類のプラグインをロードするには、sasl_client_add_plugin() 関数または sasl_server_add_plugin() 関数を使用しますが、どちらを使用するかは、そのアプリケーションがクライアント、サーバーのいずれであるかにより異なります。

    Oracle Solaris オペレーティングシステム内の SASL プラグインは、次の要件を満たす必要があります。

  • 共有ライブラリ内のプラグインは、有効な実行可能オブジェクトファイル (推奨のファイル拡張子は .so) 内に格納されている必要があります。

  • プラグインは検証可能な場所に収められている必要があります。プラグインの検証には SASL_CB_VERIFYFILE コールバックが使用されます。

  • プラグインは適切なエントリポイントを含んでいる必要があります。

  • SASL クライアントのプラグインのバージョンが、SASL サーバーの対応するプラグインのバージョンに一致している必要があります。

  • プラグインは正常に初期化できる必要があります。

  • プラグインのバイナリタイプが、libsasl のバイナリタイプに一致している必要があります。

    SASL プラグインは次の 4 つのカテゴリに分類されます。

  • クライアントメカニズムプラグイン

  • サーバーメカニズムプラグイン

  • 標準化プラグイン

  • auxprop プラグイン

sasl_client_init() 関数を呼び出すと、利用可能なすべてのクライアントプラグインが SASL クライアントにロードされます。 sasl_server_init() 関数を呼び出すと、サーバープラグイン、標準化プラグイン、および auxprop プラグインが SASL サーバーに読み込まれます。sasl_done() を呼び出すと、すべてのプラグインが読み込み解除されます。

libsasl はプラグイン検索時に、SASL_CB_GETPATH コールバック関数、デフォルトパスのいずれかを使用します。SASL_CB_GETPATH は、プラグイン検索ディレクトリのコロン区切りリストを返します。SASL コンシューマが SASL_CB_GETPATH コールバックを指定した場合、libsasl はそのコールバックから返されたパスを使って検索を行います。それ以外の場合、SASL コンシューマはバイナリタイプに対応するデフォルトパスを使用できます。

    次に、デフォルトパスとバイナリタイプの対応を示します。

  • 64 ビット SPARC アーキテクチャー: /usr/lib/sasl/sparcv9

  • x64 アーキテクチャー: /usr/lib/sasl/amd64

  • 32 ビット SPARC アーキテクチャー: /usr/lib/sasl

  • 32 ビット x86 アーキテクチャー: /usr/lib/sasl

libsasl は読み込みプロセスの一部として、サポートされている最新バージョンのプラグインを呼び出します。そのプラグインは、バージョンと自身を記述した構造体を返します。バージョンが一致した場合、libsasl はそのプラグインをロードします。現在のバージョン番号は SASL_UTILS_VERSION です。

特定のプラグインの初期化が完了すると、そのプラグインと libsasl との間のそれ以降の通信に必要となる構造体を確立する必要があります。プラグインは sasl_utils_t 構造体を使用して libsasl を呼び出します。

    libsasl ライブラリは次の構造体のエントリポイントを使用してプラグインと通信します。

  • sasl_out_params_t

  • sasl_client_params_t

  • sasl_server_params_t

  • sasl_client_plug_t

  • sasl_server_plug_t

  • sasl_canonuser_plug_t

  • sasl_auxprop_plug_t

これらの構造体のソースコードは、SASL ヘッダーファイル内に含まれています。構造体については、次のセクションで説明します。

SASL プラグインに関する重要な構造体

    libsasl とプラグインの通信は、次の構造体によって実現されます。

  • sasl_utils_t – sasl_utils_t 構造体には、さまざまなユーティリティー関数と 3 つのコンテキスト情報が含まれています。

    この構造体に含まれている各種ユーティリティー関数は、プラグイン開発者向けの簡易関数として機能します。それらの関数の多くは、libsasl の公開インタフェースへのポインタになっています。プラグインは、何らかの理由で SASL コンシューマになる必要がある場合を除き、libsasl を直接呼び出す必要はありません。

      libsasl は sasl_utils_t 用に 3 つのコンテキストを作成します。

    • sasl_conn_t *conn

    • sasl_rand_t *rpool

    • void *getopt_context

    sasl_utils_t 内の conn 変数は、たとえばプラグインの読み込み時のように、実際には特定の接続に関連付けられていない場合があります。それ以外の場合、conn は SASL コンシューマの SASL 接続コンテキストです。rpool 変数は乱数生成関数用です。getopt_context は、getopt() 関数で使用すべきコンテキストです。

    sasl_getopt_t(3SASL)sasl_log_t(3SASL)、および sasl_getcallback_t(3SASL) を参照してください。

  • sasl_out_params_t – libsasl は、sasl_out_params_t 構造体を作成し、それをクライアントまたはサーバーの mech_step() に渡します。この構造体を通じて libsasl に伝えられる情報は、認証のステータス、authidauthzidmaxbuf、折衝済みの ssf、およびデータのエンコード/デコードに関する情報です。

  • sasl_client_params_t – sasl_client_params_t 構造体は、libsasl がクライアントの状態を特定の SASL クライアントメカニズムに渡すために使用されます。この状態データの送信には、クライアントメカニズムのエントリポイント mech_new()mech_step()、および mech_idle() が使用されます。また、canon_user_client() エントリポイントにもクライアント状態を渡す必要があります。

  • sasl_server_params_t – sasl_server_params_t 構造体は、サーバー側において、sasl_client_params_t に似た機能を果たします。

クライアントプラグイン

クライアントプラグインは、クライアント側の SASL 折衝を管理するために使用されます。クライアントプラグインは通常、対応するサーバープラグインとともにパッケージ化されます。1 つのクライアントプラグインには、1 つ以上のクライアント側の SASL メカニズムが含まれています。各 SASL クライアントメカニズムは、認証のサポートに加え、オプションで整合性と機密性をサポートします。

    各 SASL クライアントメカニズムは、そのメカニズムの機能に関する次の情報を提供します。

  • SSF の最大値

  • セキュリティーフラグの最大値

  • プラグイン機能

  • プラグインを使用するためのコールバックとプロンプト ID

クライアントプラグインは sasl_client_plug_init() をエクスポートする必要があります。libsaslsasl_client_plug_init() を呼び出すことで、プラグインをクライアント用に初期化します。プラグインは sasl_client_plug_t 構造体を返します。

    sasl_client_plug_t が提供する次のエントリポイントは、libsasl がメカニズムを呼び出す際に使用されます。

  • mech_new() – クライアントは接続開始時に sasl_client_start() を呼び出しますが、この関数が mech_new() を使用します。mech_new() はメカニズムに固有の初期化を実行します。必要に応じて、接続コンテキストが割り当てられます。

  • mech_step()mech_step() は、sasl_client_start()sasl_client_step() から呼び出されます。mech_new() が呼び出されたあと、mech_step() がクライアント側で認証を実行します。認証に成功した場合、mech_step() から SASL_OK が返されます。追加のデータが必要な場合、SASL_CONTINUE が返されます。認証に失敗した場合、SASL エラーコードが返されます。エラーが発生した場合、seterror() が呼び出されます。認証に成功した場合、mech_step() は、関連するセキュリティー層の情報とコールバックを含む sasl_out_params_t 構造体を返す必要があります。canon_user() 関数はこの構造体の一部です。canon_user() は、クライアントが認証 ID と承認 ID を受信した際に呼び出される必要があります。

  • mech_dispose()mech_dispose() は、コンテキストが安全にクローズできる場合に呼び出されます。mech_dispose()sasl_dispose() によって呼び出されます。

  • mech_free()mech_free()libsasl の終了時に呼び出されます。mech_free() によって、そのプラグインに対するすべての大域状態が解放されます。

サーバープラグイン

サーバープラグインは、サーバー側の SASL 折衝を管理するために使用されます。サーバープラグインは通常、対応するクライアントプラグインとともにパッケージ化されます。1 つのサーバープラグインには、1 つ以上のサーバー側の SASL メカニズムが含まれています。各 SASL サーバーメカニズムは、認証のサポートに加え、オプションで整合性と機密性をサポートします。

    各 SASL サーバーメカニズムは、そのメカニズムの機能に関する次の情報を提供します。

  • SSF の最大値

  • セキュリティーフラグの最大値

  • プラグイン機能

  • プラグインを使用するためのコールバックとプロンプト ID

サーバープラグインは sasl_server_plug_init() をエクスポートする必要があります。libsaslsasl_server_plug_init() を呼び出すことで、プラグインをサーバー用に初期化します。プラグインは sasl_server_plug_t 構造体を返します。

    sasl_server_plug_t 構造体は、libsasl がメカニズムを呼び出すための次のエントリポイントを提供します。

  • mech_new() – サーバーは接続開始時に sasl_server_start() を呼び出しますが、この関数が mech_new() を使用します。mech_new() はメカニズムに固有の初期化を実行します。mech_new() は必要に応じて接続コンテキストを割り当てます。

  • mech_step()mech_step() は、sasl_server_start()sasl_server_step() から呼び出されます。mech_new() が呼び出されたあと、mech_step() がサーバー側で認証を実行します。認証に成功した場合、mech_step() から SASL_OK が返されます。追加のデータが必要な場合、SASL_CONTINUE が返されます。認証に失敗した場合、SASL エラーコードが返されます。エラーが発生した場合、seterror() が呼び出されます。認証に成功した場合、mech_step() は、関連するセキュリティー層の情報とコールバックを含む sasl_out_params_t 構造体を返す必要があります。canon_user() 関数はこの構造体の一部です。canon_user() は、サーバーが認証 ID と承認 ID を受信した際に呼び出される必要があります。canon_user() 関数が呼び出されると、propctx が設定されます。認証の標準化前に、必要とされるすべての補助プロパティー要求が実行される必要があります。認証の標準化後に、承認 ID 検索が実行されます。

      mech_step() 関数は SASL_OK を返す前に、sasl_out_params_t 内のすべての関連フィールドを設定する必要があります。これらのフィールドは次の機能を担っています。

    • doneflag – 交換が完了したことを示します

    • maxoutbuf – セキュリティー層の最大出力サイズを示します

    • mech_ssf – セキュリティー層に対して提供された SSF

    • encode()sasl_encode()sasl_encodev()、および sasl_decode() によって呼び出されます

    • decode()sasl_encode()sasl_encodev()、および sasl_decode() によって呼び出されます

    • encode_context()sasl_encode()sasl_encodev()、および sasl_decode() によって呼び出されます

    • decode_context()sasl_encode()sasl_encodev()、および sasl_decode() によって呼び出されます

  • mech_dispose()mech_dispose() は、コンテキストが安全にクローズできる場合に呼び出されます。mech_dispose()sasl_dispose() によって呼び出されます。

  • mech_free()mech_free()libsasl の終了時に呼び出されます。mech_free() によって、そのプラグインに対するすべての大域状態が解放されます。

  • setpass() はユーザーのパスワードを設定します。setpass() を使えば、メカニズムは内部パスワードを持つことができます。

  • mech_avail()sasl_listmech() によって呼び出され、指定されたユーザーが特定のメカニズムを利用できるかどうかを検査します。mech_avail() は新しいコンテキストを作成できるため、mech_new() への呼び出しを回避できます。パフォーマンスに影響が出なければ、この方法でコンテキストを作成します。

ユーザー標準化プラグイン

標準化プラグインは、クライアント側とサーバー側の両方で、認証名と承認名に対する代替標準化サポートを提供します。標準化プラグインを読み込む際には、sasl_canonuser_plug_init() が使用されます。

    標準化プラグインは次の要件を満たす必要があります。

  • 標準化名が出力バッファーにコピーされる必要があります。

  • 同じ入力バッファーが出力バッファーとして使用できる必要があります。

  • 標準化プラグインは、認証 ID、承認 ID のどちらか一方しか存在しない場合でも、正常に機能する必要があります。

ユーザー標準化プラグインは sasl_canonuser_init() 関数をエクスポートする必要があります。sasl_canonuser_init() 関数は、sasl_canonuser_plug_t を返すことで、必要なエントリポイントを確立する必要があります。ユーザー標準化プラグインは少なくとも、sasl_canonuser_plug_t 構造体のメンバー canon_user_client() または canon_user_server() のどちらか 1 つを実装している必要があります。

補助プロパティー (auxprop) プラグイン

auxprop プラグインは、authidauthzid の両方に対する補助プロパティーを検索するためのサポートを、SASL サーバー側で提供します。たとえば、アプリケーションによっては、内部認証用としてユーザーパスワードを検索したい場合があります。sasl_auxprop_plug_init() 関数は、auxprop プラグインを初期化するために使用され、sasl_auxpropr_plug_t 構造体を返します。

auxprop プラグインを正しく実装するには、sasl_auxprop_plug_t 構造体の auxprop_lookup メンバーを実装する必要があります。auxprop_lookup() 関数はユーザー名の標準化後に、標準化されたユーザー名を指定して呼び出されます。続いてプラグインは、要求された補助プロパティーの取得に必要な任意の検索を実行できます。


注 - Oracle Corporation は現在 auxprop プラグインを提供していません。

SASL プラグイン開発のガイドライン

このセクションでは、SASL プラグイン開発に関して、いくつかの追加の指針を提供します。

SASL プラグインにおけるエラーレポート

適切なエラーレポートは、認証エラーの原因究明時やその他のデバッグ時に役立ちます。プラグイン開発者には、sasl_utils_t 構造体の sasl_seterror() コールバック経由で特定の接続に関する詳細なエラー情報を提供することを強くお勧めします。

SASL プラグインにおけるメモリー割り当て

SASL におけるメモリー割り当ての一般規則は、「開発者自身が割り当てたメモリーは、それらが不要になった時点で漏れなく解放する」というものです。この規則に従えば、パフォーマンスと移植性が改善されるほか、メモリーリークも防止できます。

SASL 折衝順序の設定

    プラグインメカニズムは、クライアントとサーバー間で交わされる SASL 会話の順序を、次のフラグに基づいて設定することができます。

  • SASL_FEAT_WANT_CLIENT_FIRST – クライアント側が交換を開始します。

  • SASL_FEAT_WANT_SERVER_LAST – サーバーが最後のデータをクライアントに送信します。

どちらのフラグも設定されていない場合、メカニズムプラグインは内部的に順序を設定します。その場合、メカニズムは、送信すべきデータの有無を、クライアントとサーバーの両方で検査する必要があります。なお、「クライアントが最初に送信する」を選択できるのは、プロトコルが初期応答を許可する場合だけです。

「サーバーが最後に送信する」を選択した場合、ステップ関数が SASL_OK を返す際にプラグインが *serverout を設定する必要があります。「サーバーが最後に送信する」を決して使用しないメカニズムは、*serverout に NULL を設定する必要があります。「サーバーが最後に送信する」を常に使用するメカニズムは、*serverout に成功データを設定する必要があります。