SASL は、Lightweight Directory Access Protocol、バージョン 3 (LDAP v3) や Internet Message Access Protocol、バージョン 4 (IMAP v4) などのプロトコルによって使用され、プラグイン可能な認証を有効にします。認証メソッドをプロトコルに固定する代わりに、LDAP v3 および IMAP v4 は SASL を使用して認証を実行します。したがって、さまざまな SASL メカニズムによる認証が可能になります。
さまざまなセキュリティーレベルおよび配備シナリオ用にインターネットコミュニティーによって定義された、多数の標準 SASL メカニズムがあります。その範囲はセキュリティーなし (匿名認証など) から高セキュリティー (Kerberos 認証など) にいたるまで、さまざまなレベルがあります。
Java SASL API では、開発者は独自のカスタム SASL メカニズムを使用することもできます。SASL メカニズムは、Java 暗号化アーキテクチャー (JCA) を使用してインストールされます。
JSSE および Java GSS と比較すると、SASL は相対的に軽量であり、最近のプロトコルの中で一般的です。一般的かつ軽量な (インフラストラクチャーサポートの点で) SASL メカニズムがいくつか定義されているという利点もあります。一方、主要な JSSE および Java GSS メカニズムは相対的に重量のあるメカニズムを持ち、より精巧なインフラストラクチャー (それぞれ公開鍵インフラストラクチャーおよび Kerberos) を必要とします。
SASL、JSSE、および Java GSS は、しばしば併用されます。たとえば、一般的なパターンでは、アプリケーションは安全なチャネルを確立するために JSSE を使用し、クライアントのユーザー名/パスワードベースの認証には SASL を使用します。GSS-API メカニズムの上位層となる SASL メカニズムもあります。一般的な例は、LDAP で使用される SASL GSS-API/Kerberos v5 メカニズムです。
プロトコルをゼロから定義および構築する場合を除き、どの API を使用するかを決定する場合の最大要因は、多くの場合プロトコル定義です。たとえば、LDAP および IMAP は SASL を使用するように定義されているので、これらのプロトコルに関係するソフトウェアは Java SASL API を使用するようにしてください。Kerberos アプリケーションおよびサービスを構築する場合、使用する API は Java GSS です。プロトコルとして SSL/TLS を使用するアプリケーションおよびサービスを構築する場合、使用する API は JSSE です。JSSE と Java GSS をいつ使用するかについての詳細は、「Java セキュリティードキュメント」を参照してください。
SASL はチャレンジ応答プロトコルです。サーバーはクライアントにチャレンジを発行し、クライアントはチャレンジに基づいて応答を送信します。この交換は、サーバーが充足してチャレンジを発行しなくなるまで続きます。これらのチャレンジおよび応答は、任意の長さのバイナリトークンです。カプセル化を行うプロトコル (LDAP や IMAP など) は、これらのトークンのエンコードおよび交換方法を指定します。たとえば、LDAP は、SASL トークンが LDAP バインド要求および応答にどのようにカプセル化されるかを指定します。Java SASL API は、この相互作用と使用方法のスタイルに従ってモデル化されています。インタフェース SaslClient および SaslServer があり、これらはそれぞれクライアント側およびサーバー側のメカニズムを表します。アプリケーションはチャレンジおよび応答を表すバイト配列によって、メカニズムと相互に作用します。サーバー側のメカニズムは、充足されるまでチャレンジの発行と応答の処理を繰り返します。一方、クライアント側のメカニズムは、サーバーが充足されるまでチャレンジの評価と応答の発行を繰り返します。メカニズムを使用しているアプリケーションが、それぞれの繰り返しを制御します。つまり、メカニズムを使用しているアプリケーションは、チャレンジまたは応答をプロトコルパケットから抽出してメカニズムに渡し、メカニズムから返された応答またはチャレンジをプロトコルパケットに入れて、ピアに送信します。
Sasl クラスが、SaslClient および SaslServer のインスタンスの作成に使用されます。次に、使用可能な SASL メカニズムのリストを使用して、アプリケーションがどのように SASL クライアントメカニズムを作成するかの例を示します。
String[] mechanisms = new String[]{"DIGEST-MD5", "PLAIN"}; SaslClient sc = Sasl.createSaslClient(mechanisms, authzid, protocol, serverName, props, callbackHandler);
プラットフォームによってサポートされるメカニズムの可用性およびパラメータで提供されるその他の構成情報に基づいて、Java SASL フレームワークは一覧されているメカニズムの 1 つを選択し、SaslClient のインスタンスを返します。
選択されたメカニズムの名前は、通常、アプリケーションプロトコルによってサーバーに転送されます。メカニズム名を受信すると、サーバーは、クライアントから送信された応答を処理するために、対応する SaslServer オブジェクトを作成します。次に、サーバーが SaslServer のインスタンスを作成する方法の例を示します。
SaslServer ss = Sasl.createSaslServer(mechanism, protocol, myName, props, callbackHandler);
Java SASL API は汎用フレームワークなので、多数の異なるタイプのメカニズムに対応できる必要があります。各メカニズムは入力によって初期化される必要があり、先に進むために入力を必要とする場合があります。この API は、アプリケーションがメカニズムに入力を渡すための 3 つの手段を提供します。
メカニズムは、javax.security.auth.callback パッケージで定義されたコールバックを使用できます。これらは、認証を実行するアプリケーションを構築するのに便利なジェネリックコールバックです。メカニズムは、レルムおよび認証情報を収集するためのコールバックなどの、SASL 固有のコールバック、および (標準化されていない) メカニズム固有のコールバックを必要とする場合もあります。アプリケーションはさまざまなメカニズムに対応できるようにしてください。したがって、そのコールバックハンドラは、メカニズムが要求する可能性があるすべてのコールバックに対応できることが必要です。このことは、任意のメカニズムに対しては一般的には不可能ですが、通常は配備および使用されているメカニズムは数が限定されているので、可能です。
// Get optional initial response byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[]) : null); String mechanism = sc.getName(); // Send selected mechanism name and optional initial response to server send(mechanism, response); // Read response msg = receive(); while (!sc.isComplete() && (msg.status == CONTINUE || msg.status == SUCCESS)) { // Evaluate server challenge response = sc.evaluateChallenge(msg.contents); if (msg.status == SUCCESS) { // done; server doesn't expect any more SASL data if (response != null) { throw new IOException( "Protocol error: attempting to send response after completion"); } break; } else { send(mechanism, response); msg = receive(); }
クライアントアプリケーションはメカニズム (sc) を使用して認証の各ステップを繰り返し、サーバーから取得したチャレンジを評価してサーバーに応答を返信します。クライアントアプリケーションはメカニズムまたはアプリケーションレベルのプロトコルが認証が完了したことを示すまで、またはメカニズムがチャレンジを評価できない場合に、このサイクルを続行します。メカニズムがチャレンジを評価できない場合、エラーを示す例外をスローし、認証を終了します。完了状態に関してメカニズムとプロトコルの間で不一致がある場合は、認証交換に障害があることを示す可能性があるため、エラーとして処理します。
次に、サーバーが SaslServer をどのように使用するかの例を示します。
// Read request that contains mechanism name and optional initial response msg.receive(); // Obtain a SaslServer to perform authentication SaslServer ss = Sasl.createSaslServer(msg.mechanism, protocol, myName, props, callbackHandler); // Perform authentication steps until done while (!ss.isComplete()) { try { // Process response byte[] challenge = sc.evaluateResponse(msg.contents); if (ss.isComplete()) { send(mechanism, challenge, SUCCESS); } else { send(mechanism, challenge, CONTINUE); msg.receive(); } } catch (SaslException e) { send(ERROR); sc.dispose(); break; } }サーバーアプリケーションはクライアントの応答をメカニズム (ss) に渡して処理することによって、認証の各ステップを繰り返します。応答が不正な場合、サーバーがエラーを報告して認証を終了できるように、メカニズムは SaslException をスローしてエラーを示します。応答が正しい場合、メカニズムはクライアントに送信されるチャレンジデータを返し、認証が完了したかどうかを示します。チャレンジデータは「成功」を示すデータを伴うことができます。これは、たとえば、ネゴシエーションされた状態をクライアントに完結させるために使用される場合があります。
セキュリティー層がネゴシエーション済みの場合、ピアとの後続の通信はすべてセキュリティー層を使用して発生します。セキュリティー層がネゴシエーション済みかどうかを判別するには、ネゴシエーション済みの保護の品質 (QOP) をメカニズムから取得します。次に、セキュリティー層がネゴシエーション済みかどうかを判別する方法の例を示します。
String qop = (String) sc.getNegotiatedProperty(Sasl.QOP); boolean hasSecurityLayer = (qop != null && (qop.equals("auth-int") || qop.equals("auth-conf")));
Sasl.QOP プロパティーが整合性または機密性、あるはその両方がネゴシエーション済みであることを示している場合、セキュリティー層はネゴシエーション済みです。
ネゴシエーション済みの層を使用してピアと通信するには、アプリケーションは最初に wrap メソッドを使用し、ピアに送信されるデータをエンコードして「ラップされた」バッファーを生成します。次に、ラップされたバッファー内のオクテットの数を表す長さフィールドとそれに続いてラップされたバッファーの内容をピアに転送します。オクテットのストリームを受信するピアは長さフィールドを除くバッファーを unwrap に渡し、ピアによって送信された復号化されたバイトを取得します。このプロトコルの詳細は RFC 2222 で説明されています。次に、クライアントアプリケーションがセキュリティー層を使用してアプリケーションデータをどのように送受信するかの例を示します。
// Send outgoing application data to peer byte[] outgoing = ...; byte[] netOut = sc.wrap(outgoing, 0, outgoing.length); send(netOut.length, netOut); // send to peer // Receive incoming application data from peer byte[] netIn = receive(); // read length and ensuing bytes from peer byte[] incoming = sc.unwrap(netIn, 0, netIn.length);SASL メカニズムの実装は、SASL セキュリティープロバイダによって提供されます。各プロバイダは 1 つ以上の SASL メカニズムをサポートでき、Java 暗号化アーキテクチャー (JCA) に登録されます。J2SE 5 では、デフォルトで SunSASL プロバイダが JCA プロバイダとして自動的に登録されます。このプロバイダを削除するか、JCA プロバイダとしての優先順位を変更するには、次の行を変更します。
security.provider.7=com.sun.security.sasl.Providerこれは、Java セキュリティープロパティーファイル ($JAVA_HOME/lib/security/java.security) にあります。
SASL プロバイダを追加または削除するには、セキュリティープロパティーファイルで対応する行を追加または削除します。たとえば、SASL プロバイダを追加し、そのメカニズムが SunSASL プロバイダによって実装されている同じメカニズムよりも優先して選択されるようにする場合は、セキュリティープロパティーファイルに小さい番号で行を追加します。
security.provider.7=com.example.MyProvider security.provider.8=com.sun.security.sasl.Provider
この場合、java.security.Security クラスを使用して、プログラムで独自のプロバイダを追加することもできます。たとえば、次のサンプルコードは、使用可能な SASL セキュリティープロバイダのリストに com.example.MyProvider を登録します。
Security.addProvider(new com.example.MyProvider());アプリケーションが 1 つ以上のメカニズム名を指定して SASL メカニズムを要求すると、SASL フレームワークは、登録済みプロバイダのリストを順に検索して、そのメカニズムをサポートする登録済みの SASL プロバイダを探します。次に、プロバイダは、要求されたメカニズムが選択ポリシープロパティーに一致するかどうかを判別し、一致する場合は、メカニズムの実装を返します。
選択ポリシープロパティーは特定の攻撃に対する影響の受けやすさなど、メカニズムのセキュリティー面を指定します。これらは、実装というよりもメカニズムの特性 (定義) です。したがって、すべてのプロバイダは特定のメカニズムについて同じ結果になるはずです。たとえば、PLAIN メカニズムは、どのように実装されるかにかかわらず、平文攻撃の影響を受けやすくなります。選択ポリシープロパティーが指定されない場合、メカニズムの選択に制限はありません。これらのプロパティーを使用して、アプリケーションは、実行環境に配備される可能性があるメカニズムについて、適していないものを使用しないようにすることができます。たとえば、平文攻撃の影響を受けやすいメカニズムの使用を許可しない場合、アプリケーションは次のサンプルコードを使用する場合があります。
Map props = new HashMap(); props.add(Sasl.POLICY_NOPLAINTEXT, "true"); SaslClient sc = Sasl.createSaslClient(mechanisms, authzid, protocol, serverName, props, callbackHandler);選択ポリシープロパティーの詳細は、Sasl クラスを参照してください。 SunSASL プロバイダは、次のクライアントメカニズムおよびサーバーメカニズムをサポートします。
クライアントメカニズム名 | パラメータ/入力 | コールバック | 構成プロパティー | 選択ポリシー |
---|---|---|---|---|
CRAM-MD5 | 承認 ID (デフォルトのユーザー名として) | NameCallback PasswordCallback |
Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
|
DIGEST-MD5 | 承認 ID プロトコル ID サーバー名 |
NameCallback PasswordCallback RealmCallback RealmChoiceCallback |
Sasl.QOP Sasl.STRENGTH Sasl.MAX_BUFFER Sasl.SERVER_AUTH "javax.security.sasl.sendmaxbuffer" "com.sun.security.sasl.digest.cipher" |
Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
EXTERNAL | 認証 ID 外部 チャネル |
Sasl.POLICY_NOPLAINTEXT Sasl.POLICY_NOACTIVE Sasl.POLICY_NODICTIONARY |
||
GSSAPI | JAAS サブジェクト 承認 ID プロトコル ID サーバー名 |
Sasl.QOP Sasl.MAX_BUFFER Sasl.SERVER_AUTH "javax.security.sasl.sendmaxbuffer" |
Sasl.POLICY_NOACTIVE Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
|
PLAIN | 承認 ID | NameCallback PasswordCallback |
Sasl.POLICY_NOANONYMOUS |
SunSASL プロバイダのこれらのメカニズムを使用するアプリケーションは、必要なパラメータ、コールバック、およびプロパティーを提供する必要があります。プロパティーには適切なデフォルト値が設定されているため、アプリケーションがデフォルト値をオーバーライドする場合にのみ設定する必要があります。ほとんどのパラメータ、コールバック、およびプロパティーは API ドキュメントで説明されています。次のセクションでは、メカニズム固有の動作、および API ドキュメントで説明されていないパラメータについて説明します。
Cram-MD5 クライアントメカニズムは承認 ID パラメータが指定された場合、その承認 ID パラメータを NameCallback
内でデフォルトのユーザー名として使用して、アプリケーション/エンドユーザーに承認 ID を求めます。それ以外では、承認 ID は Cram-MD5 メカニズムによって使用されません。認証 ID のみがサーバーと交換されます。
Digest-MD5 メカニズムは、ダイジェスト認証およびオプションでセキュリティー層を確立する場合に使用されます。セキュリティー層とともに使用する Triple DES、DES、および RC4 (128、56、および 40 ビット) の暗号を指定します。Digest-MD5 メカニズムは、プラットフォームで使用可能な暗号のみをサポートできます。たとえば、プラットフォームが RC4 暗号をサポートしない場合、Digest-MD5 メカニズムはその暗号を使用しません。
Sasl.STRENGTH プロパティーは、「high」、「medium」、および「low」設定をサポートしており、デフォルトは「high,medium,low」です。暗号は、次のように強度設定にマッピングされています。
強度 | 暗号 | 暗号 ID |
---|---|---|
high | Triple DES RC4 128 ビット |
3des rc4 |
medium | DES RC4 56 ビット |
des rc4-56 |
low | RC4 40 ビット | rc4-40 |
特定の強度に複数の選択肢がある場合、選択される暗号は、基盤となるプラットフォームでの暗号の可用性によって決まります。使用する暗号を明示的に指定するには、「com.sun.security.sasl.digest.cipher」プロパティーを対応する暗号 ID に設定します。このプロパティー設定は、Sasl.STRENGTH および基盤となるプラットフォームで利用可能な暗号と互換性を持たせてください。たとえば、「low」に設定されている Sasl.STRENGTH と「3des」に設定されている「com.sun.security.sasl.digest.cipher」には、互換性がありません。「com.sun.security.sasl.digest.cipher」プロパティーには、デフォルトはありません。
「javax.security.sasl.sendmaxbuffer」プロパティーは、最大送信バッファーサイズ (の文字列表現) をバイト単位で指定します。デフォルト値は 65536 です。実際の最大バイト数は、この数の最小値およびピアの最大受信バッファーサイズになります。
Subject
がクライアントの Kerberos 資格を含むこと、または Kerberos に暗黙的にログインすることによって資格が取得されることを想定しています。クライアントの Kerberos 資格を取得するには、Java Authentication and Authorization Service (JAAS) を使用し、Kerberos ログインモジュールを使用してログインします。詳細および例は、「Kerberos を使った Java GSS-API および JAAS のチュートリアル」を参照してください。JAAS 認証を使用して Kerberos 資格を取得したあとで、SASL GSSAPI メカニズムを使用するコードを doAs または doAsPrivileged 内に配置します。
LoginContext lc = new LoginContext("JaasSample", new TextCallbackHandler()); lc.login(); lc.getSubject().doAs(new SaslAction()); class SaslAction implements java.security.PrivilegedAction { public class run() { ... String[] mechanisms = new String[]{"GSSAPI"}; SaslClient sc = Sasl.createSaslClient(mechanisms, authzid, protocol, serverName, props, callbackHandler); ... } }JAAS プログラミングを明示的に行わずに Kerberos 資格を取得するには、「Kerberos を使った Java GSS-API および JAAS のチュートリアル」を参照してください。この方法を使用する場合は、コードを doAs または doAsPrivileged 内にラップする必要はありません。
「javax.security.sasl.sendmaxbuffer」プロパティーは、最大送信バッファーサイズ (の文字列表現) をバイト単位で指定します。デフォルト値は 65536 です。実際の最大バイト数は、この数の最小値およびピアの最大受信バッファーサイズになります。
サーバーメカニズム名 | パラメータ/入力 | コールバック | 構成プロパティー | 選択ポリシー |
---|---|---|---|---|
CRAM-MD5 | サーバー名 | AuthorizeCallback NameCallback PasswordCallback |
Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
|
DIGEST-MD5 | プロトコル ID サーバー名 |
AuthorizeCallback NameCallback PasswordCallback RealmCallback |
Sasl.QOP Sasl.STRENGTH Sasl.MAX_BUFFER "javax.security.sasl.sendmaxbuffer" "com.sun.security.sasl.digest.realm" "com.sun.security.sasl.digest.utf8" |
Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
GSSAPI | JAAS サブジェクト プロトコル ID サーバー名 |
AuthorizeCallback | Sasl.QOP Sasl.MAX_BUFFER "javax.security.sasl.sendmaxbuffer" |
Sasl.POLICY_NOACTIVE Sasl.POLICY_NOANONYMOUS Sasl.POLICY_NOPLAINTEXT |
SunSASL プロバイダのこれらのメカニズムを使用するアプリケーションは、必要なパラメータ、コールバック、およびプロパティーを提供する必要があります。プロパティーには適切なデフォルト値が設定されているため、アプリケーションがデフォルト値をオーバーライドする場合にのみ設定する必要があります。
サーバーメカニズムのすべてのユーザーには、AuthorizeCallback を処理するコールバックハンドラが必要です。これは、要求された承認 ID に代わって認証済みのユーザーが操作できるかどうかを判別するため、および承認されたユーザーの正規化された名前を取得するために (正規化が適用可能な場合)、メカニズムによって使用されます。
ほとんどのパラメータ、コールバック、およびプロパティーは API ドキュメントで説明されています。次のセクションでは、メカニズム固有の動作、および API ドキュメントで説明されていないパラメータについて説明します。
「javax.security.sasl.sendmaxbuffer」プロパティーについては、Digest-MD5 クライアントのセクションで説明しています。
「com.sun.security.sasl.digest.realm」プロパティーは、サーバーがサポートするレルムの名前を空白で区切ったリストを指定するために使用されます。このリストは、チャレンジの一部としてクライアントに送信されます。このプロパティーが設定されていない場合、デフォルトのレルムはサーバーの名前です (パラメータとして指定)。
「com.sun.security.sasl.digest.utf8」プロパティーは、使用する文字エンコーディングを指定するために使用されます。「true」は UTF-8 エンコーディングを使用することを意味し、「false」は ISO Latin 1 (ISO-8859-1) を使用することを意味します。デフォルトは「true」です。
javax.security.sasl.level=FINEST handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=FINEST
次の表に、メカニズムおよびそれらが生成するロギング出力を示します。
メカニズム | ロギングレベル | ログ記録される情報 |
---|---|---|
CRAM-MD5 | FINE | 構成プロパティー。チャレンジおよび応答メッセージ |
DIGEST-MD5 | INFO | エンコーディングの問題のために破棄されたメッセージ (不一致の MAC、不正なパディングなど) |
DIGEST-MD5 | FINE | 構成プロパティー。チャレンジおよび応答メッセージ |
DIGEST-MD5 | FINER | チャレンジおよび応答メッセージに関するより詳細な情報 |
DIGEST-MD5 | FINEST | セキュリティー層で交換されるバッファー |
GSSAPI | FINE | 構成プロパティー。チャレンジおよび応答メッセージ |
GSSAPI | FINER | チャレンジおよび応答メッセージに関するより詳細な情報 |
GSSAPI | FINEST | セキュリティー層で交換されるバッファー |
最初のステップでは、SASL メカニズムを実装します。クライアントメカニズムを実装するには、SaslClient インタフェースで宣言されたメソッドを実装する必要があります。同様に、サーバーメカニズムの場合は、SaslServer インタフェースで宣言されたメソッドを実装する必要があります。この説明では、クライアントメカニズム「SAMPLE-MECH」の実装を開発するとします。このメカニズムは、クラス com.example.SampleMechClient によって実装されます。メカニズムが必要とする入力、およびそれらを実装が収集する方法を決定します。たとえば、メカニズムがユーザー名/パスワードベースの場合、実装ではその情報をコールバックハンドラパラメータ経由で収集する必要性が高くなります。
次のステップでは、com.example.SampleMechClient のインスタンスを作成するファクトリクラスを記述します。ファクトリは Sasl.POLICY_* プロパティーによって記述されるように、サポートするメカニズムの特性を決定する必要があります。そうすることにより、互換性のあるポリシープロパティーを使用して API ユーザーが要求したときに、メカニズムのインスタンスを返すことができます。ファクトリは、また、メカニズムを作成する前にパラメータの妥当性をチェックする場合もあります。この説明では、ファクトリクラスの名前を com.example.MySampleClientFactory とします。サンプルファクトリは 1 つのメカニズムのみを処理しますが、1 つのファクトリは任意の数のメカニズムを処理できます。
最後のステップでは、JCA プロバイダを作成します。JCA プロバイダを作成する手順は、「Java 暗号化アーキテクチャー用プロバイダの実装方法」に詳細に説明されています。SASL クライアントファクトリは、次の形式のプロパティー名を使用して登録されます。
SaslClientFactory.mechName
一方、SASL サーバーファクトリは、次の形式のプロパティー名を使用して登録されます。SaslServerFactory.mechName
mechName は、SASL メカニズムの名前です。これは、SaslClient.getMechanismName() および SaslServer.getMechanismName() によって返された名前です。この例で、プロバイダが「SAMPLE-MECH」メカニズムを登録する方法を次に示します。
put("SaslClientFactory.SAMPLE-MECH", "com.example.MySampleClientFactory");
1 つの SASL プロバイダが、多数のメカニズムを処理する場合があります。そのため、関連するファクトリを登録する put の呼び出しが多数ある場合があります。完了した SASL プロバイダは、前述の手順を使用して、アプリケーションで利用可能にすることができます。