ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
![]() |
Oracle Solaris 11 セキュリティーサービス開発ガイド Oracle Solaris 11 Information Library (日本語) |
1. Oracle Solaris の開発者向けセキュリティー機能 (概要)
3. PAM アプリケーションおよび PAM サービスの記述
8. Oracle Solaris 暗号化フレームワークの紹介
9. ユーザーレベルの暗号化アプリケーションとプロバイダの記述
ここでは、SASL アプリケーションに対して機構やその他のサービスを提供するプラグインの作成方法について説明します。
注 - エクスポート規則のため、Oracle Solaris SASL SPI は、Oracle Solaris 以外のクライアントおよびサーバー機構プラグイン用のセキュリティーレイヤーをサポートしません。 このため、Oracle Solaris 以外のクライアントおよびサーバー機構プラグインは、整合性サービスまたは機密性サービスを提供できません。 Oracle Solaris のクライアントおよびサーバー機構プラグインには、この制限はありません。
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() 関数はユーザー名の標準化後に、標準化されたユーザー名を指定して呼び出されます。 続いてプラグインは、要求された補助プロパティーの取得に必要な任意の検索を実行できます。
注 - Oracle Corporation は現在 auxprop プラグインを提供していません。
ここでは、SASL プラグイン開発に関して、いくつかの追加の指針を提供します。
適切なエラーレポートは、認証エラーの原因究明時やその他のデバッグ時に役立ちます。 プラグイン開発者には、sasl_utils_t 構造体の sasl_seterror() コールバック経由で特定の接続に関する詳細なエラー情報を提供することを強くお勧めします。
SASL におけるメモリー割り当ての一般規則は、「開発者自身が割り当てたメモリーは、それらが不要になった時点で漏れなく解放する」というものです。 この規則に従えば、パフォーマンスと移植性が改善されるほか、メモリーリークも防止できます。
プラグイン機構は、クライアントとサーバー間で交わされる SASL 会話の順序を、次のフラグに基づいて設定することができます。
SASL_FEAT_WANT_CLIENT_FIRST – クライアント側が交換を開始します。
SASL_FEAT_WANT_SERVER_LAST – サーバーが最後のデータをクライアントに送信します。
どちらのフラグも設定されていない場合、機構プラグインは内部的に順序を設定します。 その場合、機構は、送信すべきデータの有無を、クライアントとサーバーの両方で検査する必要があります。 なお、「クライアントが最初に送信する」を選択できるのは、プロトコルが初期応答を許可する場合だけです。
「サーバーが最後に送信する」を選択した場合、ステップ関数が SASL_OK を返す際にプラグインが *serverout を設定する必要があります。 「サーバーが最後に送信する」を決して使用しない機構は、*serverout に NULL を設定する必要があります。 「サーバーが最後に送信する」を常に使用する機構は、*serverout に成功データを設定する必要があります。