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

簡易認証セキュリティー層 (SASL) の紹介

SASL は、アプリケーションと共有ライブラリの開発者に対し、認証、データ整合性検査、および暗号化を行うための機構を提供します。SASL を使用すると、開発者は汎用的な API に基づいたコーディングを行えます。これにより、特定の機構への依存を回避できます。SASL は特に、プロトコル IMAP、SMTP、ACAP、および LDAP を使用するアプリケーションに適しています。というのも、これらのプロトコルはすべて SASL をサポートしているからです。SASLは RFC 2222 に記述されています。

SASL ライブラリの基本

SASL ライブラリは libsasl と呼ばれます。libsasl は、正しく記述された SASL コンシューマアプリケーションがシステム上で利用可能な任意の SASL プラグインを使用できるようにするためのフレームワークです。「プラグイン」という用語は、SASL にサービスを提供するオブジェクトを指すために使用されます。プラグインは libsasl の外部に存在します。SASL プラグインを使用すれば、認証およびセキュリティー保護、名前の標準化、および補助プロパティー (パスワードなど) の検索を行えます。暗号化アルゴリズムは libsasl 内にではなくプラグイン内に格納されます。

libsasl は、コンシューマ (アプリケーションとライブラリ) に対してアプリケーションプログラミングインタフェース (API) を提供します。サービスプロバイダインタフェース (SPI) は、プラグインが libsasl にサービスを提供するために用意されたものです。libsasl はネットワークやプロトコルを認識しません。したがって、クライアントとサーバー間でデータの送受信を行うのは、アプリケーションの責任です。

SASL はユーザーに対して 2 つの重要な識別子を使用します。「認証 ID」(authid) は、ユーザーを認証するためのユーザー ID です。認証 ID は、システムへのアクセスをユーザーに許可します。「承認 ID」 (userid) は、ユーザーが特定のオプションの使用を許可されているかどうかを検査する際に使用されます。

SASL クライアントアプリケーションと SASL サーバーアプリケーションは、共通の SASL 機構とセキュリティーレベルの折衝を行います。 通常の場合、SASL サーバーアプリケーションが、自身が受け入れ可能な認証機構のリストをクライアントに送信します。その後、SASL クライアントアプリケーションは、自身の要求にもっとも合う認証機構を決定できます。この時点から、両者で合意した認証機構に基づいて、「クライアントとサーバー間における一連の SASL 認証データの交換」として認証が実行されます。この交換は、認証に成功または失敗するか、あるいはクライアントかサーバーによって処理が中止されるまで継続されます。

認証処理中に、SASL 認証機構はセキュリティー層の折衝を行えます。セキュリティー層が選択された場合、SASL セッションが継続する限りその層を使用する必要があります。

SASL アーキテクチャー

次の図に、SASL の基本アーキテクチャーを示します。

図 7–1 SASL アーキテクチャー

クライアントとサーバーの関係において SASL の主要構成要素が協調動作する様子を示しています。

クライアントアプリケーションとサーバーアプリケーションはそれぞれ、libsasl のローカルコピーに対して SASL API 経由で呼び出しを行います。libsasl は、SASL サービスプロバイダインタフェース (SPI) 経由で SASL 機構と通信します。

セキュリティー機構

セキュリティー機構プラグインは、libsasl にセキュリティーサービスを提供します。セキュリティー機構が提供する一般的な機能のいくつかを、次に示します。

SASL セキュリティー強度係数 (SSF)

「SSF」(セキュリティー強度係数) は、SASL 保護の強さを示します。機構がセキュリティー層をサポートしている場合、クライアントとサーバーは SSF の折衝を行います。SSF の値は、SASL 折衝開始前に指定されたセキュリティープロパティーに基づいて決められます。折衝で 0 以外の SSF が決定された場合、認証完了時にクライアントとサーバーの両方でその機構のセキュリティー層を使用する必要があります。SSF は次のような整数値で表現されます。

機密性と整合性の処理はセキュリティー機構によって実行されます。libsasl はそれらの要求を調整する役割を果たします。


注 –

SASL クライアントは折衝時に、最大の SSF を持つ機構を選択します。ただし、実際に選択された SASL 機構はその後、それよりも低い SSF の折衝を行う可能性があります。


SASL における通信

アプリケーションは libsasl API 経由で libsasl と通信します。libsasl はアプリケーションによって登録されたコールバックを介して追加情報の要求を行えます。アプリケーションがプラグインを直接呼び出すことはなく、必ず libsasl 経由でプラグインを呼び出します。プラグインは通常、libsasl フレームワークのプラグインを呼び出します。すると、フレームワークがアプリケーションのコールバックを呼び出します。SASL プラグインはアプリケーションを直接呼び出すことも可能です。ただしその際、アプリケーションは、プラグインからの呼び出しと libsasl からの呼び出しを区別できません。

コールバックは、次のようにさまざまな分野で役に立ちます。

アプリケーションが登録するコールバックには、 大域とセッションの 2 種類があります。さらに、libsasl では多数のコールバック ID が定義されており、それらの ID を使ってさまざまな種類のコールバックを登録できるようになっています。特定の種類のコールバックが登録されていない場合、libsasl はデフォルトの動作を実行します。

セッションコールバックは大域コールバックよりも優先されます。ある ID に対してセッションコールバックが指定された場合、そのセッションでは大域コールバックは呼び出されません。コールバックによっては、大域でなければなりません。これは、それらのコールバックがセッションの外側で呼び出されるためです。次のような処理は大域コールバックにする必要があります。

特定の SASL コールバック ID の SASL コールバックとして、NULL コールバック関数を登録できます。NULL コールバック関数は、必要なデータを提供する準備がクライアント側に整っていることを示します。SASL コールバック ID には必ず、接頭辞 SASL_CB_ が付いています。

SASL が提供する次のコールバックは、クライアントまたはサーバーで使用できます。

SASL_CB_GETOPT

SASL オプションを取得します。オプションを設定すると、libsasl(3LIB) とその関連プラグインの動作が変更されます。クライアントまたはサーバーで使用できます。

SASL_CB_LOG

libsasl とそのプラグインに対するロギング機能を設定します。デフォルトの動作は「syslog の使用」です。

SASL_CB_GETPATH

SASL プラグイン検索パスのコロン区切りリストを取得します。デフォルトのパスは次のとおりです。

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

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

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

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

SASL_CB_GETCONF

SASL サーバーの構成ディレクトリへのパスを取得します。デフォルトは /etc/sasl です。

SASL_CB_LANGUAGE

優先順に並んだ RFC 1766 言語コードのコンマ区切りリストを指定します。このリストは、クライアントおよびサーバーのエラーメッセージとクライアントのプロンプトで使用されます。デフォルトは i-default です。

SASL_CB_VERIFYFILE

構成ファイルとプラグインファイルを検証します。

SASL が提供する次のコールバックは、クライアント専用です。

SASL_CB_USER

クライアントのユーザー名を取得します。このユーザー名は承認 ID と同一です。LOGNAME 環境変数がデフォルトになります。

SASL_CB_AUTHNAME

クライアントの認証名を取得します。

SASL_CB_PASS

クライアントのパスフレーズベースのパスワードを取得します。

SASL_CB_ECHOPROMPT

指定されたチャレンジプロンプトの結果を取得します。クライアントからの入力をエコーできます。

SASL_CB_NOECHOPROMPT

指定されたチャレンジプロンプトの結果を取得します。クライアントからの入力をエコーするべきではありません。

SASL_CB_GETREALM

認証に使用するレルムを設定します。

SASL が提供する次のコールバックは、サーバー専用です。

SASL_CB_PROXY_POLICY

認証されたユーザーが指定されたユーザーの代理役として承認されているかどうかを検査します。このコールバックが登録されていない場合、認証されたユーザーと承認されるべきユーザーが同一でなければなりません。これらの ID が同一でない場合、認証が失敗します。標準でない承認ポリシーを処理するには、サーバーアプリケーションを使用してください。

SASL_CB_SERVER_USERDB_CHECKPASS

呼び出し元から提供されたユーザーデータベースに対して平文パスワードを検証します。

SASL_CB_SERVER_USERDB_SETPASS

ユーザーデータベース内に平文パスワードを格納します。

SASL_CB_CANON_USER

アプリケーションから提供されたユーザー標準化関数を呼び出します。

最初の SASL ライブラリ初期化時に、サーバーとクライアントは必要な大域コールバックのすべてを宣言します。大域コールバックが利用可能なのは、SASL セッション初期化前と SASL セッション中です。セッション初期化前には、プラグインの読み込み、データのロギング、構成ファイルの読み取りなどの作業がコールバックによって実行されます。SASL セッションの開始時に、追加のコールバックを宣言できます。そうしたコールバックは、必要に応じて大域コールバックを上書きできます。

SASL 接続コンテキスト

libsasl は、SASL 接続の「コンテキスト」内に、SASL クライアントと SASL サーバーの両方に対する各 SASL セッションの状態を格納します。各コンテキストは、同時に 1 つの認証および 1 つのセキュリティーセッションでしか使用できません。格納される状態としては、次のような情報があります。

SASL サイクル内のステップ

次の図に、SASL ライフサイクル内に含まれる各種ステップを示します。クライアントの動作は図の左側に、サーバーの動作は右側に、それぞれ示してあります。その間に描かれた矢印は、外部接続経由でのクライアントとサーバー間の相互作用を示しています。

図 7–2 SASL ライフサイクル

クライアントとサーバーの両方における SASL ライフサイクルの各フェーズを示しています。

次からの節で、このライフサイクル内のステップについて説明します。

libsasl の初期化

クライアントは sasl_client_init() を呼び出すことで libsasl をクライアント用に初期化します。サーバーは、sasl_server_init() を呼び出すことで libsasl をサーバー用に初期化します。

sasl_client_init() の実行時には、SASL クライアントプラグイン、クライアントの機構プラグイン、およびクライアントの標準化プラグインが読み込まれます。同様に、sasl_server_init() の呼び出し時には、SASL サーバープラグイン、サーバーの機構プラグイン、サーバーの標準化プラグイン、およびサーバーの auxprop プラグインが読み込まれます。sasl_client_init() の呼び出し後、追加のクライアントプラグインは、sasl_client_add_plugin()sasl_canonuser_add_plugin() を使用して追加できます。サーバー側では、sasl_server_init() の呼び出し後、追加のサーバープラグインは、sasl_server_add_plugin()sasl_canonuser_add_plugin()、および sasl_auxprop_add_plugin() を使用して追加できます。SASL 機構は Solaris ソフトウェアの次のディレクトリに格納されます。

ただし、SASL_CB_GETPATH コールバックを使えば、このデフォルトの場所を変更できます。

この時点で、必要な大域コールバックのすべてが設定されています。SASL クライアントと SASL サーバーには、次のコールバックを含めることができます。

さらに SASL サーバーには、SASL_CB_GETCONF コールバックも含めることができます。

SASL セッションの初期化

サーバーとクライアントはプロトコル経由で接続を確立します。SASL による認証を行う場合、サーバーとクライアントは SASL 接続コンテキストを作成します。それには、sasl_server_new()sasl_client_new() をそれぞれ使用します。SASL クライアントと SASL サーバーは、sasl_setprop() を使って機構に対するセキュリティー制約プロパティーを設定できます。これにより、SASL コンシューマアプリケーションは、指定された SASL 接続コンテキストの最小 SSF、最大 SSF、およびセキュリティープロパティーを決定できます。

#define SASL_SEC_NOPLAINTEXT            0x0001
#define SASL_SEC_NOACTIVE               0x0002
#define SASL_SEC_NODICTIONARY           0x0004
#define SASL_SEC_FORWARD_SECRECY        0x0008
#define SASL_SEC_NOANONYMOUS            0x0010
#define SASL_SEC_PASS_CREDENTIALS       0x0020
#define SASL_SEC_MUTUAL_AUTH            0x0040

注 –

認証とセキュリティー層は、クライアント/サーバー間のプロトコルや libsasl 以外の機構を使って提供してもかまいません。そうした場合、sasl_setprop() 経由で外部認証 ID や外部 SSF を設定できます。たとえば、プロトコルが SSL を使用してサーバーに対するクライアント認証を行う場合を考えます。この場合、外部認証 ID をクライアントの被認証者名として、外部 SSF を鍵のサイズとして、それぞれ使用できます。


サーバー側では、libsasl が、セキュリティープロパティーと外部 SSF に従って利用可能な SASL 機構を決定します。クライアントは、その利用可能な SASL 機構を SASL サーバーからプロトコル経由で取得します。

SASL サーバー側で SASL 接続コンテキストを作成するには、sasl_server_new() を呼び出す必要があります。すでに使われていない既存の SASL 接続コンテキストを再利用することも可能です。ただし、その場合は次のパラメータをリセットする必要があります。

#define SASL_DEFUSERREALM 3     /* default realm passed to server_new or set with setprop */
#define SASL_IPLOCALPORT 8      /* iplocalport string passed to server_new */
#define SASL_IPREMOTEPORT 9     /* ipremoteport string passed to server_new */
#define SASL_SERVICE    12      /* service passed to sasl_*_new */
#define SASL_SERVERFQDN 13      /* serverFQDN passed to sasl_*_new */

sasl_client_new()sasl_server_new() に対するパラメータは、コールバックとプロトコルフラグ以外はすべて変更可能です。

また、サーバーとクライアントは、セキュリティーポリシーの確立や接続固有パラメータの設定も行えます。それには、sasl_setprop() を使って次のプロパティーを指定します。

#define SASL_SSF_EXTERNAL 100 /* external SSF active (sasl_ssf_t *) */
#define SASL_SEC_PROPS 101 /* sasl_security_properties_t */
#define SASL_AUTH_EXTERNAL 102 /* external authentication ID (const char *)
 */

サーバーは、sasl_listmech() を呼び出すことで、セキュリティーポリシーを満たす利用可能な SASL 機構のリストを取得できます。クライアントは通常、利用可能な機構リストをプロトコルに依存した方法でサーバーから取得できます。

SASL セッションの初期化を図示したのが、次の図です。この図と後続の図では、プロトコル経由でデータを転送した後の検査処理は、図を単純化する目的で省略しています。

図 7–3 SASL セッションの初期化

SASL セッションの初期化中にクライアントとサーバーが実行するステップを示しています。

SASL 認証

認証時にクライアントとサーバーで実行されるステップの数は、使用されるセキュリティー機構ごとに異なります。SASL クライアントは、使用すべきセキュリティー機構のリストを指定して sasl_client_start() を呼び出します。このリストは通常、サーバーから送られてきます。libsasl は、利用可能な機構とクライアントのセキュリティーポリシーに基づいて、この SASL セッションに最適な機構を選択します。クライアントのセキュリティーポリシーは、許可される機構を制御します。そして、選択された機構が sasl_client_start() から返されます。クライアントのセキュリティー機構は、認証時に追加情報を必要とする場合があります。登録されたコールバック関数が NULL でない限り、libsasl はその指定されたコールバックを呼び出します。コールバック関数が NULL である場合、libsasl は、SASL_INTERACT と必要情報の要求を返します。SASL_INTERACT が返された場合、要求された情報を指定して sasl_client_start() を呼び出す必要があります。

sasl_client_start() から SASL_CONTINUE または SASL_OK が返された場合、クライアントは、選択された機構と結果の認証データを、サーバーに送信する必要があります。その他の値が返された場合、何らかのエラーが発生しています。たとえば、利用可能な機構が存在しない、などです。

サーバーは、クライアントによって選択された機構と、認証データを受信します。続いてサーバーは、sasl_server_start() を使ってこのセッション用に機構データを初期化します。また、sasl_server_start() は認証データの処理も行います。sasl_server_start() から SASL_CONTINUE または SASL_OK が返された場合、サーバーは認証データを送信します。sasl_server_start() からその他の値が返された場合、機構の受け入れに失敗した、認証に失敗した、など、何らかのエラーが発生しています。その認証は中止する必要があります。その SASL コンテキストは、解放するか、または再利用する必要があります。

認証プロセスのうち、以上の部分を図示したのが、次の図です。

図 7–4 SASL 認証: クライアントデータの送信

クライアントが認証データをサーバーに送信する際の、クライアントとサーバーが実行するステップを示しています。

サーバー側の sasl_server_start() 呼び出しから SASL_CONTINUE が返された場合、サーバーは必要な認証情報をすべて取得するために、クライアントとの通信を継続します。後続のステップ数は機構ごとに異なります。必要に応じて、クライアントは sasl_client_step() を呼び出すことで、サーバーからの認証データを処理し、応答を生成します。同様に、サーバーは sasl_server_step() を呼び出すことで、クライアントからの認証データを処理し、応答を生成できます。この交換は、認証が完了するか、エラーが発生するまで継続されます。SASL_OK が返された場合、それはクライアント側またはサーバー側での認証が正常に完了したことを意味します。他方の認証を完了させるために他方に送信すべき追加データが、SASL 機構内にまだ残っている可能性があります。サーバー側とクライアント側の両方で認証が完了すると、サーバーとクライアントは、互いのプロパティーを照会できるようになります。

次の図は、追加認証データを転送する際の、サーバーとクライアント間における相互作用を示したものです。

図 7–5 SASL 認証: サーバーデータの処理

サーバーがクライアントにデータを返す際に、クライアントとサーバーが実行するステップを示しています。

SASL の機密性と整合性

セキュリティー層の有無を検査するには、sasl_getprop(3SASL) 関数を使ってセキュリティー強度係数 (SSF) の値が 0 よりも大きいかどうかを確認します。セキュリティー層の折衝が行われていた場合、クライアントとサーバーは認証成功後に結果の SSF を使用する必要があります。クライアントとサーバー間のデータ交換は、認証の場合と似た方法で行われます。プロトコルによってクライアントまたはサーバーにデータが送信される前に、データに sasl_encode() が適用されます。受信側では、最後に、sasl_decode() によってデータが復号化されます。セキュリティー層の折衝がなされていなかった場合、その SASL 接続コンテキストは必要ありません。したがって、このコンテキストは破棄または再利用してかまいません。

SASL セッションの解放

SASL 接続コンテキストを解放する必要があるのは、そのセッションを再利用しない場合だけです。sasl_dispose() は、SASL 接続コンテキストと関連するすべてのリソースおよび機構を解放します。sasl_done() を呼び出す場合、その前に SASL 接続コンテキストを破棄しておく必要があります。SASL 接続に対するコンテキストリソースを解放することは、sasl_done() の責任ではありません。libsasl のクリーンアップ」を参照してください。

SASL セッションが解放される際、すべての状態が解放される可能性がある旨が、関連する機構に通知されます。SASL セッションを解放する必要があるのは、そのセッションを再利用しない場合だけです。それ以外の場合、別のセッションがその SASL 状態を再利用できます。クライアントとサーバーのどちらも、sasl_dispose() を使って SASL 接続コンテキストを解放します。

libsasl のクリーンアップ

このステップでは、SASL ライブラリとプラグインのすべてのリソースを解放します。クライアントとサーバーは sasl_done() を呼び出すことで、libsasl() のリソースを解放し、すべての SASL プラグインを読み込み解除します。sasl_done() は SASL 接続コンテキストを解放しません。アプリケーションが SASL クライアントでもあり、かつ SASL サーバーでもある場合、sasl_done() によって SASL クライアントと SASL サーバー双方のリソースが解放される点に注意してください。クライアント、サーバーのいずれかのリソースのみを解放することはできません。


注意 – 注意 –

ライブラリ内で sasl_done() を呼び出すべきではありません。アプリケーション内で sasl_done() を呼び出す際には、libsasl を使用している可能性のあるすべてのライブラリとの干渉を回避できるように、細心の注意を払う必要があります。