Skip to main content

skip to main content

developerWorks  >  Java technology  >

Simplify enterprise Java authentication with single-sign on: Listing 1. GSSClient

developerWorks

Return to article.


Listing 1. GSSClient
/****
    GSSClient.java
****/

import java.io.*;
import java.util.*;
import java.security.*;
import org.ietf.jgss.*;
import java.net.Socket;
import javax.security.auth.login.*;
import javax.security.auth.Subject;

class GSSClient 
implements java.security.PrivilegedAction {

    //Handles callback from the JAAS framework.
    BeanCallbackHandler beanCallbackHandler = null;

    //The main object that handles all JAAS login.
    LoginContext peerLC = null;
	
    //Socket and streams used for communication.
    Socket socket = null;
    DataInputStream inStream; 
    DataOutputStream outStream;

    //This and remote clients.
    String clientName = null;
    String serverName = null;

    //Address and port of remote server.
    String serverAddress = null;
    int serverPort;
	
    //The name of the client configuration.
    String confName = null;


    public static void main(String[] args) {
        if (args.length < 9) {
	      System.err.println("Usage: java <options> KrberosLogin "
                   + " <clientname> <password> <servername> " 
                   + " <serveraddress> <server port> " 
                   + " <realm address> <kdc address> "
                   + " <name and path of conf file > <conf name ");
            System.exit(-1);
        }
	
        GSSClient gssClient = 
                  new GSSClient (args[0]/*client name*/ , 
                                 args[1]/*password*/, 
                                 args[2]/*clientName*/,
                                 args[3]/*serveraddress*/,
                                 Integer.parseInt(args[4])/*serverport*/, 
                                 args[5]/*kerberos realm name*/,
                                 args[6]/*kdc addres*/,
                                 args[7]/*name and path of conf file*/,
                                 args[8]/*conf name*/ );

        GSSContext context = gssClient.login();
        if (context!=null)
        {
            String response = null; 
            //Checking confidentiality status of context.
            if (context.getConfState())
            {
                response = gssClient.sendMessage(context, 
                                                 "A sample message from client");
                System.out.println ("Server Response "+response);
            }//if

            try {
                gssClient.getLoginContext().logout();
                context.dispose();
            } catch (Exception e) {
                e.printStackTrace();
            }//catch
			
        }
        else
            System.out.println("Client authentication deined...");
    }//main
	
    //The GSSClient constructor only sets all the required parameters.
    public GSSClient (String clientName, String password, 
                      String serverName, String serverAddress, 
                      int serverPort, String kerberosRealm, 
                      String kdcAddress, String confFile, String confName)
    {
        //The beanCallbackHandler will require the name and password of the client.
        beanCallbackHandler = new BeanCallbackHandler(clientName, password);
        this.clientName = clientName;
        this.serverName = serverName;
        this.serverAddress = serverAddress;
        this.serverPort = serverPort;
        this.confName = confName;
        System.setProperty("java.security.krb5.realm", kerberosRealm);
        System.setProperty("java.security.krb5.kdc", kdcAddress);
        System.setProperty("java.security.auth.login.config", confFile);

        System.out.println(this.clientName);
    }// KerberoseLoginBean


    public GSSContext login()
    {
        try {
             peerLC = new LoginContext(confName, beanCallbackHandler);
             peerLC.login();
			
             socket = new Socket(serverAddress, serverPort);
             inStream = new DataInputStream(socket.getInputStream());
             outStream = new DataOutputStream(socket.getOutputStream());
             return (GSSContext) Subject.doAs( peerLC.getSubject(), this);
        }
        catch (Exception e) {
             System.out.println( ">>>> GSSClient....
                                  Secure Context not established.." );
             e.printStackTrace();
        	 return null;
        }//catch

    }//establishSecureContextWithServer
	

    //This is the only method in PrivilegedAction interface.
    //It receives control only in case of successful authentication of the client.
    public Object run() {

       try {
           GSSManager manager = GSSManager.getInstance();
           Oid kerberos = new Oid("1.2.840.113554.1.2.2");
           GSSName clientPeerName = manager.createName(
                    //Name of the client for which we want to create this GSSName object.
                    clientName ,
                    //Type of GSSName. Our client is a Windows user, 
                    //which we can specifiy using GSSName.NT_USER_NAME property.
                    GSSName.NT_USER_NAME);

           GSSName remotePeerName = manager.createName(serverName, GSSName.NT_USER_NAME);
           System.out.println (">>> GSSClient... Getting client credentials");

           GSSCredential peerCredentials = manager.createCredential(
                     //The GSSName object of the client.
                     clientPeerName,
                     //Time for which credentials whill be valid.
                     10*60,
                     //Kerberos mecahnism identifier.
                     kerberos,
                     //The client only intiates the secure context request.
                     GSSCredential.INITIATE_ONLY);
 
           System.out.println (">>> GSSClient... 
                                GSSManager creating security context");
           GSSContext peerContext = manager.createContext(remotePeerName,
                                    kerberos,
                                    peerCredentials,
                                    GSSContext.DEFAULT_LIFETIME);
 

           peerContext.requestConf(true);
           byte[] byteToken = new byte[0];

           System.out.println (">>> GSSClient... 
                                Sending token to server over secure context");

           while (!peerContext.isEstablished()) {
               byteToken = peerContext.initSecContext(byteToken, 0, byteToken.length);
               if (byteToken != null) {
                   outStream.writeInt(byteToken.length);
                   outStream.write(byteToken );
                   outStream.flush();
               }//if

               if (!peerContext.isEstablished()) {
                   byteToken  = new byte[inStream.readInt()];
                   inStream.readFully(byteToken );
               }//if 
           }//while (!peerContext...)

            return peerContext; 
        
         }//try

         catch(org.ietf.jgss.GSSException ge) {
             System.out.println (">>> GSSClient... 
                                  GSS Exception "+ge.getMessage());
         }

         catch(java.lang.Exception e) {
             System.out.println (">>> GSSClient... 
                                  Exception "+e.getMessage());
         }//catch
         return null;
    }//run
   

    //Sends a message to the remote server on an already established context.
    //It returns the reply from the remote server.
    public String sendMessage(GSSContext context, String message)
    {
        byte[] serverMessage = null;
        byte[] clientMessage = null;

        MessageProp msgProp =  new MessageProp(0, true);

        try {
            System.out.println(">>> GSSClient... 
                                Client message is ["+message+"]");
            clientMessage = context.wrap (message.getBytes(),
                                          0, message.getBytes().length, msgProp);
            outStream.writeInt(clientMessage.length);
            outStream.write(clientMessage);
            outStream.flush();
	
            //Receiving server response and sending back to client.
            serverMessage = new byte[inStream.readInt()];
            inStream.readFully(serverMessage);
            serverMessage = context.unwrap(serverMessage, 
                                           0, serverMessage.length, msgProp);
            System.out.println(">>> GSSClient... 
                                Server message is ["+serverMessage+"]");
            return new String (serverMessage);
        } catch(Exception e){
            e.printStackTrace();
            return null;
        }
		
    }//sendMessage

    //It returns the established login context to client.
    public LoginContext getLoginContext()
    {
        return peerLC;
    }//getloginContext

}//GSSClient

Return to article.