第 V 部: SPNEGO Java GSS メカニズム (Java SE 6.0) を使用したセキュアな認証

課題 8: SPNEGO と Java Generic Security Services (GSS) API の使用

この課題の目標:

現在、Java GSS で使用可能なセキュリティーメカニズムは「Kerberos」のみです。この課題の目標は、SPNEGO などのほかの Java GSS メカニズムを使用してセキュアに関連付けを行う方法について学習することです。この機能は、Java SE 6 以降で使用できます。

SPNEGO とは

Java GSS は、複数のセキュリティーメカニズムをサポートするフレームワークです。GSS-API の下でセキュリティーメカニズムとネゴシエーションを行う方法が必要となります。これは、SPNEGO を介して使用できます。

SPNEGO は、IETF の RFC 4178 で標準化されている Simple and Protected GSS-API Negotiation メカニズムです。これは、ベースとなるセキュリティーメカニズムとのネゴシエーションを行う場合に使用する擬似セキュリティーメカニズムです。SPNEGO を使用すると、クライアントとサーバーに柔軟性が付与され、共通の GSS セキュリティーメカニズムとセキュアにネゴシエーションを行うことができます。

Microsoft は SPNEGO を多用しています。SPNEGO は、HTTP を介して Microsoft サーバーと相互運用したり、Negotiate プロトコルを介して HTTP ベースのクロスプラットフォーム認証をサポートしたりする場合に使用されます。

Java GSS で SPNEGO を使用する場合に行う必要がある設定

現在、Kerberos とともに Java GSS を使用する場合は、Kerberos OID を指定して Kerberos を使用します。

Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");

SPNEGO を使用するには、次のように SPNEGO OID を指定するだけで済みます。

Oid spnegoOid = new Oid("1.3.6.1.5.5.2");

そのあと、GSSCredential、GSSContext などを作成する際に SPNEGO OID を使用します。

実行手順:

  1. 次のコードを参照してください。これは src/GssSpNegoClient.java にあります

GssSpNegoClient.java のコードリスト。


  1. static class GssSpnegoClientAction implements PrivilegedExceptionAction {
  2. ...
  3.   public Object run() throws Exception {
  4.     // Create socket to server
  5.     Socket socket = new Socket(hostName, port);
  6.     DataInputStream inStream = new DataInputStream(socket.getInputStream());
  7.     DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());

  8.     // Get service's principal name
  9.     GSSManager manager = GSSManager.getInstance();
  10.     Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
  11.     GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, spnegoOid);

  12.     // Get the context for authentication
  13.     GSSContext context = manager.createContext(serverName, spnegoOid, null,
  14.        GSSContext.DEFAULT_LIFETIME);
  15.     context.requestMutualAuth(true); // Request mutual authentication
  16.     context.requestConf(true); // Request confidentiality

  17.     // Do the context establishment loop
  18.     byte[] token = new byte[0];
  19.     while (!context.isEstablished()) {
  20.       token = context.initSecContext(token, 0, token.length);
  21.       outStream.writeInt(token.length);
  22.       outStream.write(token);
  23.       outStream.flush();

  24.       // Check if we're done
  25.       if (!context.isEstablished()) {
  26.         token = new byte[inStream.readInt()];
  27.         inStream.readFully(token);
  28.       }
  29.     }

  30.     // Context established!

  31.     // Create MessageProp for use with unwrap (true means request confidentiality)
  32.     MessageProp prop = new MessageProp(0, true);

  33.     // Create encrypted message and send to server
  34.     byte[] reply = ...;
  35.     token = context.wrap(reply, 0, reply.length, prop);

  36.     outStream.writeInt(token.length);
  37.     outStream.write(token);
  38.     outStream.flush();

  39.     // Read token from server
  40.     token = new byte[inStream.readInt()];
  41.     inStream.readFully(token);

  42.     // Unwrap (decrypt) token sent by server
  43.     byte[] input = context.unwrap(token, 0, token.length, prop);
  44.     ...
  45.     context.dispose();
  46.     socket.close();
  47.     return null;
  48.   }
  49. }


  1. サンプルコードをコンパイルします。
    % javac GssSpNegoClient.java
  2. 次のコードを参照してください。これは src/GssSpNegoServer.java にあります

GssSpNegoServer.java のコードリスト。

  1. static class GssSpNegoServerAction implements PrivilegedExceptionAction {
  2. ...
  3.   public Object run() throws Exception {
  4.     // Create server socket for accepting connections
  5.     ServerSocket ss = new ServerSocket(localPort);

  6.     // Get own Kerberos credentials for accepting connection
  7.     GSSManager manager = GSSManager.getInstance();
  8.     Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
  9.     GSSCredential serverCreds = manager.createCredential(null,
  10.       GSSCredential.DEFAULT_LIFETIME, spnegoOid, GSSCredential.ACCEPT_ONLY);

  11.     while (true) {
  12.       Socket socket = ss.accept();
  13.       DataInputStream inStream = new DataInputStream(socket.getInputStream());
  14.       DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());

  15.       GSSContext context = manager.createContext((GSSCredential)serverCreds);

  16.       // Do the context establishment loop
  17.       byte[] token = null;
  18.       while (!context.isEstablished()) {
  19.         // Read token
  20.         token = new byte[inStream.readInt()];
  21.         inStream.readFully(token);

  22.         // Process token
  23.         token = context.acceptSecContext(token, 0, token.length);

  24.         // Send a token to the peer if one was generated by acceptSecContext
  25.         outStream.writeInt(token.length);
  26.         outStream.write(token);
  27.         outStream.flush();
  28.       }

  29.       // Context established!

  30.       // Create MessageProp for use with unwrap (will be set upon return from unwrap)
  31.       MessageProp prop = new MessageProp(0, false);

  32.       // Read token from client
  33.       token = new byte[inStream.readInt()];
  34.       inStream.readFully(token);
  35.       // Unwrap (decrypt) token sent by client
  36.       byte[] input = context.unwrap(token, 0, token.length, prop);
  37.       ...
  38.       // Create new token and send to client
  39.       byte[] reply = ...;
  40.       token = context.wrap(reply, 0, reply.length, prop);

  41.       outStream.writeInt(token.length);
  42.       outStream.write(token);
  43.       outStream.flush();
  44.       context.dispose();
  45.       socket.close();
  46.     }
  47.   }
  48. }

  1. サンプルコードをコンパイルします。
    % javac GssSpNegoServer.java
    
  2. 新規のウィンドウを起動してサーバーを起動します。
    
    % xterm &
    % java -Djava.security.auth.login.config=jaas-krb5.conf GssSpNegoServer
    
  3. クライアントアプリケーションを実行します。GssClient は、次の 2 つのパラメータを取ります。サービス名、およびそのサービスが実行されているサーバーの名前です。たとえば、サービスがマシン j1hol-001 上で実行されている host の場合は、次のように入力します。パスワードの入力を求められた場合は、changeit を入力します。
    
    % java -Djava.security.auth.login.config=jaas-krb5.conf \
    GssSpNegoClient host j1hol-001
    

GssSpNegoServer の例を実行した場合の出力。

  1. Authenticated principal: [host/j1hol-001@J1LABS.EXAMPLE.COM]
  2. Waiting for incoming connections...
  3. Got connection from client /129.145.128.102
  4. SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5
  5. Context Established!
  6. Client principal is test@J1LABS.EXAMPLE.COM
  7. Server principal is host/j1hol-001@J1LABS.EXAMPLE.COM
  8. Mutual authentication took place!
  9. Received data "Hello There!" of length 12
  10. Confidentiality applied: true
  11. Sending: Hello There! Thu May 06 12:11:15 PDT 2005


GssSpNegoClient の例を実行した場合の出力。

  1. Kerberos password for test: changeit
  2. Authenticated principal: [test@J1LABS.EXAMPLE.COM]
  3. Connected to address j1hol-001/129.145.128.102
  4. SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5
  5. Context Established!
  6. Client principal is test@J1LABS.EXAMPLE.COM
  7. Server principal is host@j1hol-001
  8. Mutual authentication took place!
  9. Sending message: Hello There!
  10. Will read token of size 93
  11. Received message: Hello There! Thu May 06 12:11:15 PDT 2005


サマリー:

この課題では、Kerberos などのベースとなるセキュリティーメカニズムとネゴシエーションを行い、ベースとなる認証システムとして Kerberos を使用してセキュアに通信を行うために SPNEGO とともに Java GSS API を使用するクライアント/サーバーアプリケーションを記述する方法について学習しました。

注: Microsoft は特定のバリエーションの SPNEGO プロトコルを実装しています。このため、Microsoft と相互運用を行うために、新しいシステムプロパティー「sun.security.spnego.msinterop」を使用して MS モードを追加しました。このプロパティーは、デフォルトで「true」になっています。無効にするには、このプロパティーを明示的に「false」に設定する必要があります。SPNEGO デバッグを有効にするには、システムプロパティー「sun.security.spnego.debug=true」を設定します。




Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.