/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.jini.config;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import net.jini.config.Configuration;
import net.jini.config.ConfigurationFile;
import net.jini.jeri.ssl.SslServerEndpoint;
/**
* Provides static methods for manipulating instances of {@link KeyStore}
* conveniently from within the source of a {@link Configuration}. This class
* cannot be instantiated.
*
* @author Sun Microsystems, Inc.
* @since 2.0
*/
public class KeyStores {
/** This class cannot be instantiated. */
private KeyStores() {
new AssertionError();
}
/**
* Returns a <code>KeyStore</code> initialized with contents read from a
* location specified as a file or URL. This method provides a convenient
* way to refer to keystores from within the source for a configuration,
* which may then be used with {@link #getX500Principal getX500Principal}
* to refer to principals. <p>
*
* For example, a deployer that was using {@link SslServerEndpoint} might
* use the following in the source for a {@link ConfigurationFile} to
* supply principals for use in security constraints: <p>
*
* <pre>
* Client {
* private static users = KeyStores.getKeyStore("users.ks", null);
* private static client = KeyStores.getX500Principal("client", users);
* //...
* }
* </pre>
*
* @param location the file name or URL containing the
* <code>KeyStore</code> contents
* @param type the type of <code>KeyStore</code> to create, or
* <code>null</code> for the default type
* @return the <code>KeyStore</code>, with contents read from
* <code>location</code>
* @throws GeneralSecurityException if there are problems with the contents
* @throws IOException if an I/O error occurs when reading from
* <code>location</code>
* @throws NullPointerException if <code>location</code> is
* <code>null</code>
* @see #getX500Principal getX500Principal
*/
public static KeyStore getKeyStore(String location, String type)
throws GeneralSecurityException, IOException
{
if (location == null) {
throw new NullPointerException("location cannot be null");
}
KeyStore keystore;
InputStream in = null;
try {
try {
URL url = new URL(location);
in = url.openStream();
} catch (MalformedURLException e) {
in = new FileInputStream(location);
}
in = new BufferedInputStream(in);
keystore = KeyStore.getInstance(
type != null ? type : KeyStore.getDefaultType());
keystore.load(in, null);
return keystore;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
/**
* Returns the <code>X500Principal</code> for the alias in a
* <code>KeyStore</code>; or <code>null</code> if the alias is not found,
* if the alias is not associated with a certificate, or if the certificate
* is not an {@link X509Certificate}. This method provides a convenient way
* to refer to principals from within the source for a configuration by
* specifying aliases when used with {@link #getKeyStore getKeystore}. <p>
*
* For example, a deployer that was using {@link SslServerEndpoint} might
* use the following in the source for a {@link ConfigurationFile} to
* supply principals for use in security constraints: <p>
*
* <pre>
* Client {
* private static users = KeyStores.getKeyStore("users.ks", null);
* private static client = KeyStores.getX500Principal("client", users);
* //...
* }
* </pre>
*
* @param alias the alias
* @param keystore the <code>KeyStore</code>
* @return the <code>X500Principal</code> or <code>null</code>
* @throws KeyStoreException if the keystore has not been initialized
* (loaded)
* @throws NullPointerException if either argument is <code>null</code>
* @see #getKeyStore getKeyStore
*/
public static X500Principal getX500Principal(String alias,
KeyStore keystore)
throws KeyStoreException
{
if (alias == null) {
throw new NullPointerException("alias is null");
} else if (keystore == null) {
throw new NullPointerException("keystore is null");
}
Certificate cert = keystore.getCertificate(alias);
if (cert instanceof X509Certificate) {
return ((X509Certificate) cert).getSubjectX500Principal();
}
return null;
}
}