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 ヘッダーファイル内に含まれています。構造体については、次のセクションで説明します。
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 に伝えられる情報は、認証のステータス、authid、authzid、maxbuf、折衝済みの 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() をエクスポートする必要があります。libsasl は sasl_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() をエクスポートする必要があります。libsasl は sasl_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 プラグインは、authid と authzid の両方に対する補助プロパティーを検索するためのサポートを、SASL サーバー側で提供します。たとえば、アプリケーションによっては、内部認証用としてユーザーパスワードを検索したい場合があります。sasl_auxprop_plug_init() 関数は、auxprop プラグインを初期化するために使用され、sasl_auxpropr_plug_t 構造体を返します。
auxprop プラグインを正しく実装するには、sasl_auxprop_plug_t 構造体の auxprop_lookup メンバーを実装する必要があります。auxprop_lookup() 関数はユーザー名の標準化後に、標準化されたユーザー名を指定して呼び出されます。続いてプラグインは、要求された補助プロパティーの取得に必要な任意の検索を実行できます。