FileDocCategorySizeDatePackage
PasswordAdapter.javaAPI DocGlassfish v2 API17081Tue Jun 19 16:57:36 BST 2007com.sun.enterprise.security.store

PasswordAdapter

public final class PasswordAdapter extends Object
This class implements an adapter for password manipulation a JCEKS. Note that although it uses locks ('synchronized'), it tends to be created anew with each use, an inefficient and potentially problematic use that could create more than one instance accessing the same keystore at a time.

Fields Summary
public static final String
PASSWORD_ALIAS_KEYSTORE
private KeyStore
_pwdStore
private final File
_keyFile
private char[]
_masterPassword
Constructors Summary
public PasswordAdapter(char[] masterPassword)
Construct a PasswordAdapter with given Shared Master Password, SMP using the default keyfile (domain-passwords.jceks)

param
smp master password
throws
CertificateException
throws
IOException
throws
KeyStoreException
throws
NoSuchAlgorithmException

       this( getDefaultKeyFileName(), masterPassword );
    
public PasswordAdapter(String keyStoreFileName, char[] masterPassword)
Construct a PasswordAdapter with given Shared Master Password, SMP.

param
keyfileName the jceks key file name
param
smp master password
throws
CertificateException
throws
IOException
throws
KeyStoreException
throws
NoSuchAlgorithmException

        final File  keyStoreFile    = new File( keyStoreFileName );
        
        _pwdStore   = loadKeyStore( keyStoreFile, masterPassword);
        
        // assign these only once the store is good; no need to keep copies otherwise!
        _keyFile            = keyStoreFile;
        _masterPassword     = masterPassword;
        
        //debugState( "PasswordAdapter constructor" );
    
Methods Summary
public synchronized booleanaliasExists(java.lang.String alias)
See if the given alias exists

param
alias the alias name
return
true if the alias exists in the keystore

        return _pwdStore.containsAlias(alias);
    
public synchronized voidchangePassword(char[] newMasterPassword)
Changes the keystore password, including the encoding of the keys within it.

There are several error conditions that could occur:

  • Problem extracting existing alias keys with new ones.
  • Problem writing the keystore, including destroying it if an I/O problem occurs.
For these reasons, make a new KeyStore and write it, then swap it with the old one.

param
newpassword the new keystore password
throws
KeyStoreException
throws
IOException
throws
NoSuchAlgorithmException
throws
CertificateException

        final char[]    oldMasterPassword       = getMasterPassword();
        //debug( "Changing master password from " + new String(oldMasterPassword) + " to "  + new String(newMasterPassword) );
        //debugState( "BEFORE changing master password" );

        writeKeyStoreSafe(newMasterPassword);
        
        //debugState( "AFTER changing master password" );
     
private java.security.KeyStoreduplicateKeyStore(char[] newMasterPassword)
Make a new in-memory KeyStore with all the keys secured with the new master password.

        final char[]    oldMasterPassword       = getMasterPassword();

        final KeyStore oldStore = _pwdStore;
        final KeyStore newKeyStore = KeyStore.getInstance("JCEKS", _pwdStore.getProvider() );
        newKeyStore.load( null, newMasterPassword );

        final Enumeration<String>   aliasesEnum = oldStore.aliases();
        while ( aliasesEnum.hasMoreElements() )
        {
            final String alias  = aliasesEnum.nextElement();

            if ( ! oldStore.isKeyEntry( alias ) )
            {
                throw new IllegalArgumentException( "Expecting keys only" );
            }

            final Key key      = oldStore.getKey( alias, oldMasterPassword );
            newKeyStore.setKeyEntry( alias, key, newMasterPassword, null);
        }

        return newKeyStore;
    
public synchronized java.util.EnumerationgetAliases()
Return the aliases from the keystore.

return
An enumeration containing all the aliases in the keystore.

        
        return _pwdStore.aliases();
    
private static java.lang.StringgetDefaultKeyFileName()

        return System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY) +
            File.separator + "config" + File.separator + PASSWORD_ALIAS_KEYSTORE;
    
private char[]getMasterPassword()


       
        return _masterPassword;
    
public synchronized java.lang.StringgetPasswordForAlias(java.lang.String alias)
This methods returns password String for a given alias and SMP.

param
alias
return
corresponding password or null if the alias does not exist.
exception
KeyStoreException
exception
NoSuchAlgorithmException
exception
UnrecoverableKeyException

        String passwordString = null;
        
        final Key key = _pwdStore.getKey( alias, getMasterPassword() );
        if ( key != null )
        {
            passwordString  = new String( key.getEncoded() );
        }
        
        return passwordString;
    
public synchronized javax.crypto.SecretKeygetPasswordSecretKeyForAlias(java.lang.String alias)
This methods returns password SecretKey for a given alias and SMP.

param
alias
return
corresponding password SecretKey or null if the alias does not exist.
exception
KeyStoreException
exception
NoSuchAlgorithmException
exception
UnrecoverableKeyException


        return (SecretKey)_pwdStore.getKey(alias, getMasterPassword()); 
    
private static java.security.KeyStoreloadKeyStore(java.io.File keyStoreFile, char[] masterPassword)
Construct a PasswordAdapter with given Shared Master Password, SMP.

param
keyfileName the jceks key file name
param
smp the master password
exception
CertificateException
exception
IOException
exception
KeyStoreException
exception
NoSuchAlgorithmException

     
        final KeyStore  keyStore = KeyStore.getInstance("JCEKS");

        if ( keyStoreFile.exists() )
        {
            // don't buffer keystore; it's tiny anyway
            final FileInputStream   input   = new FileInputStream( keyStoreFile );
            try {
                keyStore.load( input, masterPassword );
            }
            finally {
                input.close();
            }
        }
        else
        {
            keyStore.load( null, masterPassword );
        }

        return keyStore;       
    
public synchronized voidremoveAlias(java.lang.String alias)
Remove an alias from the keystore

param
alias The name of the alias to remove
throws
KeyStoreException
throws
IOException
throws
NoSuchAlgorithmException
throws
CertificateException

        _pwdStore.deleteEntry(alias);
        writeStore();
    
private voidsetMasterPassword(char[] smp)

        _masterPassword = smp;
    
public synchronized voidsetPasswordForAlias(java.lang.String alias, byte[] keyBytes)
This methods set alias, secretKey into JCEKS keystore.

param
alias
param
secretKey
exception
CertificateException
exception
IOException
exception
KeyStoreException
exception
NoSuchAlgorithmException

        //debugState( "BEFORE setPasswordForAlias" );
        final Key key = new SecretKeySpec(keyBytes, "AES");
        _pwdStore.setKeyEntry( alias, key, getMasterPassword(), null);
        writeStore();
        //debugState( "AFTER setPasswordForAlias" );
    
private synchronized voidwriteKeyStoreSafe(char[] masterPassword)
Writes the current KeyStore to disk in a manner that preserves its on-disk representation from being destroyed if something goes wrong; a temporary file is used.

     
        final boolean keystoreExists = _keyFile.exists();
        
        // if the KeyStore exists, update it in a manner that doesn't destroy
        // the existing store if a failure occurs.
        if ( keystoreExists )
        {
            final KeyStore oldStore = _pwdStore;
            final KeyStore newKeyStore = duplicateKeyStore( masterPassword );   
            
            // 'newKeyStore' is now complete; rename the old KeyStore, the write the new one in its place
            final File  saveOld = new File( _keyFile.toString() + ".save" );

            if ( ! _keyFile.renameTo( saveOld ) )
            {
                final String msg    = "Can't rename " + _keyFile + " to " + saveOld;
                throw new IOException( msg );
            }

            try
            {
                //debug( "Writing KeyStore to " + _keyFile + " using master password = " + new String(masterPassword) );
                writeKeyStoreToFile( newKeyStore, _keyFile, masterPassword );
                _pwdStore   = newKeyStore;
                _masterPassword = masterPassword;
                //debug( "KeyStore written successfully" );
            }
            catch( final Throwable t )
            {
                try
                {
                    saveOld.renameTo( _keyFile );
                }
                catch( final Throwable tt )
                {
                    /* best effort failed */
                    throw new RuntimeException( "Could not write new KeyStore, and " +
                        "cannot restore KeyStore to original state", tt );
                }
                
                throw new RuntimeException( "Can't write new KeyStore", t );
            }

            try
            {
                //debug( "deleting old keystore " + saveOld );
                saveOld.delete();
               // //debug( "done deleting old keystore "  saveOld );
            }
            catch( Throwable t )
            {
                throw new RuntimeException( "Can't remove old KeyStore \"" +  _keyFile  + "\"", t );
            }
        }
        else 
        {
            //debug( "Writing new KeyStore to " + _keyFile + " using master password = " + new String(masterPassword) );
            writeKeyStoreToFile( _pwdStore, _keyFile, masterPassword );
        }

        //debugState( "AFTER changing master password" );

        loadKeyStore( _keyFile, getMasterPassword() );

        //debugState( "AFTER forcing reload from file" );
     
private static voidwriteKeyStoreToFile(java.security.KeyStore keyStore, java.io.File file, char[] masterPassword)
Write the KeyStore to disk. Calling code should protect against overwriting any original file.

param
keyStore
param
file
param
masterPassword

        final FileOutputStream  out = new FileOutputStream(file);
        try
        {
            keyStore.store( out, masterPassword);
        }
        finally
        {
            out.close();
        }
    
public voidwriteStore()
Writes the keystore to disk

throws
KeyStoreException
throws
IOException
throws
NoSuchAlgorithmException
throws
CertificateException

        writeKeyStoreSafe( getMasterPassword() );