private void loadTruststore()

in taverna-credential-manager-impl/src/main/java/org/apache/taverna/security/credentialmanager/impl/CredentialManagerImpl.java [467:655]


	private void loadTruststore() throws CMException {
		if (truststore == null) {
			try {
				// Try to create Taverna's Truststore as Bouncy Castle UBER-type
				// keystore.
				truststore = KeyStore.getInstance("UBER", "BC");
			} catch (Exception ex) {
				// The requested keystore type is not available from security
				// providers.
				throw new CMException("Failed to instantiate Taverna's Truststore", ex);
			}

			if (truststoreFile.exists()) {
				// If the Truststore file already exists, open it and load the
				// Truststore
				try (FileInputStream fis = new FileInputStream(truststoreFile)) {
					// Load the Truststore from the file
					truststore.load(fis, masterPassword.toCharArray());
					
					// Delete the old revoked or unnecessary BioCatalogue,
					// BiodiversityCatalogue and heater's certificates, if present
					deleteRevokedCertificates();
					
				} catch (Exception ex) {
					/* Clear out things that are useless/hindering now */
					truststore = null;
					masterPassword = null;
					String exMessage = "Failed to load Taverna's Truststore from "
							+ truststoreFile.getAbsolutePath()
							+ ". Possible reason: incorrect password or corrupted file.";
					logger.error(exMessage, ex);
					throw new CMException(exMessage, ex);
				}
			} else {
				/*
				 * Otherwise create a new empty Truststore and load it with
				 * certs from Java's truststore.
				 */
				File javaTruststoreFile = new File(
						System.getProperty("java.home"), "lib/security/cacerts");
				KeyStore javaTruststore = null;

				// Java's truststore is of type "JKS" - try to load it
				try {
					javaTruststore = KeyStore.getInstance("JKS");
				} catch (Exception ex) {
					// The requested keystore type is not available from the
					// provider
					throw new CMException("Failed to instantiate a 'JKS'-type keystore "
							+ "for reading Java's truststore.", ex);
				}

				boolean loadedJavaTruststore = false;
				/*
				 * Load Java's truststore from the file - try with the default
				 * Java truststore passwords.
				 */
				for (String password : defaultTrustStorePasswords) {
					logger.info("Trying to load Java truststore using password: "
							+ password);
					try (FileInputStream fis = new FileInputStream(
							javaTruststoreFile)) {
						javaTruststore.load(fis, password.toCharArray());
						loadedJavaTruststore = true;
						break;
					} catch (IOException ioex) {
						/*
						 * If there is an I/O or format problem with the
						 * keystore data, or if the given password was incorrect
						 * (Thank you Sun, now I can't know if it is the file or
						 * the password..)
						 */
						logger.info(String
								.format("Failed to load the Java truststore to copy "
										+ "over certificates using default password: "
										+ "%s from %s", password,
										javaTruststoreFile));
					} catch (NoSuchAlgorithmException e) {
						logger.error("Unknown encryption algorithm "
								+ "while loading Java truststore from "
								+ javaTruststoreFile, e);
						break;
					} catch (CertificateException e) {
						logger.error("Certificate error while "
								+ "loading Java truststore from "
								+ javaTruststoreFile, e);
						break;
					}
				}

				/*
				 * Default Java truststore passwords failed - possibly the user
				 * has changed it. Ask the Java truststore password providers if
				 * they can help - this will typically pop up a dialog to ask
				 * the user if we are in a graphical environment. If not, we
				 * will simply not copy the default truststore certificates into
				 * Credential Manager's Truststore.
				 */
				if (!loadedJavaTruststore)
					if (!(loadJavaTruststoreUsingPasswordProviders(
							javaTruststore, javaTruststoreFile))) {
						String error = "Credential manager failed to load"
								+ " certificates from Java's truststore.";
						String help = "Try using the system property -D"
								+ PROPERTY_TRUSTSTORE_PASSWORD
								+ "=TheTrustStorePassword";
						logger.error(error + " " + help);
						// FIXME Writes to standard error!
						System.err.println(error);
						System.err.println(help);
					}

				// Create a new empty Truststore for Taverna
				try (FileOutputStream fos = new FileOutputStream(truststoreFile)) {
					truststore.load(null, null);
					if (loadedJavaTruststore) {
						// Copy certificates into Taverna's Truststore from
						// Java's truststore.
						Enumeration<String> aliases = javaTruststore.aliases();
						while (aliases.hasMoreElements()) {
							Certificate certificate = javaTruststore
									.getCertificate(aliases.nextElement());
							if (certificate instanceof X509Certificate)
								truststore
										.setCertificateEntry(
												createTrustedCertificateAlias((X509Certificate) certificate),
												certificate);
						}
					}

					// Insert special trusted CA certificates
					logger.info("Loading certificates of trusted CAs so as to establish trust into our services such as BioCatalogue, BiodiversityCatalogue, heater, etc.");	
					CertificateFactory cf = CertificateFactory
							.getInstance("X.509");
					for (URL trustedCertURL : getSpecialTrustedCertificates())
						// Load the certificate (possibly a chain) from the
						// stream
						try (InputStream stream = trustedCertURL.openStream()) {
							for (Certificate c : cf
									.generateCertificates(stream))
								truststore
										.setCertificateEntry(
												createTrustedCertificateAlias((X509Certificate) c),
												c);
						} catch (Exception cex) {
							logger.error("Failed to insert trusted certificate entry in the Truststore", cex);
						}

					// Immediately save the new Truststore to the file
					truststore.store(fos, masterPassword.toCharArray());
				} catch (Exception ex) {
					/*
					 * make truststore null as it was just created but failed to
					 * save so we should retry next time
					 */
					truststore = null;
					throw new CMException("Failed to generate new empty Taverna's Truststore", ex);
				}
			}

			/*
			 * Taverna distro for MAC contains info.plist file with some Java
			 * system properties set to use the Keychain which clashes with what
			 * we are setting here so we need to clear them.
			 */
			System.clearProperty(PROPERTY_TRUSTSTORE_TYPE);
			System.clearProperty(PROPERTY_TRUSTSTORE_PROVIDER);

			/*
			 * Not quite sure why we still need to set these two properties
			 * since we are creating our own SSLSocketFactory with our own
			 * TrustManager that uses Taverna's Truststore, but seem like after
			 * Taverna starts up and the first time it needs SSLSocketFactory
			 * for HTTPS connection it is still using the default Java's
			 * truststore unless these properties are set. Set the system
			 * property "javax.net.ssl.Truststore" to use Taverna's truststore.
			 */

			/*
			 * Axis 1 likes reading from these properties but seems to work as
			 * well with Taverna's SSLSocetFactory as well. We do not want to
			 * expose these as they can be read from Beanshells.
			 */
			// System.setProperty(PROPERTY_TRUSTSTORE, truststoreFile.getAbsolutePath());
			// System.setProperty(PROPERTY_TRUSTSTORE_PASSWORD, masterPassword);
			System.clearProperty(PROPERTY_TRUSTSTORE);
			System.clearProperty(PROPERTY_TRUSTSTORE_PASSWORD);
		}
	}