in src/java.base/share/classes/sun/security/tools/keytool/Main.java [736:1440]
void doCommands(PrintStream out) throws Exception {
if (cacerts) {
if (ksfname != null || storetype != null) {
throw new IllegalArgumentException(rb.getString
("the.keystore.or.storetype.option.cannot.be.used.with.the.cacerts.option"));
}
ksfname = KeyStoreUtil.getCacerts();
}
if (P11KEYSTORE.equalsIgnoreCase(storetype) ||
KeyStoreUtil.isWindowsKeyStore(storetype)) {
token = true;
if (ksfname == null) {
ksfname = NONE;
}
}
if (NONE.equals(ksfname)) {
nullStream = true;
}
if (token && !nullStream) {
System.err.println(MessageFormat.format(rb.getString
(".keystore.must.be.NONE.if.storetype.is.{0}"), storetype));
System.err.println();
tinyHelp();
}
if (token &&
(command == KEYPASSWD || command == STOREPASSWD)) {
throw new UnsupportedOperationException(MessageFormat.format(rb.getString
(".storepasswd.and.keypasswd.commands.not.supported.if.storetype.is.{0}"), storetype));
}
if (token && (keyPass != null || newPass != null || destKeyPass != null)) {
throw new IllegalArgumentException(MessageFormat.format(rb.getString
(".keypass.and.new.can.not.be.specified.if.storetype.is.{0}"), storetype));
}
if (protectedPath) {
if (storePass != null || keyPass != null ||
newPass != null || destKeyPass != null) {
throw new IllegalArgumentException(rb.getString
("if.protected.is.specified.then.storepass.keypass.and.new.must.not.be.specified"));
}
}
if (srcprotectedPath) {
if (srcstorePass != null || srckeyPass != null) {
throw new IllegalArgumentException(rb.getString
("if.srcprotected.is.specified.then.srcstorepass.and.srckeypass.must.not.be.specified"));
}
}
if (KeyStoreUtil.isWindowsKeyStore(storetype)) {
if (storePass != null || keyPass != null ||
newPass != null || destKeyPass != null) {
throw new IllegalArgumentException(rb.getString
("if.keystore.is.not.password.protected.then.storepass.keypass.and.new.must.not.be.specified"));
}
}
if (KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
if (srcstorePass != null || srckeyPass != null) {
throw new IllegalArgumentException(rb.getString
("if.source.keystore.is.not.password.protected.then.srcstorepass.and.srckeypass.must.not.be.specified"));
}
}
if (validity <= (long)0) {
throw new Exception
(rb.getString("Validity.must.be.greater.than.zero"));
}
// Try to load and install specified provider
if (providers != null) {
for (Pair<String, String> provider : providers) {
try {
KeyStoreUtil.loadProviderByName(
provider.fst, provider.snd);
if (debug) {
System.out.println("loadProviderByName: " + provider.fst);
}
} catch (IllegalArgumentException e) {
throw new Exception(String.format(rb.getString(
"provider.name.not.found"), provider.fst));
}
}
}
if (providerClasses != null) {
ClassLoader cl;
if (pathlist != null) {
String path = System.getProperty("java.class.path");
path = PathList.appendPath(
path, System.getProperty("env.class.path"));
path = PathList.appendPath(path, pathlist);
URL[] urls = PathList.pathToURLs(path);
cl = new URLClassLoader(urls);
} else {
cl = ClassLoader.getSystemClassLoader();
}
for (Pair<String, String> provider : providerClasses) {
try {
KeyStoreUtil.loadProviderByClass(
provider.fst, provider.snd, cl);
if (debug) {
System.out.println("loadProviderByClass: " + provider.fst);
}
} catch (ClassCastException cce) {
throw new Exception(String.format(rb.getString(
"provclass.not.a.provider"), provider.fst));
} catch (IllegalArgumentException e) {
throw new Exception(String.format(rb.getString(
"provider.class.not.found"), provider.fst), e.getCause());
}
}
}
if (command == LIST && verbose && rfc) {
System.err.println(rb.getString
("Must.not.specify.both.v.and.rfc.with.list.command"));
tinyHelp();
}
// Make sure provided passwords are at least 6 characters long
if (command == GENKEYPAIR && keyPass!=null && keyPass.length < 6) {
throw new Exception(rb.getString
("Key.password.must.be.at.least.6.characters"));
}
if (newPass != null && newPass.length < 6) {
throw new Exception(rb.getString
("New.password.must.be.at.least.6.characters"));
}
if (destKeyPass != null && destKeyPass.length < 6) {
throw new Exception(rb.getString
("New.password.must.be.at.least.6.characters"));
}
// Set this before inplaceImport check so we can compare name.
if (ksfname == null) {
ksfname = System.getProperty("user.home") + File.separator
+ ".keystore";
}
KeyStore srcKeyStore = null;
if (command == IMPORTKEYSTORE) {
inplaceImport = inplaceImportCheck();
if (inplaceImport) {
// We load srckeystore first so we have srcstorePass that
// can be assigned to storePass
srcKeyStore = loadSourceKeyStore();
if (storePass == null) {
storePass = srcstorePass;
}
}
}
// Check if keystore exists.
// If no keystore has been specified at the command line, try to use
// the default, which is located in $HOME/.keystore.
// No need to check if isKeyStoreRelated(command) is false.
// DO NOT open the existing keystore if this is an in-place import.
// The keystore should be created as brand new.
if (isKeyStoreRelated(command) && !nullStream && !inplaceImport) {
try {
ksfile = new File(ksfname);
// Check if keystore file is empty
if (ksfile.exists() && ksfile.length() == 0) {
throw new Exception(rb.getString
("Keystore.file.exists.but.is.empty.") + ksfname);
}
ksStream = new FileInputStream(ksfile);
} catch (FileNotFoundException e) {
// These commands do not need the keystore to be existing.
// Either it will create a new one or the keystore is
// optional (i.e. PRINTCRL and PRINTCERT).
if (command != GENKEYPAIR &&
command != GENSECKEY &&
command != IDENTITYDB &&
command != IMPORTCERT &&
command != IMPORTPASS &&
command != IMPORTKEYSTORE &&
command != PRINTCRL &&
command != PRINTCERT) {
throw new Exception(rb.getString
("Keystore.file.does.not.exist.") + ksfname);
}
}
}
if ((command == KEYCLONE || command == CHANGEALIAS)
&& dest == null) {
dest = getAlias("destination");
if ("".equals(dest)) {
throw new Exception(rb.getString
("Must.specify.destination.alias"));
}
}
if (command == DELETE && alias == null) {
alias = getAlias(null);
if ("".equals(alias)) {
throw new Exception(rb.getString("Must.specify.alias"));
}
}
if (ksfile != null && ksStream != null && providerName == null &&
!inplaceImport) {
// existing keystore
if (storetype == null) {
// Probe for keystore type when filename is available
keyStore = KeyStore.getInstance(ksfile, storePass);
storetype = keyStore.getType();
} else {
keyStore = KeyStore.getInstance(storetype);
// storePass might be null here, will probably prompt later
keyStore.load(ksStream, storePass);
}
if (storetype.equalsIgnoreCase("pkcs12")) {
try {
isPasswordlessKeyStore = PKCS12KeyStore.isPasswordless(ksfile);
} catch (IOException ioe) {
// This must be a JKS keystore that's opened as a PKCS12
}
}
} else {
// Create new keystore
if (storetype == null) {
storetype = KeyStore.getDefaultType();
}
if (providerName == null) {
keyStore = KeyStore.getInstance(storetype);
} else {
keyStore = KeyStore.getInstance(storetype, providerName);
}
// When creating a new pkcs12 file, Do not prompt for storepass
// if certProtectionAlgorithm and macAlgorithm are both NONE.
if (storetype.equalsIgnoreCase("pkcs12")) {
isPasswordlessKeyStore =
"NONE".equals(SecurityProperties.getOverridableProperty(
"keystore.pkcs12.certProtectionAlgorithm"))
&& "NONE".equals(SecurityProperties.getOverridableProperty(
"keystore.pkcs12.macAlgorithm"));
}
/*
* Load the keystore data.
*
* At this point, it's OK if no keystore password has been provided.
* We want to make sure that we can load the keystore data, i.e.,
* the keystore data has the right format. If we cannot load the
* keystore, why bother asking the user for his or her password?
* Only if we were able to load the keystore, and no keystore
* password has been provided, will we prompt the user for the
* keystore password to verify the keystore integrity.
* This means that the keystore is loaded twice: first load operation
* checks the keystore format, second load operation verifies the
* keystore integrity.
*
* If the keystore password has already been provided (at the
* command line), however, the keystore is loaded only once, and the
* keystore format and integrity are checked "at the same time".
*
* Null stream keystores are loaded later.
*/
if (!nullStream) {
if (inplaceImport) {
keyStore.load(null, storePass);
} else {
// both ksStream and storePass could be null
keyStore.load(ksStream, storePass);
}
}
}
if (P12KEYSTORE.equalsIgnoreCase(storetype) && command == KEYPASSWD) {
throw new UnsupportedOperationException(rb.getString
(".keypasswd.commands.not.supported.if.storetype.is.PKCS12"));
}
// All commands that create or modify the keystore require a keystore
// password.
if (nullStream && storePass != null) {
keyStore.load(null, storePass);
} else if (!nullStream && storePass != null) {
// If we are creating a new non nullStream-based keystore,
// insist that the password be at least 6 characters
if (ksStream == null && storePass.length < 6) {
throw new Exception(rb.getString
("Keystore.password.must.be.at.least.6.characters"));
}
} else {
if (!protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype)
&& isKeyStoreRelated(command)
&& !isPasswordlessKeyStore) {
if (command == CERTREQ ||
command == DELETE ||
command == GENKEYPAIR ||
command == GENSECKEY ||
command == IMPORTCERT ||
command == IMPORTPASS ||
command == IMPORTKEYSTORE ||
command == KEYCLONE ||
command == CHANGEALIAS ||
command == SELFCERT ||
command == STOREPASSWD ||
command == KEYPASSWD ||
command == IDENTITYDB) {
int count = 0;
do {
if (command == IMPORTKEYSTORE) {
System.err.print
(rb.getString("Enter.destination.keystore.password."));
} else {
System.err.print
(rb.getString("Enter.keystore.password."));
}
System.err.flush();
storePass = Password.readPassword(System.in);
passwords.add(storePass);
// If we are creating a new non nullStream-based keystore,
// insist that the password be at least 6 characters
if (!nullStream && (storePass == null || storePass.length < 6)) {
System.err.println(rb.getString
("Keystore.password.is.too.short.must.be.at.least.6.characters"));
storePass = null;
}
// If the keystore file does not exist and needs to be
// created, the storepass should be prompted twice.
if (storePass != null && !nullStream && ksStream == null) {
System.err.print(rb.getString("Re.enter.new.password."));
char[] storePassAgain = Password.readPassword(System.in);
passwords.add(storePassAgain);
if (!Arrays.equals(storePass, storePassAgain)) {
System.err.println
(rb.getString("They.don.t.match.Try.again"));
storePass = null;
}
}
count++;
} while ((storePass == null) && count < 3);
if (storePass == null) {
System.err.println
(rb.getString("Too.many.failures.try.later"));
return;
}
} else {
// here we have EXPORTCERT and LIST (info valid until STOREPASSWD)
if (command != PRINTCRL && command != PRINTCERT) {
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,
// or verify the integrity of an input stream-based keystore
if (nullStream) {
keyStore.load(null, storePass);
} else if (ksStream != null) {
// Reload with user-provided password
try (FileInputStream fis = new FileInputStream(ksfile)) {
keyStore.load(fis, storePass);
}
}
}
if (storePass != null && P12KEYSTORE.equalsIgnoreCase(storetype)) {
MessageFormat form = new MessageFormat(rb.getString(
"Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
if (keyPass != null && !Arrays.equals(storePass, keyPass)) {
Object[] source = {"-keypass"};
System.err.println(form.format(source));
keyPass = storePass;
}
if (destKeyPass != null && !Arrays.equals(storePass, destKeyPass)) {
Object[] source = {"-destkeypass"};
System.err.println(form.format(source));
destKeyPass = storePass;
}
}
// -trustcacerts can be specified on -importcert, -printcert or -printcrl.
// Reset it so that warnings on CA cert will remain for other command.
if (command != IMPORTCERT && command != PRINTCERT
&& command != PRINTCRL) {
trustcacerts = false;
}
if (trustcacerts) {
KeyStore cakstore = buildTrustedCerts();
if (cakstore != null) {
caks = cakstore;
} else {
// try to load cacerts again, and let exception propagate
// if it cannot be loaded
caks = KeyStoreUtil.getCacertsKeyStore();
}
}
// Perform the specified command
if (command == CERTREQ) {
if (filename != null) {
try (PrintStream ps = new PrintStream(new FileOutputStream
(filename))) {
doCertReq(alias, sigAlgName, ps);
}
} else {
doCertReq(alias, sigAlgName, out);
}
if (verbose && filename != null) {
MessageFormat form = new MessageFormat(rb.getString
("Certification.request.stored.in.file.filename."));
Object[] source = {filename};
System.err.println(form.format(source));
System.err.println(rb.getString("Submit.this.to.your.CA"));
}
} else if (command == DELETE) {
doDeleteEntry(alias);
kssave = true;
} else if (command == EXPORTCERT) {
if (filename != null) {
try (PrintStream ps = new PrintStream(new FileOutputStream
(filename))) {
doExportCert(alias, ps);
}
} else {
doExportCert(alias, out);
}
if (filename != null) {
MessageFormat form = new MessageFormat(rb.getString
("Certificate.stored.in.file.filename."));
Object[] source = {filename};
System.err.println(form.format(source));
}
} else if (command == GENKEYPAIR) {
if (keyAlgName == null) {
throw new Exception(rb.getString(
"keyalg.option.missing.error"));
}
doGenKeyPair(alias, dname, keyAlgName, keysize, groupName, sigAlgName,
signerAlias);
kssave = true;
} else if (command == GENSECKEY) {
if (keyAlgName == null) {
throw new Exception(rb.getString(
"keyalg.option.missing.error"));
}
doGenSecretKey(alias, keyAlgName, keysize);
kssave = true;
} else if (command == IMPORTPASS) {
if (keyAlgName == null) {
keyAlgName = "PBE";
}
// password is stored as a secret key
doGenSecretKey(alias, keyAlgName, keysize);
kssave = true;
} else if (command == IDENTITYDB) {
if (filename != null) {
try (InputStream inStream = new FileInputStream(filename)) {
doImportIdentityDatabase(inStream);
}
} else {
doImportIdentityDatabase(System.in);
}
} else if (command == IMPORTCERT) {
InputStream inStream = System.in;
if (filename != null) {
inStream = new FileInputStream(filename);
}
String importAlias = (alias!=null)?alias:keyAlias;
try {
if (keyStore.entryInstanceOf(
importAlias, KeyStore.PrivateKeyEntry.class)) {
kssave = installReply(importAlias, inStream);
if (kssave) {
System.err.println(rb.getString
("Certificate.reply.was.installed.in.keystore"));
} else {
System.err.println(rb.getString
("Certificate.reply.was.not.installed.in.keystore"));
}
} else if (!keyStore.containsAlias(importAlias) ||
keyStore.entryInstanceOf(importAlias,
KeyStore.TrustedCertificateEntry.class)) {
kssave = addTrustedCert(importAlias, inStream);
if (kssave) {
System.err.println(rb.getString
("Certificate.was.added.to.keystore"));
} else {
System.err.println(rb.getString
("Certificate.was.not.added.to.keystore"));
}
}
} finally {
if (inStream != System.in) {
inStream.close();
}
}
} else if (command == IMPORTKEYSTORE) {
// When not in-place import, srcKeyStore is not loaded yet.
if (srcKeyStore == null) {
srcKeyStore = loadSourceKeyStore();
}
doImportKeyStore(srcKeyStore);
kssave = true;
} else if (command == KEYCLONE) {
keyPassNew = newPass;
// added to make sure only key can go through
if (alias == null) {
alias = keyAlias;
}
if (!keyStore.containsAlias(alias)) {
MessageFormat form = new MessageFormat
(rb.getString("Alias.alias.does.not.exist"));
Object[] source = {alias};
throw new Exception(form.format(source));
}
if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
MessageFormat form = new MessageFormat(rb.getString(
"Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key"));
Object[] source = {alias};
throw new Exception(form.format(source));
}
doCloneEntry(alias, dest, true); // Now everything can be cloned
kssave = true;
} else if (command == CHANGEALIAS) {
if (alias == null) {
alias = keyAlias;
}
doCloneEntry(alias, dest, false);
// in PKCS11, clone a PrivateKeyEntry will delete the old one
if (keyStore.containsAlias(alias)) {
doDeleteEntry(alias);
}
kssave = true;
} else if (command == KEYPASSWD) {
keyPassNew = newPass;
doChangeKeyPasswd(alias);
kssave = true;
} else if (command == LIST) {
if (storePass == null
&& !protectedPath
&& !KeyStoreUtil.isWindowsKeyStore(storetype)
&& !isPasswordlessKeyStore) {
printNoIntegrityWarning();
}
if (alias != null) {
doPrintEntry(alias, out);
} else {
doPrintEntries(out);
}
} else if (command == PRINTCERT) {
doPrintCert(out);
} else if (command == SELFCERT) {
doSelfCert(alias, dname, sigAlgName);
kssave = true;
} else if (command == STOREPASSWD) {
doChangeStorePasswd();
kssave = true;
} else if (command == GENCERT) {
if (alias == null) {
alias = keyAlias;
}
InputStream inStream = System.in;
if (infilename != null) {
inStream = new FileInputStream(infilename);
}
PrintStream ps = null;
if (outfilename != null) {
ps = new PrintStream(new FileOutputStream(outfilename));
out = ps;
}
try {
doGenCert(alias, sigAlgName, inStream, out);
} finally {
if (inStream != System.in) {
inStream.close();
}
if (ps != null) {
ps.close();
}
}
} else if (command == GENCRL) {
if (alias == null) {
alias = keyAlias;
}
if (filename != null) {
try (PrintStream ps =
new PrintStream(new FileOutputStream(filename))) {
doGenCRL(ps);
}
} else {
doGenCRL(out);
}
} else if (command == PRINTCERTREQ) {
if (filename != null) {
try (InputStream inStream = new FileInputStream(filename)) {
doPrintCertReq(inStream, out);
}
} else {
doPrintCertReq(System.in, out);
}
} else if (command == PRINTCRL) {
doPrintCRL(filename, out);
} else if (command == SHOWINFO) {
doShowInfo();
} else if (command == VERSION) {
doPrintVersion();
}
// If we need to save the keystore, do so.
if (kssave) {
if (verbose) {
MessageFormat form = new MessageFormat
(rb.getString(".Storing.ksfname."));
Object[] source = {nullStream ? "keystore" : ksfname};
System.err.println(form.format(source));
}
if (token) {
keyStore.store(null, null);
} else {
char[] pass = (storePassNew!=null) ? storePassNew : storePass;
if (nullStream) {
keyStore.store(null, pass);
} else {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
keyStore.store(bout, pass);
try (FileOutputStream fout = new FileOutputStream(ksfname)) {
fout.write(bout.toByteArray());
}
}
}
}
if (isKeyStoreRelated(command)
&& !token && !nullStream && ksfname != null) {
// JKS storetype warning on the final result keystore
File f = new File(ksfname);
char[] pass = (storePassNew!=null) ? storePassNew : storePass;
if (f.exists()) {
// Probe for real type. A JKS can be loaded as PKCS12 because
// DualFormat support, vice versa.
String realType = storetype;
try {
keyStore = KeyStore.getInstance(f, pass);
realType = keyStore.getType();
if (realType.equalsIgnoreCase("JKS")
|| realType.equalsIgnoreCase("JCEKS")) {
boolean allCerts = true;
for (String a : Collections.list(keyStore.aliases())) {
if (!keyStore.entryInstanceOf(
a, TrustedCertificateEntry.class)) {
allCerts = false;
break;
}
}
// Don't warn for "cacerts" style keystore.
if (!allCerts) {
weakWarnings.add(String.format(
rb.getString("jks.storetype.warning"),
realType, ksfname));
}
}
} catch (KeyStoreException e) {
// Probing not supported, therefore cannot be JKS or JCEKS.
// Skip the legacy type warning at all.
}
if (inplaceImport) {
String realSourceStoreType = srcstoretype;
try {
realSourceStoreType = KeyStore.getInstance(
new File(inplaceBackupName), srcstorePass).getType();
} catch (KeyStoreException e) {
// Probing not supported. Assuming srcstoretype.
}
String format =
realType.equalsIgnoreCase(realSourceStoreType) ?
rb.getString("backup.keystore.warning") :
rb.getString("migrate.keystore.warning");
weakWarnings.add(
String.format(format,
srcksfname,
realSourceStoreType,
inplaceBackupName,
realType));
}
}
}
}