Source for gnu.java.security.provider.X509CertificateFactory

   1: /* X509CertificateFactory.java -- generates X.509 certificates.
   2:    Copyright (C) 2003 Free Software Foundation, Inc.
   3: 
   4: This file is 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, or (at your option)
   9: 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; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 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.java.security.provider;
  40: 
  41: import gnu.java.io.Base64InputStream;
  42: import gnu.java.security.x509.X509CRL;
  43: import gnu.java.security.x509.X509CertPath;
  44: import gnu.java.security.x509.X509Certificate;
  45: 
  46: import java.io.BufferedInputStream;
  47: import java.io.EOFException;
  48: import java.io.IOException;
  49: import java.io.InputStream;
  50: import java.security.cert.CRL;
  51: import java.security.cert.CRLException;
  52: import java.security.cert.CertPath;
  53: import java.security.cert.Certificate;
  54: import java.security.cert.CertificateEncodingException;
  55: import java.security.cert.CertificateException;
  56: import java.security.cert.CertificateFactorySpi;
  57: import java.util.Collection;
  58: import java.util.Iterator;
  59: import java.util.LinkedList;
  60: import java.util.List;
  61: 
  62: public class X509CertificateFactory
  63:     extends CertificateFactorySpi
  64: {
  65:   public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
  66: 
  67:   public static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
  68: 
  69:   public static final String BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
  70: 
  71:   public static final String END_X509_CRL = "-----END X509 CRL-----";
  72: 
  73:   public X509CertificateFactory()
  74:   {
  75:     super();
  76:   }
  77: 
  78:   public Certificate engineGenerateCertificate(InputStream inStream)
  79:       throws CertificateException
  80:   {
  81:     try
  82:       {
  83:         return generateCert(inStream);
  84:       }
  85:     catch (IOException ioe)
  86:       {
  87:         CertificateException ce = new CertificateException(ioe.getMessage());
  88:         ce.initCause(ioe);
  89:         throw ce;
  90:       }
  91:   }
  92: 
  93:   public Collection engineGenerateCertificates(InputStream inStream)
  94:       throws CertificateException
  95:   {
  96:     LinkedList certs = new LinkedList();
  97:     while (true)
  98:       {
  99:         try
 100:           {
 101:             certs.add(generateCert(inStream));
 102:           }
 103:         catch (EOFException eof)
 104:           {
 105:             break;
 106:           }
 107:         catch (IOException ioe)
 108:           {
 109:             CertificateException ce = new CertificateException(ioe.getMessage());
 110:             ce.initCause(ioe);
 111:             throw ce;
 112:           }
 113:       }
 114:     return certs;
 115:   }
 116: 
 117:   public CRL engineGenerateCRL(InputStream inStream) throws CRLException
 118:   {
 119:     try
 120:       {
 121:         return generateCRL(inStream);
 122:       }
 123:     catch (IOException ioe)
 124:       {
 125:         CRLException crle = new CRLException(ioe.getMessage());
 126:         crle.initCause(ioe);
 127:         throw crle;
 128:       }
 129:   }
 130: 
 131:   public Collection engineGenerateCRLs(InputStream inStream)
 132:       throws CRLException
 133:   {
 134:     LinkedList crls = new LinkedList();
 135:     while (true)
 136:       {
 137:         try
 138:           {
 139:             crls.add(generateCRL(inStream));
 140:           }
 141:         catch (EOFException eof)
 142:           {
 143:             break;
 144:           }
 145:         catch (IOException ioe)
 146:           {
 147:             CRLException crle = new CRLException(ioe.getMessage());
 148:             crle.initCause(ioe);
 149:             throw crle;
 150:           }
 151:       }
 152:     return crls;
 153:   }
 154: 
 155:   public CertPath engineGenerateCertPath(List certs)
 156:   {
 157:     return new X509CertPath(certs);
 158:   }
 159: 
 160:   public CertPath engineGenerateCertPath(InputStream in)
 161:       throws CertificateEncodingException
 162:   {
 163:     return new X509CertPath(in);
 164:   }
 165: 
 166:   public CertPath engineGenerateCertPath(InputStream in, String encoding)
 167:       throws CertificateEncodingException
 168:   {
 169:     return new X509CertPath(in, encoding);
 170:   }
 171: 
 172:   public Iterator engineGetCertPathEncodings()
 173:   {
 174:     return X509CertPath.ENCODINGS.iterator();
 175:   }
 176: 
 177:   private X509Certificate generateCert(InputStream inStream)
 178:       throws IOException, CertificateException
 179:   {
 180:     if (inStream == null)
 181:       throw new CertificateException("missing input stream");
 182:     if (! inStream.markSupported())
 183:       inStream = new BufferedInputStream(inStream, 8192);
 184:     inStream.mark(20);
 185:     int i = inStream.read();
 186:     if (i == -1)
 187:       throw new EOFException();
 188:     // If the input is in binary DER format, the first byte MUST be
 189:     // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
 190:     // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
 191:     //
 192:     // So if we do not see 0x30 here we will assume it is in Base-64.
 193:     if (i != 0x30)
 194:       {
 195:         inStream.reset();
 196:         StringBuffer line = new StringBuffer(80);
 197:         do
 198:           {
 199:             line.setLength(0);
 200:             do
 201:               {
 202:                 i = inStream.read();
 203:                 if (i == -1)
 204:                   throw new EOFException();
 205:                 if (i != '\n' && i != '\r')
 206:                   line.append((char) i);
 207:               }
 208:             while (i != '\n' && i != '\r');
 209:           }
 210:         while (! line.toString().equals(BEGIN_CERTIFICATE));
 211:         X509Certificate ret = new X509Certificate(
 212:             new BufferedInputStream(new Base64InputStream(inStream), 8192));
 213:         line.setLength(0);
 214:         line.append('-'); // Base64InputStream will eat this.
 215:         do
 216:           {
 217:             i = inStream.read();
 218:             if (i == -1)
 219:               throw new EOFException();
 220:             if (i != '\n' && i != '\r')
 221:               line.append((char) i);
 222:           }
 223:         while (i != '\n' && i != '\r');
 224:         // XXX ???
 225:         if (! line.toString().equals(END_CERTIFICATE))
 226:           throw new CertificateException("no end-of-certificate marker");
 227:         return ret;
 228:       }
 229:     else
 230:       {
 231:         inStream.reset();
 232:         return new X509Certificate(inStream);
 233:       }
 234:   }
 235: 
 236:   private X509CRL generateCRL(InputStream inStream) throws IOException,
 237:       CRLException
 238:   {
 239:     if (inStream == null)
 240:       throw new CRLException("missing input stream");
 241:     if (! inStream.markSupported())
 242:       inStream = new BufferedInputStream(inStream, 8192);
 243:     inStream.mark(20);
 244:     int i = inStream.read();
 245:     if (i == -1)
 246:       throw new EOFException();
 247:     // If the input is in binary DER format, the first byte MUST be
 248:     // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
 249:     // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
 250:     //
 251:     // So if we do not see 0x30 here we will assume it is in Base-64.
 252:     if (i != 0x30)
 253:       {
 254:         inStream.reset();
 255:         StringBuffer line = new StringBuffer(80);
 256:         do
 257:           {
 258:             line.setLength(0);
 259:             do
 260:               {
 261:                 i = inStream.read();
 262:                 if (i == -1)
 263:                   throw new EOFException();
 264:                 if (i != '\n' && i != '\r')
 265:                   line.append((char) i);
 266:               }
 267:             while (i != '\n' && i != '\r');
 268:           }
 269:         while (! line.toString().startsWith(BEGIN_X509_CRL));
 270:         X509CRL ret = new X509CRL(
 271:             new BufferedInputStream(new Base64InputStream(inStream), 8192));
 272:         line.setLength(0);
 273:         line.append('-'); // Base64InputStream will eat this.
 274:         do
 275:           {
 276:             i = inStream.read();
 277:             if (i == -1)
 278:               throw new EOFException();
 279:             if (i != '\n' && i != '\r')
 280:               line.append((char) i);
 281:           }
 282:         while (i != '\n' && i != '\r');
 283:         // XXX ???
 284:         if (! line.toString().startsWith(END_X509_CRL))
 285:           throw new CRLException("no end-of-CRL marker");
 286:         return ret;
 287:       }
 288:     else
 289:       {
 290:         inStream.reset();
 291:         return new X509CRL(inStream);
 292:       }
 293:   }
 294: }