Source for gnu.javax.net.ssl.provider.X509TrustManagerFactory

   1: /* X509TrustManagerFactory.java -- X.509 trust manager factory.
   2:    Copyright (C) 2006  Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.javax.net.ssl.provider;
  40: 
  41: import java.io.FileInputStream;
  42: import java.io.IOException;
  43: 
  44: import java.util.Arrays;
  45: import java.util.Enumeration;
  46: import java.util.HashSet;
  47: import java.util.LinkedList;
  48: import java.util.Set;
  49: 
  50: import java.security.AccessController;
  51: import java.security.InvalidAlgorithmParameterException;
  52: import java.security.KeyStore;
  53: import java.security.KeyStoreException;
  54: import java.security.NoSuchAlgorithmException;
  55: import java.security.cert.CertPath;
  56: import java.security.cert.CertPathValidator;
  57: import java.security.cert.CertPathValidatorException;
  58: import java.security.cert.Certificate;
  59: import java.security.cert.CertificateException;
  60: import java.security.cert.PKIXParameters;
  61: import java.security.cert.TrustAnchor;
  62: import java.security.cert.X509Certificate;
  63: 
  64: import javax.net.ssl.ManagerFactoryParameters;
  65: import javax.net.ssl.TrustManager;
  66: import javax.net.ssl.TrustManagerFactorySpi;
  67: import javax.net.ssl.X509TrustManager;
  68: 
  69: import gnu.java.security.action.GetPropertyAction;
  70: import gnu.java.security.x509.X509CertPath;
  71: import gnu.javax.net.ssl.NullManagerParameters;
  72: import gnu.javax.net.ssl.StaticTrustAnchors;
  73: 
  74: /**
  75:  * This class implements a {@link javax.net.ssl.TrustManagerFactory} engine
  76:  * for the ``JessieX509'' algorithm.
  77:  */
  78: public class X509TrustManagerFactory extends TrustManagerFactorySpi
  79: {
  80: 
  81:   // Constants and fields.
  82:   // -------------------------------------------------------------------------
  83: 
  84:   private static final String sep
  85:     = AccessController.doPrivileged(new GetPropertyAction("file.separator"));
  86: 
  87:   /**
  88:    * The location of the JSSE key store.
  89:    */
  90:   private static final String JSSE_CERTS
  91:     = AccessController.doPrivileged(new GetPropertyAction("java.home"))
  92:       + sep + "lib" + sep + "security" + sep + "jssecerts";
  93: 
  94:   /**
  95:    * The location of the system key store, containing the CA certs.
  96:    */
  97:   private static final String CA_CERTS
  98:     = AccessController.doPrivileged(new GetPropertyAction("java.home"))
  99:       + sep + "lib" + sep + "security" + sep + "cacerts";
 100: 
 101:   private Manager current;
 102: 
 103:   // Construtors.
 104:   // -------------------------------------------------------------------------
 105: 
 106:   public X509TrustManagerFactory()
 107:   {
 108:     super();
 109:   }
 110: 
 111:   // Instance methods.
 112:   // -------------------------------------------------------------------------
 113: 
 114:   protected TrustManager[] engineGetTrustManagers()
 115:   {
 116:     if (current == null)
 117:       {
 118:         throw new IllegalStateException("not initialized");
 119:       }
 120:     return new TrustManager[] { current };
 121:   }
 122: 
 123:   protected void engineInit(ManagerFactoryParameters params)
 124:     throws InvalidAlgorithmParameterException
 125:   {
 126:     if (params instanceof StaticTrustAnchors)
 127:       {
 128:         current = new Manager(((StaticTrustAnchors) params).getCertificates());
 129:       }
 130:     else if (params instanceof NullManagerParameters)
 131:       {
 132:         current = new Manager(new X509Certificate[0]);
 133:       }
 134:     else
 135:       {
 136:         throw new InvalidAlgorithmParameterException();
 137:       }
 138:   }
 139: 
 140:   protected void engineInit(KeyStore store) throws KeyStoreException
 141:   {
 142:     if (store == null)
 143:       {
 144:         GetPropertyAction gpa = new GetPropertyAction("javax.net.ssl.trustStoreType");
 145:         String s = AccessController.doPrivileged(gpa);
 146:         if (s == null)
 147:           s = KeyStore.getDefaultType();
 148:         store = KeyStore.getInstance(s);
 149:         try
 150:           {
 151:             s = AccessController.doPrivileged(gpa.setParameters("javax.net.ssl.trustStore"));
 152:             FileInputStream in = null;
 153:             if (s == null)
 154:               {
 155:                 try
 156:                   {
 157:                     in = new FileInputStream(JSSE_CERTS);
 158:                   }
 159:                 catch (IOException e)
 160:                   {
 161:                     in = new FileInputStream(CA_CERTS);
 162:                   }
 163:               }
 164:             else
 165:               {
 166:                 in = new FileInputStream(s);
 167:               }
 168:             String p = AccessController.doPrivileged(gpa.setParameters("javax.net.ssl.trustStorePassword"));
 169:             store.load(in, p != null ? p.toCharArray() : null);
 170:           }
 171:         catch (IOException ioe)
 172:           {
 173:             throw new KeyStoreException(ioe);
 174:           }
 175:         catch (CertificateException ce)
 176:           {
 177:             throw new KeyStoreException(ce);
 178:           }
 179:         catch (NoSuchAlgorithmException nsae)
 180:           {
 181:             throw new KeyStoreException(nsae);
 182:           }
 183:       }
 184: 
 185:     LinkedList<X509Certificate> l = new LinkedList<X509Certificate>();
 186:     Enumeration aliases = store.aliases();
 187:     while (aliases.hasMoreElements())
 188:       {
 189:         String alias = (String) aliases.nextElement();
 190:         if (!store.isCertificateEntry(alias))
 191:           continue;
 192:         Certificate c = store.getCertificate(alias);
 193:         if (!(c instanceof X509Certificate))
 194:           continue;
 195:         l.add((X509Certificate) c);
 196:       }
 197:     current = this.new Manager(l.toArray(new X509Certificate[l.size()]));
 198:   }
 199: 
 200:   // Inner class.
 201:   // -------------------------------------------------------------------------
 202: 
 203:   /**
 204:    * The actual manager implementation returned.
 205:    */
 206:   private class Manager implements X509TrustManager
 207:   {
 208: 
 209:     // Fields.
 210:     // -----------------------------------------------------------------------
 211: 
 212:     private final Set<TrustAnchor> anchors;
 213: 
 214:     // Constructor.
 215:     // -----------------------------------------------------------------------
 216: 
 217:     Manager(X509Certificate[] trusted)
 218:     {
 219:       anchors = new HashSet<TrustAnchor>();
 220:       if (trusted != null)
 221:         {
 222:           for (X509Certificate cert : trusted)
 223:             {
 224:               anchors.add(new TrustAnchor(cert, null));
 225:             }
 226:         }
 227:     }
 228: 
 229:     // Instance methodns.
 230:     // -----------------------------------------------------------------------
 231: 
 232:     public void checkClientTrusted(X509Certificate[] chain, String authType)
 233:       throws CertificateException
 234:     {
 235:       checkTrusted(chain, authType);
 236:     }
 237: 
 238:     public void checkServerTrusted(X509Certificate[] chain, String authType)
 239:       throws CertificateException
 240:     {
 241:       checkTrusted(chain, authType);
 242:     }
 243: 
 244:     public X509Certificate[] getAcceptedIssuers()
 245:     {
 246:       return anchors.toArray(new X509Certificate[anchors.size()]);
 247:     }
 248: 
 249:     // Own methods.
 250:     // -----------------------------------------------------------------------
 251: 
 252:     private void checkTrusted(X509Certificate[] chain, String authType)
 253:       throws CertificateException
 254:     {
 255:       CertPathValidator validator = null;
 256: 
 257:       try
 258:         {
 259:           validator = CertPathValidator.getInstance("PKIX");
 260:         }
 261:       catch (NoSuchAlgorithmException nsae)
 262:         {
 263:           throw new CertificateException(nsae);
 264:         }
 265: 
 266:       CertPath path = new X509CertPath(Arrays.asList(chain));
 267: 
 268:       PKIXParameters params = null;
 269:       try
 270:         {
 271:           params = new PKIXParameters(anchors);
 272:           // XXX we probably do want to enable revocation, but it's a pain
 273:           // in the ass.
 274:           params.setRevocationEnabled(false);
 275:         }
 276:       catch (InvalidAlgorithmParameterException iape)
 277:         {
 278:           throw new CertificateException(iape);
 279:         }
 280: 
 281:       try
 282:         {
 283:           validator.validate(path, params);
 284:         }
 285:       catch (CertPathValidatorException cpve)
 286:         {
 287:           throw new CertificateException(cpve);
 288:         }
 289:       catch (InvalidAlgorithmParameterException iape)
 290:         {
 291:           throw new CertificateException(iape);
 292:         }
 293:     }
 294:   }
 295: }