Package com.sun.appserv.management.client

Source Code of com.sun.appserv.management.client.TrustStoreTrustManager

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.appserv.management.client;

import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.util.Date;
import java.text.DateFormat;

import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;

import javax.net.ssl.X509TrustManager;

import com.sun.appserv.management.util.misc.LineReaderImpl;


/**
  This X509TrustManager implementation supports a trust-store file and allows
  adding new certificates to it.  It is designed to allow a subclass to
  override a variety of protected methods including those of TrustManager:
  <ul>
  <li>checkClientTrusted</li>
  <li>checkServerTrusted</li>
  <li>getAcceptedIssuers</li>
  </ul>
 
  as well as:
 
  <ul>
  <li>#checkCertificate</li>
  <li>#getTrustStorePassword</li>
  <li>#shouldAddToTrustStore</li>
  <li>#askShouldAddToTrustStore</li>
  <li>#getCertificateAlias</li>
  <li>#addCertificateToTrustStore</li>
  <li>#writeStore</li>
  <li>#certificateNotInTrustStore</li>
  <li>#getTrustStore</li>
  </ul>
  <p>
  For convenience, if setPrompt( true ) is called, then when a new Certificate
  is encountered, askShouldAddToTrustStore( c ) prompts the user
  via System.in as to whether to accept this new Certificate as trusted.
  Subclasses can of course override this behavior any any desired way.
*/
public class TrustStoreTrustManager
  implements X509TrustManager // do NOT make Serializable
{
  private final File    mTrustStoreFile;
  private final char[]  mTrustStorePassword;
  private final String  mKeyStoreType;
  private KeyStore    mTrustStore;
  private boolean      mPrompt;
 
  /**
    Create a new instance with the specified File and password
    The trustStoreFile must exist.
   
    @param trustStoreFile    (not required to exist)
    @param keyStoreType    keystore (truststore) type, eg "JKS"
    @param trustStorePassword (may be null)
   */
    public
  TrustStoreTrustManager(
    final File    trustStoreFile,
    final String  keyStoreType,
    final char[]  trustStorePassword )
  {
    if ( trustStoreFile == null || keyStoreType == null )
    {
      throw new IllegalArgumentException();
    }
   
    mTrustStoreFile    = trustStoreFile;
    mKeyStoreType    = keyStoreType;
    mTrustStorePassword  = trustStorePassword;
    mTrustStore      = null;
    mPrompt        = false;
   
    try
    {
      getTrustStore()// force initialization now
    }
    catch( Exception e )
    {
      throw new RuntimeException( e );
    }
  }
 
  /**
    calls this( trustStoreFile,"JKS", trustStorePassword )
   */
    public
  TrustStoreTrustManager(
    final File    trustStoreFile,
    final char[]  trustStorePassword )
  {
    this( trustStoreFile, "JKS", trustStorePassword );
  }
 
  /**
    If set to true, then when a new Certificate is encountered, the user
    will be prompted via System.in as to whether it should be trusted.
   
    @param prompt
   */
    public void
  setPrompt( final boolean prompt )
  {
    mPrompt  = prompt;
  }
 
  /**
    Create an instance using the system trust-store as returned by
    getSystemTrustStoreFile().
   
    @return an instance or null if not possible
   */
    public static TrustStoreTrustManager
  getSystemInstance()
  {
      final File    trustStore      = getSystemTrustStoreFile();
      final char[]  trustStorePassword  = getSystemTrustStorePassword();
     
      TrustStoreTrustManager  mgr  = null;
     
      if ( trustStore != null && trustStorePassword != null )
      {
        return( new TrustStoreTrustManager( trustStore, trustStorePassword ) );
      }
     
      return( mgr );
  }
 
    private static char[]
  toCharArray( final String s )
  {
    return( s == null ? null : s.toCharArray() );
  }
 
 
  /**
    Standard system property denoting the trust-store.
   */
  public static final String  TRUSTSTORE_FILE_SPROP  = "javax.net.ssl.trustStore";
 
  /**
    Standard system property denoting the trust-store password.
   */
  public static final String  TRUSTSTORE_PASSWORD_SPROP= "javax.net.ssl.trustStorePassword";
 
  /**
    Use System.getProperty( "javax.net.ssl.trustStore" ) to find a trust-store.
   */
    public static File
  getSystemTrustStoreFile()
  {
    final String  prop  = System.getProperty( TRUSTSTORE_FILE_SPROP );
    final File trustStore  = prop == null ? null : new File( prop );
    return( trustStore );
  }
 
  /**
    Use System.getProperty( "javax.net.ssl.trustStorePassword" ) to find the
    trust-store password.
   */
    public static char[]
  getSystemTrustStorePassword()
  {
    return( toCharArray( System.getProperty( TRUSTSTORE_PASSWORD_SPROP ) ) );
  }
   
 
  /**
    Return the trust-store that was initially passed in.
   
    @return File
   */
    public final File
  getTrustStoreFile()
  {
    return( mTrustStoreFile );
  }
 
  /**
    Subclass may choose to override this method to get the password from any
    desired source.  Otherwise, the password used to create this instance is
    returned.
   
    @return char[]
   */
    protected char[]
  getTrustStorePassword()
  {
    return( mTrustStorePassword );
  }
 
    public void
  checkClientTrusted( X509Certificate[] chain, String authType)
    throws CertificateException
  {
    throw new UnsupportedOperationException( "checkClientTrusted() not supported" );
  }
 
    public void
  checkServerTrusted( X509Certificate[] chain, String authType)
    throws CertificateException
  {
    if (chain == null || chain.length == 0)
    {
      throw new IllegalArgumentException();
        }
       
    checkCertificate(chain);
  }
 
  /**
    By default, no issuers are trusted. It is better to trust specific
    Certificates explicitly.
   
    @return X509Certificate[]
   */
    public X509Certificate[]
  getAcceptedIssuers()
  {
    // none, by default
    return( new X509Certificate[ 0 ] );
  }
 
  /**
    Prompts via System.in to ask whether the Certificate should be added.
   
    @param c
    @return true if the response is yes.
   */
    protected boolean
  askShouldAddToTrustStore( final Certificate c )
    throws IOException
  {
    final LineReaderImpl  reader  = new LineReaderImpl( System.in );
   
    final String prompt  = c.toString() +
      "\n\nAdd the above certificate to the truststore [y/n]?";
     
    final String result  = reader.readLine( prompt );
   
    return( result.equalsIgnoreCase( "y" ) || result.equalsIgnoreCase( "yes" ) );
  }
 
  /**
    Subclass may wish to override this routine and call defaultShouldAddToTrustStore( c );
   
    @param c
    @return true if the Certificate should be trusted and added to the trust-store
   */
    protected boolean
  shouldAddToTrustStore( final Certificate c )
    throws IOException
  {
    return( mPrompt ? askShouldAddToTrustStore( c ) : false );
  }
 
  /**
    Return an alias for a Certificate to be added to the TrustStore.
    @param c
    @return an alias to be used for adding the Certificate to the trust-store
   */
    protected String
  getCertificateAlias( final Certificate c )
  {
        final DateFormat f = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);    
       
    return( "cert" +  f.format( new Date() ) );
  }
 
 
  /**
    Add the Certificate with the specified alias to the trust-store.
   
    @param alias
    @param c
   */
    protected void
  addCertificateToTrustStore(
    final String    alias,
    final Certificate  c )
    throws IOException,
    KeyStoreException, NoSuchAlgorithmException, CertificateException
  {
        mTrustStore.setCertificateEntry( alias, c );
         writeStore();
  }
 
 
  /**
    Add the Certificate to the trust-store, using the alias returned by
    getCertificateAlias( c ).
   
    @param c
   */
    protected void
  addCertificateToTrustStore( final Certificate c )
    throws IOException,
    KeyStoreException, NoSuchAlgorithmException, CertificateException
  {
        final String aliasName = getCertificateAlias( c );
       
        addCertificateToTrustStore( aliasName, c );
  }
 
    private void
  writeStore(
    final KeyStore  trustStore,
    final char[]  trustStorePassword,
    final File    f )
    throws IOException,
    KeyStoreException, NoSuchAlgorithmException, CertificateException
 
    FileOutputStream  out  = new FileOutputStream( f );
     
    try
    {
      trustStore.store( out, trustStorePassword );
    }
    catch( Throwable t )
    {
      t.printStackTrace();
    }
    finally
    {
      out.close();
    }
    }   
   
  /**
    Write the store to disk.  Results are undefined if an error occurs while
    writing the file.
   */
    protected void
  writeStore()
    throws IOException,
    KeyStoreException, NoSuchAlgorithmException, CertificateException
 
    writeStore( getTrustStore(), getTrustStorePassword(), getTrustStoreFile() );
      // NOTE: any exception thrown from here is squelched by calling JDK code
      // if in the middle of a SSL negotiation
    }   
   
 
  /**
    The Certificate is not found in the trust-store.
    If shouldAddToTrustStore( c ) returns false, then a CertificateException
    is thrown.  Otherwise, addCertificateToTrustStore( c ) is called.
   
    @param c
   */
    protected void
  certificateNotInTrustStore( final Certificate c )
    throws IOException,
    KeyStoreException, NoSuchAlgorithmException, CertificateException
  {
        if ( shouldAddToTrustStore( c ) )
        {
          addCertificateToTrustStore( c );
        }
        else
        {
            throw new CertificateException( "Certificate not trusted:\n" + c );
        }
  }
 
    private void
  createTrustStoreFile(
    final KeyStore  keyStore,
    final char[]  pw,
    final File     f )
    throws IOException,
      CertificateException, NoSuchAlgorithmException,
      KeyStoreException, FileNotFoundException
  {
    f.createNewFile();
    writeStore( keyStore, pw, f );
  }

  /**
    Get the KeyStore containing the Certificates to be trusted.  This should
    be a KeyStore corresponding to the file that was specified.  The same
    KeyStore should be returned each time.
   
    @return KeyStore
   */
    protected synchronized KeyStore
  getTrustStore()
    throws IOException,
      CertificateException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException
  {
    if ( mTrustStore == null )
    {
      mTrustStore  = KeyStore.getInstance( mKeyStoreType );
      final File  f  = getTrustStoreFile();
      final char[]  pw  = getTrustStorePassword();
      if ( (! f.exists()) || f.length() == 0 )
      {
        f.delete();
        mTrustStore.load( null, pw );
        createTrustStoreFile( mTrustStore, pw, f);
      }
      else
      {
        final FileInputStream is  = new FileInputStream( f );
        try
        {
          mTrustStore.load( is, pw );
        }
        finally
        {
          is.close();
        }
      }
    }
   
    return( mTrustStore );
  }
 
  /**
       @param chain
       @throws RuntimeException
       @throws CertificateException
     */   
    protected void
  checkCertificate( final X509Certificate[] chain)
    throws RuntimeException, CertificateException
    {
    try
    {
            //First ensure that the certificate is valid.
            for (int i = 0 ; i < chain.length ; i ++)
            {
                chain[i].checkValidity();  
            }
           
            mTrustStore  = getTrustStore();
           
            final Certificate  cert  = chain[ 0 ];
           
            //if the certificate already exists in the truststore, it is implicitly trusted
            if ( mTrustStore.getCertificateAlias( cert ) == null )
            {
              certificateNotInTrustStore( cert );
            }
        }
        catch (CertificateException e)
        {
            throw e;
        }
        catch (Exception e)
        {       
      throw new RuntimeException( e );
    }
  }

 
    public String
  toString()
  {
    return( "TrustStoreTrustManager--trusts certificates found in truststore: " + mTrustStore );
  }
}


TOP

Related Classes of com.sun.appserv.management.client.TrustStoreTrustManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.