提交 b51dd8fc 编写于 作者: W weijun

6890876: jarsigner can add CRL info into signed jar

Reviewed-by: mullan
上级 726b88f9
/*
* 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.
......
/*
* 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();
}
});
}
}
/*
* 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;
......
/*
* 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;
}
}
/*
* 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);
}
}
}
/*
* 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);
......
/*
* 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
......
/*
* 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: " +
......
/*
* 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
*/
......
#
# 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册