Oracle Solaris セキュリティーサービス開発ガイド

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

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


注 –

エクスポート規則のため、Solaris SASL サービスプロバイダインタフェース (SPI) は、Solaris 以外のクライアントおよびサーバー機構プラグイン用のセキュリティーレイヤーをサポートしません。このため、Solaris 以外のクライアントおよびサーバー機構プラグインは、整合性サービスまたは機密性サービスを提供できません。Solaris のクライアントおよびサーバー機構プラグインには、この制限はありません。


SASL プラグインの概要

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

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

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

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

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

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

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

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

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

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

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

クライアントプラグイン

クライアントプラグインは、クライアント側の SASL 折衝を管理するために使用されます。クライアントプラグインは通常、対応するサーバープラグインとともにパッケージ化されます。1 つのクライアントプラグインには、1 つ以上のクライアント側の SASL 機構が含まれています。各 SASL クライアント機構は、認証のサポートに加え、任意で整合性と機密性をサポートします。各機構が自身の機能について提供する情報は、次のとおりです。

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

サーバープラグイン

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

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

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

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

ユーザー標準化プラグインは 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() 関数はユーザー名の標準化後に、標準化されたユーザー名を指定して呼び出されます。続いてプラグインは、要求された補助プロパティーの取得に必要な任意の検索を実行できます。


注 –

Sun Microsystems, Inc. は現在、auxprop プラグインを提供していません。


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

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

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

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

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

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

SASL 折衝順序の設定

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

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

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