FileDocCategorySizeDatePackage
Krb5LoginModule.javaAPI DocJava SE 6 API38264Tue Jun 10 00:23:22 BST 2008com.sun.security.auth.module

Krb5LoginModule

public class Krb5LoginModule extends Object implements LoginModule

This LoginModule authenticates users using Kerberos protocols.

The configuration entry for Krb5LoginModule has several options that control the authentication process and additions to the Subject's private credential set. Irrespective of these options, the Subject's principal set and private credentials set are updated only when commit is called. When commit is called, the KerberosPrincipal is added to the Subject's principal set and KerberosTicket is added to the Subject's private credentials.

If the configuration entry for KerberosLoginModule has the option storeKey set to true, then KerberosKey will also be added to the subject's private credentials. KerberosKey, the principal's key will be either obtained from the keytab or derived from user's password.

This LoginModule recognizes the doNotPrompt option. If set to true the user will not be prompted for the password.

The user can specify the location of the ticket cache by using the option ticketCache in the configuration entry.

The user can specify the keytab location by using the option keyTab in the configuration entry.

The principal name can be specified in the configuration entry by using the option principal. The principal name can either be a simple user name or a service name such as host/mission.eng.sun.com. The principal can also be set using the system property sun.security.krb5.principal. This property is checked during login. If this property is not set, then the principal name from the configuration is used. In the case where the principal property is not set and the principal entry also does not exist, the user is prompted for the name.

The following is a list of configuration options supported for Krb5LoginModule:

refreshKrb5Config:
Set this to true, if you want the configuration to be refreshed before the login method is called.

useTicketCache:
Set this to true, if you want the TGT to be obtained from the ticket cache. Set this option to false if you do not want this module to use the ticket cache. (Default is False). This module will search for the tickect cache in the following locations: For Windows 2000, it will use Local Security Authority (LSA) API to get the TGT. On Solaris and Linux it will look for the ticket cache in /tmp/krb5cc_uid where the uid is numeric user identifier. If the ticket cache is not available in either of the above locations, or if we are on a different Windows platform, it will look for the cache as {user.home}{file.separator}krb5cc_{user.name}. You can override the ticket cache location by using ticketCache

ticketCache:
Set this to the name of the ticket cache that contains user's TGT. If this is set, useTicketCache must also be set to true; Otherwise a configuration error will be returned.

renewTGT:
Set this to true, if you want to renew the TGT. If this is set, useTicketCache must also be set to true; otherwise a configuration error will be returned.

doNotPrompt:
Set this to true if you do not want to be prompted for the password if credentials can not be obtained from the cache or keytab.(Default is false) If set to true authentication will fail if credentials can not be obtained from the cache or keytab.

useKeyTab:
Set this to true if you want the module to get the principal's key from the the keytab.(default value is False) If keyatb is not set then the module will locate the keytab from the Kerberos configuration file.
If it is not specifed in the Kerberos configuration file then it will look for the file {user.home}{file.separator}krb5.keytab.

keyTab:
Set this to the file name of the keytab to get principal's secret key.

storeKey:
Set this to true to if you want the principal's key to be stored in the Subject's private credentials.

principal:
The name of the principal that should be used. The principal can be a simple username such as "testuser" or a service name such as "host/testhost.eng.sun.com". You can use the principal option to set the principal when there are credentials for multiple principals in the keyTab or when you want a specific ticket cache only. The principal can also be set using the system property sun.security.krb5.principal. In addition, if this system property is defined, then it will be used. If this property is not set, then the principal name from the configuration will be used.

isInitiator:
Set this to true, if initiator. Set this to false, if acceptor only. (Default is true). Note: Do not set this value to false for initiators.

This LoginModule also recognizes the following additional Configuration options that enable you to share username and passwords across different authentication modules:


useFirstPass if, true, this LoginModule retrieves the
username and password from the module's shared state,
using "javax.security.auth.login.name" and
"javax.security.auth.login.password" as the respective
keys. The retrieved values are used for authentication.
If authentication fails, no attempt for a retry
is made, and the failure is reported back to the
calling application.

tryFirstPass if, true, this LoginModule retrieves the
the username and password from the module's shared
state using "javax.security.auth.login.name" and
"javax.security.auth.login.password" as the respective
keys. The retrieved values are used for
authentication.
If authentication fails, the module uses the
CallbackHandler to retrieve a new username
and password, and another attempt to authenticate
is made. If the authentication fails,
the failure is reported back to the calling application

storePass if, true, this LoginModule stores the username and
password obtained from the CallbackHandler in the
modules shared state, using
"javax.security.auth.login.name" and
"javax.security.auth.login.password" as the respective
keys. This is not performed if existing values already
exist for the username and password in the shared
state, or if authentication fails.

clearPass if, true, this LoginModule clears the
username and password stored in the module's shared
state after both phases of authentication
(login and commit) have completed.

Examples of some configuration values for Krb5LoginModule in JAAS config file and the results are:

    doNotPrompt=true;

This is an illegal combination since useTicketCache is not set and the user can not be prompted for the password.

    ticketCache = < filename >;

This is an illegal combination since useTicketCache is not set to true and the ticketCache is set. A configuration error will occur.

    renewTGT=true;

This is an illegal combination since useTicketCache is not set to true and renewTGT is set. A configuration error will occur.

    storeKey=true useTicketCache = true doNotPrompt=true;;

This is an illegal combination since storeKey is set to true but the key can not be obtained either by prompting the user or from the keytab.A configuration error will occur.

    keyTab = < filename > doNotPrompt=true ;

This is an illegal combination since useKeyTab is not set to true and the keyTab is set. A configuration error will occur.

    debug=true

Prompt the user for the principal name and the password. Use the authentication exchange to get TGT from the KDC and populate the Subject with the principal and TGT. Output debug messages.

    useTicketCache = true doNotPrompt=true;

Check the default cache for TGT and populate the Subject with the principal and TGT. If the TGT is not available, do not prompt the user, instead fail the authentication.

    principal=< name >useTicketCache = true doNotPrompt=true;

Get the TGT from the default cache for the principal and populate the Subject's principal and private creds set. If ticket cache is not available or does not contain the principal's TGT authentication will fail.

    useTicketCache = true ticketCache=< file name >useKeyTab = true keyTab=< keytab filename > principal = < principal name > doNotPrompt=true;

Search the cache for the principal's TGT. If it is not available use the key in the keytab to perform authentication exchange with the KDC and acquire the TGT. The Subject will be populated with the principal and the TGT. If the key is not available or valid then authentication will fail.

    useTicketCache = true ticketCache=< file name >

The TGT will be obtained from the cache specified. The Kerberos principal name used will be the principal name in the Ticket cache. If the TGT is not available in the ticket cache the user will be prompted for the principal name and the password. The TGT will be obtained using the authentication exchange with the KDC. The Subject will be populated with the TGT.

    useKeyTab = true keyTab=< keytab filename > principal= < principal name > storeKey=true;

The key for the principal will be retrieved from the keytab. If the key is not available in the keytab the user will be prompted for the principal's password. The Subject will be populated with the principal's key either from the keytab or derived from the password entered.

    useKeyTab = true keyTab=< keytabname > storeKey=true doNotPrompt=true;

The user will be prompted for the service principal name. If the principal's longterm key is available in the keytab , it will be added to the Subject's private credentials. An authentication exchange will be attempted with the principal name and the key from the Keytab. If successful the TGT will be added to the Subject's private credentials set. Otherwise the authentication will fail.

    useKeyTab = true keyTab=< file name > storeKey=true principal= < principal name > useTicketCache=true ticketCache=< file name >;

The principal's key will be retrieved from the keytab and added to the Subject's private credentials. If the key is not available, the user will be prompted for the password; the key derived from the password will be added to the Subject's private credentials set. The client's TGT will be retrieved from the ticket cache and added to the Subject's private credentials. If the TGT is not available in the ticket cache, it will be obtained using the authentication exchange and added to the Subject's private credentials.

    isInitiator = false

Configured to act as acceptor only, credentials are not acquired via AS exchange. For acceptors only, set this value to false. For initiators, do not set this value to false.

    isInitiator = true

Configured to act as initiator, credentials are acquired via AS exchange. For initiators, set this value to true, or leave this option unset, in which case default value (true) will be used.

version
1.18, 01/11/00
author
Ram Marti

Fields Summary
private Subject
subject
private CallbackHandler
callbackHandler
private Map
sharedState
private Map
options
private boolean
debug
private boolean
storeKey
private boolean
doNotPrompt
private boolean
useTicketCache
private boolean
useKeyTab
private String
ticketCacheName
private String
keyTabName
private String
princName
private boolean
useFirstPass
private boolean
tryFirstPass
private boolean
storePass
private boolean
clearPass
private boolean
refreshKrb5Config
private boolean
renewTGT
private boolean
isInitiator
private boolean
succeeded
private boolean
commitSucceeded
private String
username
private EncryptionKey[]
encKeys
private Credentials
cred
private PrincipalName
principal
private KerberosPrincipal
kerbClientPrinc
private KerberosTicket
kerbTicket
private KerberosKey[]
kerbKeys
private StringBuffer
krb5PrincName
private char[]
password
private static final String
NAME
private static final String
PWD
static final ResourceBundle
rb
Constructors Summary
Methods Summary
public booleanabort()

This method is called if the LoginContext's overall authentication failed. (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not succeed).

If this LoginModule's own authentication attempt succeeded (checked by retrieving the private state saved by the login and commit methods), then this method cleans up any state that was originally saved.

exception
LoginException if the abort fails.
return
false if this LoginModule's own login and/or commit attempts failed, and true otherwise.

	if (succeeded == false) {
	    return false;
	} else if (succeeded == true && commitSucceeded == false) {
	    // login succeeded but overall authentication failed
	    succeeded = false;
	    cleanKerberosCred();
	} else {
	    // overall authentication succeeded and commit succeeded,
	    // but someone else's commit failed
	    logout();
	}
	return true;
    
private voidattemptAuthentication(boolean getPasswdFromSharedState)
process the configuration options Get the TGT either out of cache or from the KDC using the password entered Check the permission before getting the TGT

	
	/* 
	 * Check the creds cache to see whether 
	 * we have TGT for this client principal
	 */
	if (krb5PrincName != null) {
	    try {
	        principal = new PrincipalName
		    (krb5PrincName.toString(),
		     PrincipalName.KRB_NT_PRINCIPAL);
	    } catch (KrbException e) {
		LoginException le = new LoginException(e.getMessage());
		le.initCause(e);
		throw le;
	    }
	}

	try { 
	    if (useTicketCache) {
		// ticketCacheName == null implies the default cache
		if (debug)
		    System.out.println("Acquire TGT from Cache");
		cred  = Credentials.acquireTGTFromCache
		    (principal, ticketCacheName);

		if (cred != null) {
		    // check to renew credentials
		    if (!isCurrent(cred)) {
			if (renewTGT) {
			    cred = renewCredentials(cred);
			} else {
			    // credentials have expired
			    cred = null;
			    if (debug)
				System.out.println("Credentials are" +
						" no longer valid");
			}
		    }
		}

		if (cred != null) {
		   // get the principal name from the ticket cache
		   if (principal == null) { 
			principal = cred.getClient();
		   }
		}
		if (debug) {
		    System.out.println("Principal is " + principal);
		    if (cred == null) {
			System.out.println
			    ("null credentials from Ticket Cache");
		    }
		}
	    }		     

	    // cred = null indicates that we didn't get the creds
	    // from the cache or useTicketCache was false
		
	    if (cred == null) {
		// We need the principal name whether we use keytab
		// or AS Exchange
		if (principal == null) {
		    promptForName(getPasswdFromSharedState);
		    principal = new PrincipalName
			(krb5PrincName.toString(),
			 PrincipalName.KRB_NT_PRINCIPAL);
		}
		if (useKeyTab) {
		    encKeys = 
			EncryptionKey.acquireSecretKeys(principal, keyTabName);

		    if (debug) {
			if (encKeys != null)
			    System.out.println
				("principal's key obtained from the keytab");
			else
			    System.out.println
				("Key for the principal " + 
				 principal  + 
				 " not available in " + 
				 ((keyTabName == null) ? 
				  "default key tab" : keyTabName));
		    }
		    
		}   
		// We can't get the key from the keytab so prompt    
		if (encKeys == null) {	
		    promptForPass(getPasswdFromSharedState);

		    encKeys = EncryptionKey.acquireSecretKeys(
			password, principal.getSalt());

		    if (isInitiator) {
			if (debug)
			    System.out.println("Acquire TGT using AS Exchange");
			cred = Credentials.acquireTGT(principal, 
						encKeys, password);
			// update keys after pre-auth
			encKeys = EncryptionKey.acquireSecretKeys(password, 
							principal.getSalt());
		    }
		} else {
		    if (isInitiator) {
			if (debug)
			    System.out.println("Acquire TGT using AS Exchange");
			cred = Credentials.acquireTGT(principal, 
						encKeys, password);
		    }
		}

		// Get the TGT using AS Exchange
		if (debug) {
		    System.out.println("principal is " + principal);
		    HexDumpEncoder hd = new HexDumpEncoder();	
		    for (int i = 0; i < encKeys.length; i++) {
			System.out.println("EncryptionKey: keyType=" + 
			    encKeys[i].getEType() + " keyBytes (hex dump)=" +
                            hd.encode(encKeys[i].getBytes()));
		    }
		}

		// we should hava a non-null cred
		if (isInitiator && (cred == null)) {
		    throw new LoginException 
			("TGT Can not be obtained from the KDC ");
		}

	    }
	} catch (KrbException e) {
	    LoginException le = new LoginException(e.getMessage());
	    le.initCause(e);
	    throw le;
	} catch (IOException ioe) {
	    LoginException ie = new LoginException(ioe.getMessage());
	    ie.initCause(ioe);
	    throw ie;
	}
    
private voidcleanKerberosCred()
Clean Kerberos credentials

	// Clean the ticket and server key
	try {
	    if (kerbTicket != null)
		kerbTicket.destroy();
	    if (kerbKeys != null) {
	        for (int i = 0; i < kerbKeys.length; i++) {
		    kerbKeys[i].destroy();
  		}
            }
	} catch (DestroyFailedException e) {
	    throw new LoginException
		("Destroy Failed on Kerberos Private Credentials");
	}
	kerbTicket = null;
	kerbKeys = null;
	kerbClientPrinc = null;
    
private voidcleanState()
Clean out the state

       
	// save input as shared state only if
	// authentication succeeded
	if (succeeded) {
	    if (storePass &&
		!sharedState.containsKey(NAME) &&
		!sharedState.containsKey(PWD)) {
		sharedState.put(NAME, username);
		sharedState.put(PWD, password);
	    }
	}
	username = null;
	password = null;
	if (krb5PrincName != null && krb5PrincName.length() != 0)
	    krb5PrincName.delete(0, krb5PrincName.length());
	krb5PrincName = null;
	if (clearPass) {
	    sharedState.remove(NAME);
	    sharedState.remove(PWD);
	}
    
public booleancommit()

This method is called if the LoginContext's overall authentication succeeded (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules succeeded).

If this LoginModule's own authentication attempt succeeded (checked by retrieving the private state saved by the login method), then this method associates a Krb5Principal with the Subject located in the LoginModule. It adds Kerberos Credentials to the the Subject's private credentials set. If this LoginModule's own authentication attempted failed, then this method removes any state that was originally saved.

exception
LoginException if the commit fails.
return
true if this LoginModule's own login and commit attempts succeeded, or false otherwise.


	/*
	 * Let us add the Krb5 Creds to the Subject's 
	 * private credentials. The credentials are of type
	 * KerberosKey or KerberosTicket
	 */
	if (succeeded == false) {
	    return false;
	} else {

	    if (isInitiator && (cred == null)) {
		succeeded = false;
		throw new LoginException("Null Client Credential");
	    }

	    if (subject.isReadOnly()) {
	        cleanKerberosCred();
		throw new LoginException("Subject is Readonly");
	    }

	    /*
	     * Add the Principal (authenticated identity)
	     * to the Subject's principal set and
	     * add the credentials (TGT or Service key) to the
	     * Subject's private credentials
	     */

	    Set privCredSet =  subject.getPrivateCredentials();
	    Set princSet  = subject.getPrincipals();
	    kerbClientPrinc = new KerberosPrincipal(principal.getName());
	
	    // create Kerberos Ticket 
	    if (isInitiator) {
		kerbTicket = Krb5Util.credsToTicket(cred);
	    }

	    if (storeKey) {
		if (encKeys == null || encKeys.length <= 0) {
		    succeeded = false;
		    throw new LoginException("Null Server Key ");
		}

		kerbKeys = new KerberosKey[encKeys.length];
		for (int i = 0; i < encKeys.length; i ++) {
	            Integer temp = encKeys[i].getKeyVersionNumber();
		    kerbKeys[i] = new KerberosKey(kerbClientPrinc,
					  encKeys[i].getBytes(),
					  encKeys[i].getEType(),
					  (temp == null?
					  0: temp.intValue()));
                }
		
	    }
	    // Let us add the kerbClientPrinc,kerbTicket and kerbKey (if
	    // storeKey is true)
	    if (!princSet.contains(kerbClientPrinc))
		princSet.add(kerbClientPrinc);

	    // add the TGT
	    if (kerbTicket != null) {
		if (!privCredSet.contains(kerbTicket)) 	
		    privCredSet.add(kerbTicket);
	    }

	    if (storeKey) {
		for (int i = 0; i < kerbKeys.length; i++) {
		    if (!privCredSet.contains(kerbKeys[i])) {	
    			privCredSet.add(kerbKeys[i]);
		    }
		    encKeys[i].destroy();
		    encKeys[i] = null;
		    if (debug) {
		        System.out.println("Added server's key"
					+ kerbKeys[i]);		    
		        System.out.println("\t\t[Krb5LoginModule] " +
				       "added Krb5Principal  " + 
				       kerbClientPrinc.toString()
				       + " to Subject");
		    }			
		}
	    }
	}
	commitSucceeded = true;
	if (debug)
	    System.out.println("Commit Succeeded \n");
	return true;
    
public voidinitialize(javax.security.auth.Subject subject, javax.security.auth.callback.CallbackHandler callbackHandler, java.util.Map sharedState, java.util.Map options)
Initialize this LoginModule.

param
subject the Subject to be authenticated.

param
callbackHandler a CallbackHandler for communication with the end user (prompting for usernames and passwords, for example).

param
sharedState shared LoginModule state.

param
options options specified in the login Configuration for this particular LoginModule.


                                                                                  			   			     

        
			    
			     
			      
 
	this.subject = subject;
	this.callbackHandler = callbackHandler;
	this.sharedState = sharedState;
	this.options = options;

	// initialize any configured options

	debug = "true".equalsIgnoreCase((String)options.get("debug"));
	storeKey = "true".equalsIgnoreCase((String)options.get("storeKey"));
	doNotPrompt = "true".equalsIgnoreCase((String)options.get
					      ("doNotPrompt"));
	useTicketCache = "true".equalsIgnoreCase((String)options.get
						 ("useTicketCache"));
	useKeyTab = "true".equalsIgnoreCase((String)options.get("useKeyTab"));
	ticketCacheName = (String)options.get("ticketCache");
	keyTabName = (String)options.get("keyTab");
	princName = (String)options.get("principal");
	refreshKrb5Config =
	    "true".equalsIgnoreCase((String)options.get("refreshKrb5Config"));
	renewTGT =
	    "true".equalsIgnoreCase((String)options.get("renewTGT"));

	// check isInitiator value
	String isInitiatorValue = ((String)options.get("isInitiator"));
	if (isInitiatorValue == null) {
	    // use default, if value not set
	} else {
	    isInitiator = "true".equalsIgnoreCase(isInitiatorValue);
	}

	tryFirstPass =
	    "true".equalsIgnoreCase
	    ((String)options.get("tryFirstPass"));
	useFirstPass =
	    "true".equalsIgnoreCase
	    ((String)options.get("useFirstPass"));
	storePass =
	    "true".equalsIgnoreCase((String)options.get("storePass"));
	clearPass =
	    "true".equalsIgnoreCase((String)options.get("clearPass"));
	if (debug) {
	    System.out.print("Debug is  " + debug  
			     + " storeKey " + storeKey 
			     + " useTicketCache " + useTicketCache
			     + " useKeyTab " + useKeyTab
			     + " doNotPrompt " + doNotPrompt
			     + " ticketCache is " + ticketCacheName
			     + " isInitiator " + isInitiator
			     + " KeyTab is " + keyTabName
			     + " refreshKrb5Config is " + refreshKrb5Config
		     	     + " principal is " + princName
			     + " tryFirstPass is " + tryFirstPass 
			     + " useFirstPass is " + useFirstPass
			     + " storePass is " + storePass
			     + " clearPass is " + clearPass + "\n");
	}
    
private booleanisCurrent(sun.security.krb5.Credentials creds)

	Date endTime = creds.getEndTime();
	if (endTime != null) {
	    return (System.currentTimeMillis() <= endTime.getTime());
	}
	return true;
    
public booleanlogin()
Authenticate the user

return
true in all cases since this LoginModule should not be ignored.
exception
FailedLoginException if the authentication fails.

exception
LoginException if this LoginModule is unable to perform the authentication.


	int len;	
	validateConfiguration();
	if (refreshKrb5Config) {
	    try {
		if (debug) {
		    System.out.println("Refreshing Kerberos configuration");
		}
	        sun.security.krb5.Config.refresh();
	    } catch (KrbException ke) {
	        LoginException le = new LoginException(ke.getMessage());
	        le.initCause(ke);
	        throw le;
	    }
	}
	String principalProperty = System.getProperty
	    ("sun.security.krb5.principal"); 
	if (principalProperty != null) {
	    krb5PrincName = new StringBuffer(principalProperty);
	} else {
	    if (princName != null) {
		krb5PrincName = new StringBuffer(princName);
	    }
    	}
    
	if (tryFirstPass) {
	    try {
		attemptAuthentication(true);    
		if (debug)
		    System.out.println("\t\t[Krb5LoginModule] " +
				       "authentication succeeded");
		succeeded = true;
		cleanState();
		return true;
	    } catch (LoginException le) {
		// authentication failed -- try again below by prompting
		cleanState();
		if (debug) {
		    System.out.println("\t\t[Krb5LoginModule] " +
				       "tryFirstPass failed with:" +
				       le.getMessage());
		}
	    } 
	} else if (useFirstPass) {
	    try {
		attemptAuthentication(true);
		succeeded = true;
		cleanState();
		return true;
	    } catch (LoginException e) {
		// authentication failed -- clean out state
		if (debug) {
		    System.out.println("\t\t[Krb5LoginModule] " +
				       "authentication failed \n" +
				       e.getMessage());
		}
		succeeded = false;
		cleanState();
		throw e;
	    } 
	}
    
	// attempt the authentication by getting the username and pwd 
	// by prompting or configuration i.e. not from shared state
	
	try {
	    attemptAuthentication(false);
	    succeeded = true;
	    cleanState();
	    return true;
	} catch (LoginException e) {
	    // authentication failed -- clean out state
	    if (debug) {
		System.out.println("\t\t[Krb5LoginModule] " +
				   "authentication failed \n" +
				   e.getMessage());
	    }
	    succeeded = false;
	    cleanState();
	    throw e;
	}
    
public booleanlogout()
Logout the user.

This method removes the Krb5Principal that was added by the commit method.

exception
LoginException if the logout fails.
return
true in all cases since this LoginModule should not be ignored.


        if (debug) {
            System.out.println("\t\t[Krb5LoginModule]: " +
                "Entering logout");
        }

        if (subject.isReadOnly()) {
	    cleanKerberosCred();
            throw new LoginException("Subject is Readonly");
        }
	
	subject.getPrincipals().remove(kerbClientPrinc);
	   // Let us remove all Kerberos credentials stored in the Subject 
	Iterator it = subject.getPrivateCredentials().iterator();
	while (it.hasNext()) {
	    Object o = it.next();
	    if (o instanceof KerberosTicket ||
		o instanceof KerberosKey) {
		it.remove();
	    }
	}
	// clean the kerberos ticket and keys
	cleanKerberosCred();

	succeeded = false;
	commitSucceeded = false;
	if (debug) {
            System.out.println("\t\t[Krb5LoginModule]: " +
			       "logged out Subject");
        }
	return true;
    
private voidpromptForName(boolean getPasswdFromSharedState)

	krb5PrincName = new StringBuffer("");
	if (getPasswdFromSharedState) {
	    // use the name saved by the first module in the stack
	    username = (String)sharedState.get(NAME);
	    if (debug) {
		System.out.println
		    ("username from shared state is " + username + "\n");
	    }
	    if (username == null) {
		System.out.println
		    ("username from shared state is null\n");
		throw new LoginException
		    ("Username can not be obtained from sharedstate ");
	    }
	    if (debug) {
		System.out.println
		    ("username from shared state is " + username + "\n");
	    }
	    if (username != null && username.length() > 0) {
		krb5PrincName.insert(0, username);
		return;
	    }
	}
   
	if (doNotPrompt) {
	    throw new LoginException
		("Unable to obtain Princpal Name for authentication ");
	} else {
	    if (callbackHandler == null)
		throw new LoginException("No CallbackHandler "
					 + "available "
					 + "to garner authentication " 
					 + "information from the user");
	    try {
		String defUsername = System.getProperty("user.name");
		
		Callback[] callbacks = new Callback[1];
		MessageFormat form = new MessageFormat(
				       rb.getString(
				       "Kerberos username [[defUsername]]: "));
	        Object[] source =  {defUsername};
		callbacks[0] = new NameCallback(form.format(source));
		callbackHandler.handle(callbacks);
		username = ((NameCallback)callbacks[0]).getName();
		if (username == null || username.length() == 0)
		    username = defUsername;
		krb5PrincName.insert(0, username);
		
	    } catch (java.io.IOException ioe) {
		throw new LoginException(ioe.getMessage());
	    } catch (UnsupportedCallbackException uce) {
		throw new LoginException
		    (uce.getMessage()
		     +" not available to garner " 
		     +" authentication information " 
		     +" from the user");
	    }
	}
    
private voidpromptForPass(boolean getPasswdFromSharedState)


	if (getPasswdFromSharedState) {
	    // use the password saved by the first module in the stack
	    password = (char[])sharedState.get(PWD);
	    if (password == null) {
		if (debug) {
		    System.out.println
			("Password from shared state is null");
		}
		throw new LoginException
		    ("Password can not be obtained from sharedstate ");
	    }
	    if (debug) {
		System.out.println
		    ("password is " + new String(password));
	    }
	    return;
	}
	if (doNotPrompt) {
	    throw new LoginException
		("Unable to obtain password from user\n");
	} else {
	    if (callbackHandler == null)
		throw new LoginException("No CallbackHandler "
					 + "available "
					 + "to garner authentication " 
					 + "information from the user");
	    try {
		Callback[] callbacks = new Callback[1];
		String userName = krb5PrincName.toString();
		MessageFormat form = new MessageFormat(
					 rb.getString(
					 "Kerberos password for [username]: "));
	        Object[] source = {userName};
		callbacks[0] = new PasswordCallback(
						    form.format(source),
						    false);
		callbackHandler.handle(callbacks);
		char[] tmpPassword = ((PasswordCallback)
				      callbacks[0]).getPassword();
		if (tmpPassword == null) {
		    // treat a NULL password as an empty password
		    tmpPassword = new char[0];
		}
		password = new char[tmpPassword.length];
		System.arraycopy(tmpPassword, 0,
				 password, 0, tmpPassword.length);
		((PasswordCallback)callbacks[0]).clearPassword();
		

		// clear tmpPassword
		for (int i = 0; i < tmpPassword.length; i++)
		    tmpPassword[i] = ' ";
		tmpPassword = null;
		if (debug) {
		    System.out.println("\t\t[Krb5LoginModule] " +
				       "user entered username: " +
				       krb5PrincName);
		    System.out.println();
		}
	    } catch (java.io.IOException ioe) {
		throw new LoginException(ioe.getMessage());
	    } catch (UnsupportedCallbackException uce) {
		throw new LoginException(uce.getMessage()
					 +" not available to garner " 
					 +" authentication information " 
					 + "from the user");
	    }
	}	
    
private sun.security.krb5.CredentialsrenewCredentials(sun.security.krb5.Credentials creds)

	Credentials lcreds;
	try {
	    if (!creds.isRenewable())
		throw new RefreshFailedException("This ticket" +
				" is not renewable");
	    if (System.currentTimeMillis() > cred.getRenewTill().getTime())
		throw new RefreshFailedException("This ticket is past "
                                             + "its last renewal time.");
	    lcreds = creds.renew();
	    if (debug)
		System.out.println("Renewed Kerberos Ticket");
	} catch (Exception e) {
	    lcreds = null;
	    if (debug)
		System.out.println("Ticket could not be renewed : "
				+ e.getMessage());
	}
	return lcreds;
    
private voidvalidateConfiguration()

	if (doNotPrompt && !useTicketCache && !useKeyTab)
	    throw new LoginException
		("Configuration Error" 
		 + " - either doNotPrompt should be "
		 + " false or useTicketCache/useKeyTab "
		 + " should be true");
	if (ticketCacheName != null && !useTicketCache)
	    throw new LoginException
		("Configuration Error " 
		 + " - useTicketCache should be set "
		 + "to true to use the ticket cache" 
		 + ticketCacheName);
	if (keyTabName != null & !useKeyTab)
	    throw new LoginException
		("Configuration Error - useKeyTab should be set to true "
		 + "to use the keytab" + keyTabName);
	if (storeKey && doNotPrompt && !useKeyTab) 
	    throw new LoginException
		("Configuration Error - either doNotPrompt "
		 + "should be set to false or "
		 + "useKeyTab must be set to true for storeKey option");
	if (renewTGT && !useTicketCache)
	    throw new LoginException
		("Configuration Error" 
		 + " - either useTicketCache should be "
		 + " true or renewTGT should be false");