151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 230350d69719039aafc65e9c783f56b46d9d8725bSergio Giro * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.x509; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.Constructor; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.Field; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.reflect.InvocationTargetException; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.CertificateException; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.HexDumpEncoder; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.*; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class defines the Extensions attribute for the Certificate. 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Amit Kapoor 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Hemma Prafullchandra 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see CertAttrSet 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class CertificateExtensions implements CertAttrSet<Extension> { 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Identifier for this attribute, to be used with the 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * get, set, delete methods of Certificate, x509 type. 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final String IDENT = "x509.info.extensions"; 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * name 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static final String NAME = "extensions"; 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final Debug debug = Debug.getInstance("x509"); 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Map<String,Extension> map = Collections.synchronizedMap( 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new TreeMap<String,Extension>()); 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean unsupportedCritExt = false; 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Map<String,Extension> unparseableExtensions; 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Default constructor. 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public CertificateExtensions() { } 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create the object, decoding the values from the passed DER stream. 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param in the DerInputStream to read the Extension from. 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on decoding errors. 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public CertificateExtensions(DerInputStream in) throws IOException { 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski init(in); 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // helper routine 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void init(DerInputStream in) throws IOException { 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue[] exts = in.getSequence(5); 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < exts.length; i++) { 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Extension ext = new Extension(exts[i]); 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parseExtension(ext); 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Class[] PARAMS = {Boolean.class, Object.class}; 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Parse the encoded extension 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void parseExtension(Extension ext) throws IOException { 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 9730350d69719039aafc65e9c783f56b46d9d8725bSergio Giro Class<?> extClass = OIDMap.getClass(ext.getExtensionId()); 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extClass == null) { // Unsupported extension 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ext.isCritical()) { 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski unsupportedCritExt = true; 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (map.put(ext.getExtensionId().toString(), ext) == null) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Duplicate extensions not allowed"); 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10830350d69719039aafc65e9c783f56b46d9d8725bSergio Giro Constructor<?> cons = extClass.getConstructor(PARAMS); 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] passed = new Object[] {Boolean.valueOf(ext.isCritical()), 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ext.getExtensionValue()}; 11230350d69719039aafc65e9c783f56b46d9d8725bSergio Giro CertAttrSet<?> certExt = (CertAttrSet<?>) 11330350d69719039aafc65e9c783f56b46d9d8725bSergio Giro cons.newInstance(passed); 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (map.put(certExt.getName(), (Extension)certExt) != null) { 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Duplicate extensions not allowed"); 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (InvocationTargetException invk) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Throwable e = invk.getTargetException(); 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (ext.isCritical() == false) { 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // ignore errors parsing non-critical extensions 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (unparseableExtensions == null) { 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski unparseableExtensions = new TreeMap<String,Extension>(); 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski unparseableExtensions.put(ext.getExtensionId().toString(), 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new UnparseableExtension(ext, e)); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (debug != null) { 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debug.println("Error parsing extension: " + ext); 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski e.printStackTrace(); 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski HexDumpEncoder h = new HexDumpEncoder(); 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.err.println(h.encodeBuffer(ext.getExtensionValue())); 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (e instanceof IOException) { 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw (IOException)e; 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 13730350d69719039aafc65e9c783f56b46d9d8725bSergio Giro throw new IOException(e); 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException e) { 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw e; 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 14230350d69719039aafc65e9c783f56b46d9d8725bSergio Giro throw new IOException(e); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the extensions in DER form to the stream, setting 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the context specific tag as needed in the X.509 v3 certificate. 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param out the DerOutputStream to marshal the contents to. 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception CertificateException on encoding errors. 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on errors. 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encode(OutputStream out) 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws CertificateException, IOException { 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encode(out, false); 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Encode the extensions in DER form to the stream. 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param out the DerOutputStream to marshal the contents to. 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param isCertReq if true then no context specific tag is added. 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception CertificateException on encoding errors. 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on errors. 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void encode(OutputStream out, boolean isCertReq) 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws CertificateException, IOException { 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream extOut = new DerOutputStream(); 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Collection<Extension> allExts = map.values(); 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] objs = allExts.toArray(); 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < objs.length; i++) { 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (objs[i] instanceof CertAttrSet) 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((CertAttrSet)objs[i]).encode(extOut); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else if (objs[i] instanceof Extension) 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((Extension)objs[i]).encode(extOut); 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new CertificateException("Illegal extension object"); 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream seq = new DerOutputStream(); 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski seq.write(DerValue.tag_Sequence, extOut); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerOutputStream tmp; 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isCertReq) { // certificate 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp = new DerOutputStream(); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)3), 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski seq); 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp = seq; // pkcs#10 certificateRequest 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.write(tmp.toByteArray()); 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Set the attribute value. 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the extension name used in the cache. 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param obj the object to set. 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if the object could not be cached. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void set(String name, Object obj) throws IOException { 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj instanceof Extension) { 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski map.put(name, (Extension)obj); 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Unknown extension type."); 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get the attribute value. 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the extension name used in the lookup. 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if named extension is not found. 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21530350d69719039aafc65e9c783f56b46d9d8725bSergio Giro public Extension get(String name) throws IOException { 21630350d69719039aafc65e9c783f56b46d9d8725bSergio Giro Extension obj = map.get(name); 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj == null) { 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("No extension found with name " + name); 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (obj); 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Similar to get(String), but throw no exception, might return null. 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Used in X509CertImpl::getExtension(OID). 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Extension getExtension(String name) { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return map.get(name); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Delete the attribute value. 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the extension name used in the lookup. 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException if named extension is not found. 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void delete(String name) throws IOException { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object obj = map.get(name); 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (obj == null) { 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("No extension found with name " + name); 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski map.remove(name); 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getNameByOid(ObjectIdentifier oid) throws IOException { 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String name: map.keySet()) { 24430350d69719039aafc65e9c783f56b46d9d8725bSergio Giro if (map.get(name).getExtensionId().equals((Object)oid)) { 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return name; 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return an enumeration of names of attributes existing within this 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * attribute. 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Enumeration<Extension> getElements() { 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Collections.enumeration(map.values()); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a collection view of the extensions. 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a collection view of the extensions in this Certificate. 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Collection<Extension> getAllExtensions() { 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return map.values(); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Map<String,Extension> getUnparseableExtensions() { 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (unparseableExtensions == null) { 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Collections.emptyMap(); 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return unparseableExtensions; 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the name of this attribute. 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getName() { 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return NAME; 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return true if a critical extension is found that is 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not supported, otherwise return false. 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean hasUnsupportedCriticalExtension() { 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return unsupportedCritExt; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Compares this CertificateExtensions for equality with the specified 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object. If the <code>other</code> object is an 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>instanceof</code> <code>CertificateExtensions</code>, then 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * all the entries are compared with the entries from this. 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param other the object to test for equality with this 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * CertificateExtensions. 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true iff all the entries match that of the Other, 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * false otherwise. 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean equals(Object other) { 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (this == other) 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(other instanceof CertificateExtensions)) 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Collection<Extension> otherC = 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((CertificateExtensions)other).getAllExtensions(); 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Object[] objs = otherC.toArray(); 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = objs.length; 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len != map.size()) 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Extension otherExt, thisExt; 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String key = null; 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < len; i++) { 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (objs[i] instanceof CertAttrSet) 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski key = ((CertAttrSet)objs[i]).getName(); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski otherExt = (Extension)objs[i]; 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (key == null) 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski key = otherExt.getExtensionId().toString(); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski thisExt = map.get(key); 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (thisExt == null) 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (! thisExt.equals(otherExt)) 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this.getUnparseableExtensions().equals( 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ((CertificateExtensions)other).getUnparseableExtensions()); 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a hashcode value for this CertificateExtensions. 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the hashcode value. 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int hashCode() { 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return map.hashCode() + getUnparseableExtensions().hashCode(); 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a string representation of this <tt>CertificateExtensions</tt> 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * object in the form of a set of entries, enclosed in braces and separated 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by the ASCII characters "<tt>, </tt>" (comma and space). 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Overrides to <tt>toString</tt> method of <tt>Object</tt>. 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a string representation of this CertificateExtensions. 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return map.toString(); 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass UnparseableExtension extends Extension { 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String name; 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Throwable why; 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public UnparseableExtension(Extension ext, Throwable why) { 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super(ext); 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski name = ""; 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 36430350d69719039aafc65e9c783f56b46d9d8725bSergio Giro Class<?> extClass = OIDMap.getClass(ext.getExtensionId()); 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (extClass != null) { 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Field field = extClass.getDeclaredField("NAME"); 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski name = (String)(field.get(null)) + " "; 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If we cannot find the name, just ignore it 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.why = why; 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override public String toString() { 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return super.toString() + 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "Unparseable " + name + "extension due to\n" + why + "\n\n" + 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new sun.misc.HexDumpEncoder().encodeBuffer(getExtensionValue()); 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 382