6890876: jarsigner can add CRL info into signed jar
Reviewed-by: mullan
This commit is contained in:
parent
a94d06f6b7
commit
7c6813eb7a
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,9 @@
|
||||
package com.sun.jarsigner;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.cert.X509CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
@ -80,6 +82,13 @@ public interface ContentSignerParameters {
|
||||
*/
|
||||
public X509Certificate[] getSignerCertificateChain();
|
||||
|
||||
/**
|
||||
* Retrieves the signer's X.509 CRLs.
|
||||
*
|
||||
* @return An unmodifiable set of X.509 CRLs (never <code>null</code>)
|
||||
*/
|
||||
public Set<X509CRL> getCRLs();
|
||||
|
||||
/**
|
||||
* Retrieves the content that was signed.
|
||||
* The content is the JAR file's signature file.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,10 @@
|
||||
package java.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.cert.CRL;
|
||||
import java.security.cert.CertPath;
|
||||
import sun.misc.JavaSecurityCodeSignerAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* This class encapsulates information about a code signer.
|
||||
@ -163,4 +166,43 @@ public final class CodeSigner implements Serializable {
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// A private attribute attached to this CodeSigner object. Can be accessed
|
||||
// through SharedSecrets.getJavaSecurityCodeSignerAccess().[g|s]etCRLs
|
||||
//
|
||||
// Currently called in SignatureFileVerifier.getSigners
|
||||
private transient CRL[] crls;
|
||||
|
||||
/**
|
||||
* Sets the CRLs attached
|
||||
* @param crls, null to clear
|
||||
*/
|
||||
void setCRLs(CRL[] crls) {
|
||||
this.crls = crls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CRLs attached
|
||||
* @return the crls, initially null
|
||||
*/
|
||||
CRL[] getCRLs() {
|
||||
return crls;
|
||||
}
|
||||
|
||||
// Set up JavaSecurityCodeSignerAccess in SharedSecrets
|
||||
static {
|
||||
SharedSecrets.setJavaSecurityCodeSignerAccess(
|
||||
new JavaSecurityCodeSignerAccess() {
|
||||
@Override
|
||||
public void setCRLs(CodeSigner signer, CRL[] crls) {
|
||||
signer.setCRLs(crls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CRL[] getCRLs(CodeSigner signer) {
|
||||
return signer.getCRLs();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ package java.util.jar;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
package sun.misc;
|
||||
|
||||
import java.security.CodeSigner;
|
||||
import java.security.cert.CRL;
|
||||
|
||||
public interface JavaSecurityCodeSignerAccess {
|
||||
void setCRLs(CodeSigner signer, CRL[] crls);
|
||||
CRL[] getCRLs(CodeSigner signer);
|
||||
}
|
@ -27,8 +27,8 @@ package sun.misc;
|
||||
|
||||
import java.util.jar.JarFile;
|
||||
import java.io.Console;
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.security.CodeSigner;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
/** A repository of "shared secrets", which are a mechanism for
|
||||
@ -49,6 +49,7 @@ public class SharedSecrets {
|
||||
private static JavaNioAccess javaNioAccess;
|
||||
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
||||
private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
|
||||
private static JavaSecurityCodeSignerAccess javaSecurityCodeSignerAccess;
|
||||
|
||||
public static JavaUtilJarAccess javaUtilJarAccess() {
|
||||
if (javaUtilJarAccess == null) {
|
||||
@ -126,4 +127,16 @@ public class SharedSecrets {
|
||||
unsafe.ensureClassInitialized(ProtectionDomain.class);
|
||||
return javaSecurityProtectionDomainAccess;
|
||||
}
|
||||
|
||||
public static void setJavaSecurityCodeSignerAccess
|
||||
(JavaSecurityCodeSignerAccess jscsa) {
|
||||
javaSecurityCodeSignerAccess = jscsa;
|
||||
}
|
||||
|
||||
public static JavaSecurityCodeSignerAccess
|
||||
getJavaSecurityCodeSignerAccess() {
|
||||
if (javaSecurityCodeSignerAccess == null)
|
||||
unsafe.ensureClassInitialized(CodeSigner.class);
|
||||
return javaSecurityCodeSignerAccess;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1996-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@ package sun.security.pkcs;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509CRL;
|
||||
@ -173,20 +172,30 @@ public class PKCS7 {
|
||||
* @param digestAlgorithmIds the message digest algorithm identifiers.
|
||||
* @param contentInfo the content information.
|
||||
* @param certificates an array of X.509 certificates.
|
||||
* @param crls an array of CRLs
|
||||
* @param signerInfos an array of signer information.
|
||||
*/
|
||||
public PKCS7(AlgorithmId[] digestAlgorithmIds,
|
||||
ContentInfo contentInfo,
|
||||
X509Certificate[] certificates,
|
||||
X509CRL[] crls,
|
||||
SignerInfo[] signerInfos) {
|
||||
|
||||
version = BigInteger.ONE;
|
||||
this.digestAlgorithmIds = digestAlgorithmIds;
|
||||
this.contentInfo = contentInfo;
|
||||
this.certificates = certificates;
|
||||
this.crls = crls;
|
||||
this.signerInfos = signerInfos;
|
||||
}
|
||||
|
||||
public PKCS7(AlgorithmId[] digestAlgorithmIds,
|
||||
ContentInfo contentInfo,
|
||||
X509Certificate[] certificates,
|
||||
SignerInfo[] signerInfos) {
|
||||
this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos);
|
||||
}
|
||||
|
||||
private void parseNetscapeCertChain(DerValue val)
|
||||
throws ParsingException, IOException {
|
||||
DerInputStream dis = new DerInputStream(val.toByteArray());
|
||||
@ -312,7 +321,7 @@ public class PKCS7 {
|
||||
ByteArrayInputStream bais = null;
|
||||
try {
|
||||
if (certfac == null)
|
||||
crls[i] = (X509CRL) new X509CRLImpl(crlVals[i]);
|
||||
crls[i] = new X509CRLImpl(crlVals[i]);
|
||||
else {
|
||||
byte[] encoded = crlVals[i].toByteArray();
|
||||
bais = new ByteArrayInputStream(encoded);
|
||||
@ -480,7 +489,30 @@ public class PKCS7 {
|
||||
signedData.putOrderedSetOf((byte)0xA0, implCerts);
|
||||
}
|
||||
|
||||
// no crls (OPTIONAL field)
|
||||
// CRLs (optional)
|
||||
if (crls != null && crls.length != 0) {
|
||||
// cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder
|
||||
Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length);
|
||||
for (X509CRL crl: crls) {
|
||||
if (crl instanceof X509CRLImpl)
|
||||
implCRLs.add((X509CRLImpl) crl);
|
||||
else {
|
||||
try {
|
||||
byte[] encoded = crl.getEncoded();
|
||||
implCRLs.add(new X509CRLImpl(encoded));
|
||||
} catch (CRLException ce) {
|
||||
IOException ie = new IOException(ce.getMessage());
|
||||
ie.initCause(ce);
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the CRL set (tagged with [1] IMPLICIT)
|
||||
// to the signed data
|
||||
signedData.putOrderedSetOf((byte)0xA1,
|
||||
implCRLs.toArray(new X509CRLImpl[implCRLs.size()]));
|
||||
}
|
||||
|
||||
// signerInfos
|
||||
signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos);
|
||||
|
@ -26,6 +26,7 @@
|
||||
package sun.security.tools;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.cert.X509CRL;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.util.jar.*;
|
||||
@ -35,6 +36,7 @@ import java.net.URISyntaxException;
|
||||
import java.text.Collator;
|
||||
import java.text.MessageFormat;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.*;
|
||||
@ -56,6 +58,7 @@ import java.util.Map.Entry;
|
||||
import sun.security.x509.*;
|
||||
import sun.security.util.*;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
|
||||
/**
|
||||
@ -114,14 +117,16 @@ public class JarSigner {
|
||||
static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
|
||||
|
||||
X509Certificate[] certChain; // signer's cert chain (when composing)
|
||||
Set<X509CRL> crls; // signer provided CRLs
|
||||
PrivateKey privateKey; // private key
|
||||
KeyStore store; // the keystore specified by -keystore
|
||||
// or the default keystore, never null
|
||||
|
||||
String keystore; // key store file
|
||||
List<String> crlfiles = new ArrayList<String>(); // CRL files to add
|
||||
boolean nullStream = false; // null keystore input stream (NONE)
|
||||
boolean token = false; // token-based keystore
|
||||
String jarfile; // jar file to sign or verify
|
||||
String jarfile; // jar files to sign or verify
|
||||
String alias; // alias to sign jar with
|
||||
List<String> ckaliases = new ArrayList<String>(); // aliases in -verify
|
||||
char[] storepass; // keystore password
|
||||
@ -146,6 +151,7 @@ public class JarSigner {
|
||||
boolean signManifest = true; // "sign" the whole manifest
|
||||
boolean externalSF = true; // leave the .SF out of the PKCS7 block
|
||||
boolean strict = false; // treat warnings as error
|
||||
boolean autoCRL = false; // Automatcially add CRL defined in cert
|
||||
|
||||
// read zip entry raw bytes
|
||||
private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
|
||||
@ -226,6 +232,29 @@ public class JarSigner {
|
||||
} else {
|
||||
loadKeyStore(keystore, true);
|
||||
getAliasInfo(alias);
|
||||
crls = new HashSet<X509CRL>();
|
||||
if (crlfiles.size() > 0 || autoCRL) {
|
||||
CertificateFactory fac =
|
||||
CertificateFactory.getInstance("X509");
|
||||
List<CRL> list = new ArrayList<CRL>();
|
||||
for (String file: crlfiles) {
|
||||
Collection<? extends CRL> tmp = KeyTool.loadCRLs(file);
|
||||
for (CRL crl: tmp) {
|
||||
if (crl instanceof X509CRL) {
|
||||
crls.add((X509CRL)crl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (autoCRL) {
|
||||
List<CRL> crlsFromCert =
|
||||
KeyTool.readCRLsFromCert(certChain[0]);
|
||||
for (CRL crl: crlsFromCert) {
|
||||
if (crl instanceof X509CRL) {
|
||||
crls.add((X509CRL)crl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load the alternative signing mechanism
|
||||
if (altSignerClass != null) {
|
||||
@ -367,6 +396,13 @@ public class JarSigner {
|
||||
} else if (collator.compare(flags, "-digestalg") ==0) {
|
||||
if (++n == args.length) usageNoArg();
|
||||
digestalg = args[n];
|
||||
} else if (collator.compare(flags, "-crl") ==0) {
|
||||
if ("auto".equals(modifier)) {
|
||||
autoCRL = true;
|
||||
} else {
|
||||
if (++n == args.length) usageNoArg();
|
||||
crlfiles.add(args[n]);
|
||||
}
|
||||
} else if (collator.compare(flags, "-certs") ==0) {
|
||||
showcerts = true;
|
||||
} else if (collator.compare(flags, "-strict") ==0) {
|
||||
@ -515,6 +551,9 @@ public class JarSigner {
|
||||
System.out.println(rb.getString
|
||||
("[-sigalg <algorithm>] name of signature algorithm"));
|
||||
System.out.println();
|
||||
System.out.println(rb.getString
|
||||
("[-crl[:auto| <file>] include CRL in signed jar"));
|
||||
System.out.println();
|
||||
System.out.println(rb.getString
|
||||
("[-verify] verify a signed JAR file"));
|
||||
System.out.println();
|
||||
@ -654,6 +693,20 @@ public class JarSigner {
|
||||
if (showcerts) {
|
||||
sb.append(si);
|
||||
sb.append('\n');
|
||||
CRL[] crls = SharedSecrets
|
||||
.getJavaSecurityCodeSignerAccess()
|
||||
.getCRLs(signer);
|
||||
if (crls != null) {
|
||||
for (CRL crl: crls) {
|
||||
if (crl instanceof X509CRLImpl) {
|
||||
sb.append(tab).append("[");
|
||||
sb.append(String.format(
|
||||
rb.getString("with a CRL including %d entries"),
|
||||
((X509CRLImpl)crl).getRevokedCertificates().size()))
|
||||
.append("]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (showcerts && !verbose.equals("all")) {
|
||||
@ -1233,7 +1286,7 @@ public class JarSigner {
|
||||
|
||||
try {
|
||||
block =
|
||||
sf.generateBlock(privateKey, sigalg, certChain,
|
||||
sf.generateBlock(privateKey, sigalg, certChain, crls,
|
||||
externalSF, tsaUrl, tsaCert, signingMechanism, args,
|
||||
zipFile);
|
||||
} catch (SocketTimeoutException e) {
|
||||
@ -2197,6 +2250,7 @@ class SignatureFile {
|
||||
public Block generateBlock(PrivateKey privateKey,
|
||||
String sigalg,
|
||||
X509Certificate[] certChain,
|
||||
Set<X509CRL> crls,
|
||||
boolean externalSF, String tsaUrl,
|
||||
X509Certificate tsaCert,
|
||||
ContentSigner signingMechanism,
|
||||
@ -2204,7 +2258,7 @@ class SignatureFile {
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, IOException,
|
||||
SignatureException, CertificateException
|
||||
{
|
||||
return new Block(this, privateKey, sigalg, certChain, externalSF,
|
||||
return new Block(this, privateKey, sigalg, certChain, crls, externalSF,
|
||||
tsaUrl, tsaCert, signingMechanism, args, zipFile);
|
||||
}
|
||||
|
||||
@ -2218,7 +2272,8 @@ class SignatureFile {
|
||||
* Construct a new signature block.
|
||||
*/
|
||||
Block(SignatureFile sfg, PrivateKey privateKey, String sigalg,
|
||||
X509Certificate[] certChain, boolean externalSF, String tsaUrl,
|
||||
X509Certificate[] certChain, Set<X509CRL> crls,
|
||||
boolean externalSF, String tsaUrl,
|
||||
X509Certificate tsaCert, ContentSigner signingMechanism,
|
||||
String[] args, ZipFile zipFile)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException, IOException,
|
||||
@ -2305,7 +2360,7 @@ class SignatureFile {
|
||||
// Assemble parameters for the signing mechanism
|
||||
ContentSignerParameters params =
|
||||
new JarSignerParameters(args, tsaUri, tsaCert, signature,
|
||||
signatureAlgorithm, certChain, content, zipFile);
|
||||
signatureAlgorithm, certChain, crls, content, zipFile);
|
||||
|
||||
// Generate the signature block
|
||||
block = signingMechanism.generateSignedData(
|
||||
@ -2346,6 +2401,7 @@ class JarSignerParameters implements ContentSignerParameters {
|
||||
private byte[] signature;
|
||||
private String signatureAlgorithm;
|
||||
private X509Certificate[] signerCertificateChain;
|
||||
private Set<X509CRL> crls;
|
||||
private byte[] content;
|
||||
private ZipFile source;
|
||||
|
||||
@ -2354,7 +2410,8 @@ class JarSignerParameters implements ContentSignerParameters {
|
||||
*/
|
||||
JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate,
|
||||
byte[] signature, String signatureAlgorithm,
|
||||
X509Certificate[] signerCertificateChain, byte[] content,
|
||||
X509Certificate[] signerCertificateChain, Set<X509CRL> crls,
|
||||
byte[] content,
|
||||
ZipFile source) {
|
||||
|
||||
if (signature == null || signatureAlgorithm == null ||
|
||||
@ -2367,6 +2424,7 @@ class JarSignerParameters implements ContentSignerParameters {
|
||||
this.signature = signature;
|
||||
this.signatureAlgorithm = signatureAlgorithm;
|
||||
this.signerCertificateChain = signerCertificateChain;
|
||||
this.crls = crls;
|
||||
this.content = content;
|
||||
this.source = source;
|
||||
}
|
||||
@ -2442,4 +2500,13 @@ class JarSignerParameters implements ContentSignerParameters {
|
||||
public ZipFile getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<X509CRL> getCRLs() {
|
||||
if (crls == null) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
return Collections.unmodifiableSet(crls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -74,6 +74,8 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||
"[-digestalg <algorithm>] name of digest algorithm"},
|
||||
{"[-sigalg <algorithm>] name of signature algorithm",
|
||||
"[-sigalg <algorithm>] name of signature algorithm"},
|
||||
{"[-crl[:auto| <file>] include CRL in signed jar",
|
||||
"[-crl[:auto| <file>] include CRL in signed jar"},
|
||||
{"[-verify] verify a signed JAR file",
|
||||
"[-verify] verify a signed JAR file"},
|
||||
{"[-verbose[:suboptions]] verbose output when signing/verifying.",
|
||||
@ -191,6 +193,7 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||
{"using an alternative signing mechanism",
|
||||
"using an alternative signing mechanism"},
|
||||
{"entry was signed on", "entry was signed on {0}"},
|
||||
{"with a CRL including %d entries", "with a CRL including %d entries"},
|
||||
{"Warning: ", "Warning: "},
|
||||
{"This jar contains unsigned entries which have not been integrity-checked. ",
|
||||
"This jar contains unsigned entries which have not been integrity-checked. "},
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package sun.security.tools;
|
||||
|
||||
import sun.misc.SharedSecrets;
|
||||
import java.io.*;
|
||||
import java.security.CodeSigner;
|
||||
import java.security.KeyStore;
|
||||
@ -42,6 +43,7 @@ import java.security.Principal;
|
||||
import java.security.Provider;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.Collator;
|
||||
@ -50,14 +52,20 @@ import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.cert.CertStore;
|
||||
|
||||
import java.security.cert.X509CRL;
|
||||
import java.security.cert.X509CRLEntry;
|
||||
import java.security.cert.X509CRLSelector;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.pkcs.PKCS10;
|
||||
import sun.security.provider.X509Factory;
|
||||
import sun.security.util.DerOutputStream;
|
||||
import sun.security.util.Password;
|
||||
import sun.security.util.PathList;
|
||||
import javax.crypto.KeyGenerator;
|
||||
@ -72,6 +80,7 @@ import javax.net.ssl.X509TrustManager;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.security.pkcs.PKCS10Attribute;
|
||||
import sun.security.pkcs.PKCS9Attribute;
|
||||
import sun.security.provider.certpath.ldap.LDAPCertStoreHelper;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.x509.*;
|
||||
|
||||
@ -147,6 +156,7 @@ public final class KeyTool {
|
||||
private Set<char[]> passwords = new HashSet<char[]> ();
|
||||
private String startDate = null;
|
||||
|
||||
private List <String> ids = new ArrayList <String> (); // used in GENCRL
|
||||
private List <String> v3ext = new ArrayList <String> ();
|
||||
|
||||
enum Command {
|
||||
@ -180,9 +190,6 @@ public final class KeyTool {
|
||||
STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,
|
||||
STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
|
||||
PROVIDERARG, PROVIDERPATH, V, PROTECTED),
|
||||
IDENTITYDB("Imports entries from a JDK 1.1.x-style identity database",
|
||||
FILEIN, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME,
|
||||
PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V),
|
||||
IMPORTCERT("Imports a certificate or a certificate chain",
|
||||
NOPROMPT, TRUSTCACERTS, PROTECTED, ALIAS, FILEIN,
|
||||
KEYPASS, KEYSTORE, STOREPASS, STORETYPE,
|
||||
@ -195,10 +202,6 @@ public final class KeyTool {
|
||||
SRCALIAS, DESTALIAS, SRCKEYPASS, DESTKEYPASS,
|
||||
NOPROMPT, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH,
|
||||
V),
|
||||
KEYCLONE("Clones a key entry",
|
||||
ALIAS, DESTALIAS, KEYPASS, NEW, STORETYPE,
|
||||
KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS,
|
||||
PROVIDERARG, PROVIDERPATH, V),
|
||||
KEYPASSWD("Changes the key password of an entry",
|
||||
ALIAS, KEYPASS, NEW, KEYSTORE, STOREPASS,
|
||||
STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
|
||||
@ -211,12 +214,29 @@ public final class KeyTool {
|
||||
RFC, FILEIN, SSLSERVER, JARFILE, V),
|
||||
PRINTCERTREQ("Prints the content of a certificate request",
|
||||
FILEIN, V),
|
||||
PRINTCRL("Prints the content of a CRL file",
|
||||
FILEIN, V),
|
||||
STOREPASSWD("Changes the store password of a keystore",
|
||||
NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME,
|
||||
PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V),
|
||||
|
||||
// Undocumented start here, KEYCLONE is used a marker in -help;
|
||||
|
||||
KEYCLONE("Clones a key entry",
|
||||
ALIAS, DESTALIAS, KEYPASS, NEW, STORETYPE,
|
||||
KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS,
|
||||
PROVIDERARG, PROVIDERPATH, V),
|
||||
SELFCERT("Generates a self-signed certificate",
|
||||
ALIAS, SIGALG, DNAME, STARTDATE, VALIDITY, KEYPASS,
|
||||
STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME,
|
||||
PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V),
|
||||
STOREPASSWD("Changes the store password of a keystore",
|
||||
NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME,
|
||||
GENCRL("Generates CRL",
|
||||
RFC, FILEOUT, ID,
|
||||
ALIAS, SIGALG, EXT, KEYPASS, KEYSTORE,
|
||||
STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
|
||||
PROVIDERARG, PROVIDERPATH, V, PROTECTED),
|
||||
IDENTITYDB("Imports entries from a JDK 1.1.x-style identity database",
|
||||
FILEIN, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME,
|
||||
PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V);
|
||||
|
||||
final String description;
|
||||
@ -244,6 +264,7 @@ public final class KeyTool {
|
||||
EXT("ext", "<value>", "X.509 extension"),
|
||||
FILEOUT("file", "<filename>", "output file name"),
|
||||
FILEIN("file", "<filename>", "input file name"),
|
||||
ID("id", "<id:reason>", "Serial ID of cert to revoke"),
|
||||
INFILE("infile", "<filename>", "input file name"),
|
||||
KEYALG("keyalg", "<keyalg>", "key algorithm name"),
|
||||
KEYPASS("keypass", "<arg>", "key password"),
|
||||
@ -458,6 +479,8 @@ public final class KeyTool {
|
||||
validity = Long.parseLong(args[++i]);
|
||||
} else if (collator.compare(flags, "-ext") == 0) {
|
||||
v3ext.add(args[++i]);
|
||||
} else if (collator.compare(flags, "-id") == 0) {
|
||||
ids.add(args[++i]);
|
||||
} else if (collator.compare(flags, "-file") == 0) {
|
||||
filename = args[++i];
|
||||
} else if (collator.compare(flags, "-infile") == 0) {
|
||||
@ -720,7 +743,8 @@ public final class KeyTool {
|
||||
command != GENSECKEY &&
|
||||
command != IDENTITYDB &&
|
||||
command != IMPORTCERT &&
|
||||
command != IMPORTKEYSTORE) {
|
||||
command != IMPORTKEYSTORE &&
|
||||
command != PRINTCRL) {
|
||||
throw new Exception(rb.getString
|
||||
("Keystore file does not exist: ") + ksfname);
|
||||
}
|
||||
@ -855,10 +879,12 @@ public final class KeyTool {
|
||||
&& !KeyStoreUtil.isWindowsKeyStore(storetype)
|
||||
&& isKeyStoreRelated(command)) {
|
||||
// here we have EXPORTCERT and LIST (info valid until STOREPASSWD)
|
||||
System.err.print(rb.getString("Enter keystore password: "));
|
||||
System.err.flush();
|
||||
storePass = Password.readPassword(System.in);
|
||||
passwords.add(storePass);
|
||||
if (command != PRINTCRL) {
|
||||
System.err.print(rb.getString("Enter keystore password: "));
|
||||
System.err.flush();
|
||||
storePass = Password.readPassword(System.in);
|
||||
passwords.add(storePass);
|
||||
}
|
||||
}
|
||||
|
||||
// Now load a nullStream-based keystore,
|
||||
@ -895,7 +921,7 @@ public final class KeyTool {
|
||||
|
||||
// Create a certificate factory
|
||||
if (command == PRINTCERT || command == IMPORTCERT
|
||||
|| command == IDENTITYDB) {
|
||||
|| command == IDENTITYDB || command == PRINTCRL) {
|
||||
cf = CertificateFactory.getInstance("X509");
|
||||
}
|
||||
|
||||
@ -1086,6 +1112,22 @@ public final class KeyTool {
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
} else if (command == GENCRL) {
|
||||
if (alias == null) {
|
||||
alias = keyAlias;
|
||||
}
|
||||
PrintStream ps = null;
|
||||
if (filename != null) {
|
||||
ps = new PrintStream(new FileOutputStream(filename));
|
||||
out = ps;
|
||||
}
|
||||
try {
|
||||
doGenCRL(out);
|
||||
} finally {
|
||||
if (ps != null) {
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
} else if (command == PRINTCERTREQ) {
|
||||
InputStream inStream = System.in;
|
||||
if (filename != null) {
|
||||
@ -1098,6 +1140,8 @@ public final class KeyTool {
|
||||
inStream.close();
|
||||
}
|
||||
}
|
||||
} else if (command == PRINTCRL) {
|
||||
doPrintCRL(filename, out);
|
||||
}
|
||||
|
||||
// If we need to save the keystore, do so.
|
||||
@ -1152,7 +1196,8 @@ public final class KeyTool {
|
||||
CertificateValidity interval = new CertificateValidity(firstDate,
|
||||
lastDate);
|
||||
|
||||
PrivateKey privateKey = (PrivateKey)recoverKey(alias, storePass, keyPass).fst;
|
||||
PrivateKey privateKey =
|
||||
(PrivateKey)recoverKey(alias, storePass, keyPass).fst;
|
||||
if (sigAlgName == null) {
|
||||
sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm());
|
||||
}
|
||||
@ -1221,6 +1266,56 @@ public final class KeyTool {
|
||||
}
|
||||
}
|
||||
|
||||
private void doGenCRL(PrintStream out)
|
||||
throws Exception {
|
||||
if (ids == null) {
|
||||
throw new Exception("Must provide -id when -gencrl");
|
||||
}
|
||||
Certificate signerCert = keyStore.getCertificate(alias);
|
||||
byte[] encoded = signerCert.getEncoded();
|
||||
X509CertImpl signerCertImpl = new X509CertImpl(encoded);
|
||||
X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
|
||||
X509CertImpl.NAME + "." + X509CertImpl.INFO);
|
||||
X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
|
||||
CertificateSubjectName.DN_NAME);
|
||||
|
||||
Date firstDate = getStartDate(startDate);
|
||||
Date lastDate = (Date) firstDate.clone();
|
||||
lastDate.setTime(lastDate.getTime() + (long)validity*1000*24*60*60);
|
||||
CertificateValidity interval = new CertificateValidity(firstDate,
|
||||
lastDate);
|
||||
|
||||
|
||||
PrivateKey privateKey =
|
||||
(PrivateKey)recoverKey(alias, storePass, keyPass).fst;
|
||||
if (sigAlgName == null) {
|
||||
sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm());
|
||||
}
|
||||
|
||||
X509CRLEntry[] badCerts = new X509CRLEntry[ids.size()];
|
||||
for (int i=0; i<ids.size(); i++) {
|
||||
String id = ids.get(i);
|
||||
int d = id.indexOf(':');
|
||||
if (d >= 0) {
|
||||
CRLExtensions ext = new CRLExtensions();
|
||||
ext.set("Reason", new CRLReasonCodeExtension(Integer.parseInt(id.substring(d+1))));
|
||||
badCerts[i] = new X509CRLEntryImpl(new BigInteger(id.substring(0, d)),
|
||||
firstDate, ext);
|
||||
} else {
|
||||
badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
|
||||
}
|
||||
}
|
||||
X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts);
|
||||
crl.sign(privateKey, sigAlgName);
|
||||
if (rfc) {
|
||||
out.println("-----BEGIN X509 CRL-----");
|
||||
new BASE64Encoder().encodeBuffer(crl.getEncodedInternal(), out);
|
||||
out.println("-----END X509 CRL-----");
|
||||
} else {
|
||||
out.write(crl.getEncodedInternal());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PKCS#10 cert signing request, corresponding to the
|
||||
* keys (and name) associated with a given alias.
|
||||
@ -1925,6 +2020,177 @@ public final class KeyTool {
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Iterable<T> e2i(final Enumeration<T> e) {
|
||||
return new Iterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return e.hasMoreElements();
|
||||
}
|
||||
@Override
|
||||
public T next() {
|
||||
return e.nextElement();
|
||||
}
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads CRLs from a source. This method is also called in JarSigner.
|
||||
* @param src the source, which means System.in if null, or a URI,
|
||||
* or a bare file path name
|
||||
*/
|
||||
public static Collection<? extends CRL> loadCRLs(String src) throws Exception {
|
||||
InputStream in = null;
|
||||
URI uri = null;
|
||||
if (src == null) {
|
||||
in = System.in;
|
||||
} else {
|
||||
try {
|
||||
uri = new URI(src);
|
||||
if (uri.getScheme().equals("ldap")) {
|
||||
// No input stream for LDAP
|
||||
} else {
|
||||
in = uri.toURL().openStream();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
in = new FileInputStream(src);
|
||||
} catch (Exception e2) {
|
||||
if (uri == null || uri.getScheme() == null) {
|
||||
throw e2; // More likely a bare file path
|
||||
} else {
|
||||
throw e; // More likely a protocol or network problem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in != null) {
|
||||
try {
|
||||
// Read the full stream before feeding to X509Factory,
|
||||
// otherwise, keytool -gencrl | keytool -printcrl
|
||||
// might not work properly, since -gencrl is slow
|
||||
// and there's no data in the pipe at the beginning.
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
byte[] b = new byte[4096];
|
||||
while (true) {
|
||||
int len = in.read(b);
|
||||
if (len < 0) break;
|
||||
bout.write(b, 0, len);
|
||||
}
|
||||
return CertificateFactory.getInstance("X509").generateCRLs(
|
||||
new ByteArrayInputStream(bout.toByteArray()));
|
||||
} finally {
|
||||
if (in != System.in) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
} else { // must be LDAP, and uri is not null
|
||||
String path = uri.getPath();
|
||||
if (path.charAt(0) == '/') path = path.substring(1);
|
||||
LDAPCertStoreHelper h = new LDAPCertStoreHelper();
|
||||
CertStore s = h.getCertStore(uri);
|
||||
X509CRLSelector sel =
|
||||
h.wrap(new X509CRLSelector(), null, path);
|
||||
return s.getCRLs(sel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns CRLs described in a X509Certificate's CRLDistributionPoints
|
||||
* Extension. Only those containing a general name of type URI are read.
|
||||
*/
|
||||
public static List<CRL> readCRLsFromCert(X509Certificate cert)
|
||||
throws Exception {
|
||||
List<CRL> crls = new ArrayList<CRL>();
|
||||
CRLDistributionPointsExtension ext =
|
||||
X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension();
|
||||
if (ext == null) return crls;
|
||||
for (DistributionPoint o: (List<DistributionPoint>)
|
||||
ext.get(CRLDistributionPointsExtension.POINTS)) {
|
||||
GeneralNames names = o.getFullName();
|
||||
if (names != null) {
|
||||
for (GeneralName name: names.names()) {
|
||||
if (name.getType() == GeneralNameInterface.NAME_URI) {
|
||||
URIName uriName = (URIName)name.getName();
|
||||
for (CRL crl: KeyTool.loadCRLs(uriName.getName())) {
|
||||
if (crl instanceof X509CRL) {
|
||||
crls.add((X509CRL)crl);
|
||||
}
|
||||
}
|
||||
break; // Different name should point to same CRL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return crls;
|
||||
}
|
||||
|
||||
private static String verifyCRL(KeyStore ks, CRL crl)
|
||||
throws Exception {
|
||||
X509CRLImpl xcrl = (X509CRLImpl)crl;
|
||||
X500Principal issuer = xcrl.getIssuerX500Principal();
|
||||
for (String s: e2i(ks.aliases())) {
|
||||
Certificate cert = ks.getCertificate(s);
|
||||
if (cert instanceof X509Certificate) {
|
||||
X509Certificate xcert = (X509Certificate)cert;
|
||||
if (xcert.getSubjectX500Principal().equals(issuer)) {
|
||||
try {
|
||||
((X509CRLImpl)crl).verify(cert.getPublicKey());
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void doPrintCRL(String src, PrintStream out)
|
||||
throws Exception {
|
||||
for (CRL crl: loadCRLs(src)) {
|
||||
printCRL(crl, out);
|
||||
String issuer = null;
|
||||
if (caks != null) {
|
||||
issuer = verifyCRL(caks, crl);
|
||||
if (issuer != null) {
|
||||
System.out.println("Verified by " + issuer + " in cacerts");
|
||||
}
|
||||
}
|
||||
if (issuer == null && keyStore != null) {
|
||||
issuer = verifyCRL(keyStore, crl);
|
||||
if (issuer != null) {
|
||||
System.out.println("Verified by " + issuer + " in keystore");
|
||||
}
|
||||
}
|
||||
if (issuer == null) {
|
||||
out.println(rb.getString
|
||||
("*******************************************"));
|
||||
out.println("WARNING: not verified. Make sure -keystore and -alias are correct.");
|
||||
out.println(rb.getString
|
||||
("*******************************************\n\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printCRL(CRL crl, PrintStream out)
|
||||
throws Exception {
|
||||
if (rfc) {
|
||||
X509CRL xcrl = (X509CRL)crl;
|
||||
out.println("-----BEGIN X509 CRL-----");
|
||||
new BASE64Encoder().encodeBuffer(xcrl.getEncoded(), out);
|
||||
out.println("-----END X509 CRL-----");
|
||||
} else {
|
||||
out.println(crl.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void doPrintCertReq(InputStream in, PrintStream out)
|
||||
throws Exception {
|
||||
|
||||
@ -2063,6 +2329,16 @@ public final class KeyTool {
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
CRL[] crls = SharedSecrets
|
||||
.getJavaSecurityCodeSignerAccess()
|
||||
.getCRLs(signer);
|
||||
if (crls != null) {
|
||||
out.println(rb.getString("CRLs:"));
|
||||
out.println();
|
||||
for (CRL crl: crls) {
|
||||
printCRL(crl, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3330,15 +3606,22 @@ public final class KeyTool {
|
||||
/**
|
||||
* Match a command (may be abbreviated) with a command set.
|
||||
* @param s the command provided
|
||||
* @param list the legal command set
|
||||
* @param list the legal command set. If there is a null, commands after it
|
||||
* are regarded experimental, which means they are supported but their
|
||||
* existence should not be revealed to user.
|
||||
* @return the position of a single match, or -1 if none matched
|
||||
* @throws Exception if s is ambiguous
|
||||
*/
|
||||
private static int oneOf(String s, String... list) throws Exception {
|
||||
int[] match = new int[list.length];
|
||||
int nmatch = 0;
|
||||
int experiment = Integer.MAX_VALUE;
|
||||
for (int i = 0; i<list.length; i++) {
|
||||
String one = list[i];
|
||||
if (one == null) {
|
||||
experiment = i;
|
||||
continue;
|
||||
}
|
||||
if (one.toLowerCase(Locale.ENGLISH)
|
||||
.startsWith(s.toLowerCase(Locale.ENGLISH))) {
|
||||
match[nmatch++] = i;
|
||||
@ -3360,17 +3643,27 @@ public final class KeyTool {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nmatch == 0) return -1;
|
||||
if (nmatch == 1) return match[0];
|
||||
StringBuffer sb = new StringBuffer();
|
||||
MessageFormat form = new MessageFormat(rb.getString
|
||||
("command {0} is ambiguous:"));
|
||||
Object[] source = {s};
|
||||
sb.append(form.format(source) +"\n ");
|
||||
for (int i=0; i<nmatch; i++) {
|
||||
sb.append(" " + list[match[i]]);
|
||||
if (nmatch == 0) {
|
||||
return -1;
|
||||
} else if (nmatch == 1) {
|
||||
return match[0];
|
||||
} else {
|
||||
// If multiple matches is in experimental commands, ignore them
|
||||
if (match[1] > experiment) {
|
||||
return match[0];
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
MessageFormat form = new MessageFormat(rb.getString
|
||||
("command {0} is ambiguous:"));
|
||||
Object[] source = {s};
|
||||
sb.append(form.format(source));
|
||||
sb.append("\n ");
|
||||
for (int i=0; i<nmatch && match[i]<experiment; i++) {
|
||||
sb.append(' ');
|
||||
sb.append(list[match[i]]);
|
||||
}
|
||||
throw new Exception(sb.toString());
|
||||
}
|
||||
throw new Exception(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3405,6 +3698,8 @@ public final class KeyTool {
|
||||
"IssuerAlternativeName",
|
||||
"SubjectInfoAccess",
|
||||
"AuthorityInfoAccess",
|
||||
null,
|
||||
"CRLDistributionPoints",
|
||||
};
|
||||
|
||||
private ObjectIdentifier findOidForExtName(String type)
|
||||
@ -3417,6 +3712,7 @@ public final class KeyTool {
|
||||
case 4: return PKIXExtensions.IssuerAlternativeName_Id;
|
||||
case 5: return PKIXExtensions.SubjectInfoAccess_Id;
|
||||
case 6: return PKIXExtensions.AuthInfoAccess_Id;
|
||||
case 8: return PKIXExtensions.CRLDistributionPoints_Id;
|
||||
default: return new ObjectIdentifier(type);
|
||||
}
|
||||
}
|
||||
@ -3712,6 +4008,28 @@ public final class KeyTool {
|
||||
("Illegal value: ") + extstr);
|
||||
}
|
||||
break;
|
||||
case 8: // CRL, experimental, only support 1 distributionpoint
|
||||
if(value != null) {
|
||||
String[] ps = value.split(",");
|
||||
GeneralNames gnames = new GeneralNames();
|
||||
for(String item: ps) {
|
||||
colonpos = item.indexOf(':');
|
||||
if (colonpos < 0) {
|
||||
throw new Exception("Illegal item " + item + " in " + extstr);
|
||||
}
|
||||
String t = item.substring(0, colonpos);
|
||||
String v = item.substring(colonpos+1);
|
||||
gnames.add(createGeneralName(t, v));
|
||||
}
|
||||
ext.set(CRLDistributionPointsExtension.NAME,
|
||||
new CRLDistributionPointsExtension(
|
||||
isCritical, Collections.singletonList(
|
||||
new DistributionPoint(gnames, null, null))));
|
||||
} else {
|
||||
throw new Exception(rb.getString
|
||||
("Illegal value: ") + extstr);
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
ObjectIdentifier oid = new ObjectIdentifier(name);
|
||||
byte[] data = null;
|
||||
@ -3748,6 +4066,9 @@ public final class KeyTool {
|
||||
new DerValue(DerValue.tag_OctetString, data)
|
||||
.toByteArray()));
|
||||
break;
|
||||
default:
|
||||
throw new Exception(rb.getString(
|
||||
"Unknown extension type: ") + extstr);
|
||||
}
|
||||
}
|
||||
// always non-critical
|
||||
@ -3810,11 +4131,8 @@ public final class KeyTool {
|
||||
System.err.println(rb.getString("Commands:"));
|
||||
System.err.println();
|
||||
for (Command c: Command.values()) {
|
||||
if (c != IDENTITYDB
|
||||
&& c != KEYCLONE
|
||||
&& c != SELFCERT) { // Deprecated commands
|
||||
System.err.printf(" %-20s%s\n", c, rb.getString(c.description));
|
||||
}
|
||||
if (c == KEYCLONE) break;
|
||||
System.err.printf(" %-20s%s\n", c, rb.getString(c.description));
|
||||
}
|
||||
System.err.println();
|
||||
System.err.println(rb.getString(
|
||||
|
@ -38,6 +38,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jarsigner.*;
|
||||
import java.security.cert.X509CRL;
|
||||
import java.util.Arrays;
|
||||
import sun.security.pkcs.*;
|
||||
import sun.security.timestamp.*;
|
||||
@ -239,7 +240,7 @@ public final class TimestampedSigner extends ContentSigner {
|
||||
// Create the PKCS #7 signed data message
|
||||
PKCS7 p7 =
|
||||
new PKCS7(algorithms, contentInfo, signerCertificateChain,
|
||||
signerInfos);
|
||||
parameters.getCRLs().toArray(new X509CRL[parameters.getCRLs().size()]), signerInfos);
|
||||
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
|
||||
p7.encodeSignedData(p7out);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -71,6 +71,7 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
"Generates a secret key"}, //-genseckey
|
||||
{"Generates certificate from a certificate request",
|
||||
"Generates certificate from a certificate request"}, //-gencert
|
||||
{"Generates CRL", "Generates CRL"}, //-gencrl
|
||||
{"Imports entries from a JDK 1.1.x-style identity database",
|
||||
"Imports entries from a JDK 1.1.x-style identity database"}, //-identitydb
|
||||
{"Imports a certificate or a certificate chain",
|
||||
@ -87,6 +88,8 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
"Prints the content of a certificate"}, //-printcert
|
||||
{"Prints the content of a certificate request",
|
||||
"Prints the content of a certificate request"}, //-printcertreq
|
||||
{"Prints the content of a CRL file",
|
||||
"Prints the content of a CRL file"}, //-printcrl
|
||||
{"Generates a self-signed certificate",
|
||||
"Generates a self-signed certificate"}, //-selfcert
|
||||
{"Changes the store password of a keystore",
|
||||
@ -176,6 +179,8 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
"verbose output"}, //-v
|
||||
{"validity number of days",
|
||||
"validity number of days"}, //-validity
|
||||
{"Serial ID of cert to revoke",
|
||||
"Serial ID of cert to revoke"}, //-id
|
||||
// keytool: Running part
|
||||
{"keytool error: ", "keytool error: "},
|
||||
{"Illegal option: ", "Illegal option: "},
|
||||
@ -375,6 +380,7 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
{"Signer #%d:", "Signer #%d:"},
|
||||
{"Timestamp:", "Timestamp:"},
|
||||
{"Signature:", "Signature:"},
|
||||
{"CRLs:", "CRLs:"},
|
||||
{"Certificate owner: ", "Certificate owner: "},
|
||||
{"Not a signed jar file", "Not a signed jar file"},
|
||||
{"No certificate from the SSL server",
|
||||
@ -433,6 +439,7 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
{"This extension cannot be marked as critical. ",
|
||||
"This extension cannot be marked as critical. "},
|
||||
{"Odd number of hex digits found: ", "Odd number of hex digits found: "},
|
||||
{"Unknown extension type: ", "Unknown extension type: "},
|
||||
{"command {0} is ambiguous:", "command {0} is ambiguous:"},
|
||||
|
||||
// policytool
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
package sun.security.util;
|
||||
|
||||
import java.security.CodeSigner;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
@ -34,11 +33,11 @@ import java.security.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import sun.security.pkcs.*;
|
||||
import sun.security.timestamp.TimestampToken;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
import sun.security.jca.Providers;
|
||||
|
||||
@ -479,7 +478,12 @@ public class SignatureFileVerifier {
|
||||
signers = new ArrayList<CodeSigner>();
|
||||
}
|
||||
// Append the new code signer
|
||||
signers.add(new CodeSigner(certChain, getTimestamp(info)));
|
||||
CodeSigner signer = new CodeSigner(certChain, getTimestamp(info));
|
||||
if (block.getCRLs() != null) {
|
||||
SharedSecrets.getJavaSecurityCodeSignerAccess().setCRLs(
|
||||
signer, block.getCRLs());
|
||||
}
|
||||
signers.add(signer);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Signature Block Certificate: " +
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -89,7 +89,7 @@ import sun.misc.HexDumpEncoder;
|
||||
* @author Hemma Prafullchandra
|
||||
* @see X509CRL
|
||||
*/
|
||||
public class X509CRLImpl extends X509CRL {
|
||||
public class X509CRLImpl extends X509CRL implements DerEncoder {
|
||||
|
||||
// CRL data, and its envelope
|
||||
private byte[] signedCRL = null; // DER encoded crl
|
||||
@ -1189,6 +1189,13 @@ public class X509CRLImpl extends X509CRL {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void derEncode(OutputStream out) throws IOException {
|
||||
if (signedCRL == null)
|
||||
throw new IOException("Null CRL to encode");
|
||||
out.write(signedCRL.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Immutable X.509 Certificate Issuer DN and serial number pair
|
||||
*/
|
||||
|
91
jdk/test/sun/security/tools/jarsigner/crl.sh
Normal file
91
jdk/test/sun/security/tools/jarsigner/crl.sh
Normal file
@ -0,0 +1,91 @@
|
||||
#
|
||||
# Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
# have any questions.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 6890876
|
||||
# @summary jarsigner can add CRL info into signed jar
|
||||
#
|
||||
|
||||
if [ "${TESTJAVA}" = "" ] ; then
|
||||
JAVAC_CMD=`which javac`
|
||||
TESTJAVA=`dirname $JAVAC_CMD`/..
|
||||
fi
|
||||
|
||||
# set platform-dependent variables
|
||||
# PF: platform name, say, solaris-sparc
|
||||
|
||||
PF=""
|
||||
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Windows* )
|
||||
FS="\\"
|
||||
;;
|
||||
* )
|
||||
FS="/"
|
||||
;;
|
||||
esac
|
||||
|
||||
KS=crl.jks
|
||||
JFILE=crl.jar
|
||||
|
||||
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
|
||||
JAR=$TESTJAVA${FS}bin${FS}jar
|
||||
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
|
||||
|
||||
rm $KS $JFILE
|
||||
|
||||
# Generates some crl files, each containing two entries
|
||||
|
||||
$KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300
|
||||
$KT -alias a -gencrl -id 1:1 -id 2:2 -file crl1
|
||||
$KT -alias a -gencrl -id 3:3 -id 4:4 -file crl2
|
||||
$KT -alias b -dname CN=b -keyalg rsa -genkey -validity 300
|
||||
$KT -alias b -gencrl -id 5:1 -id 6:2 -file crl3
|
||||
|
||||
$KT -alias c -dname CN=c -keyalg rsa -genkey -validity 300 \
|
||||
-ext crl=uri:file://`pwd`/crl1
|
||||
|
||||
echo A > A
|
||||
|
||||
# Test -crl:auto, cRLDistributionPoints is a local file
|
||||
|
||||
$JAR cvf $JFILE A
|
||||
$JARSIGNER -keystore $KS -storepass changeit $JFILE c \
|
||||
-crl:auto || exit 1
|
||||
$JARSIGNER -keystore $KS -verify -debug -strict $JFILE || exit 6
|
||||
$KT -printcert -jarfile $JFILE | grep CRLs || exit 7
|
||||
|
||||
# Test -crl <file>
|
||||
|
||||
$JAR cvf $JFILE A
|
||||
$JARSIGNER -keystore $KS -storepass changeit $JFILE a \
|
||||
-crl crl1 -crl crl2 || exit 1
|
||||
$JARSIGNER -keystore $KS -storepass changeit $JFILE b \
|
||||
-crl crl3 -crl crl2 || exit 1
|
||||
$JARSIGNER -keystore $KS -verify -debug -strict $JFILE || exit 3
|
||||
$KT -printcert -jarfile $JFILE | grep CRLs || exit 4
|
||||
CRLCOUNT=`$KT -printcert -jarfile $JFILE | grep SerialNumber | wc -l`
|
||||
if [ $CRLCOUNT != 8 ]; then exit 5; fi
|
||||
|
||||
exit 0
|
Loading…
x
Reference in New Issue
Block a user