001: /**
002: * $Id: PSX509TrustManager.java,v 1.4 2006/11/28 13:18:48 vk162573 Exp $
003: * Copyright 2006 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.admin.common.util;
014:
015: import java.io.File;
016: import java.io.FileInputStream;
017: import java.io.FileNotFoundException;
018: import java.io.FileOutputStream;
019: import java.io.InputStream;
020: import java.io.IOException;
021: import java.net.UnknownHostException;
022: import java.security.KeyStore;
023: import java.security.cert.CertificateEncodingException;
024: import java.security.cert.CertificateException;
025: import java.security.cert.CertificateExpiredException;
026: import java.security.cert.CertificateNotYetValidException;
027: import java.security.cert.CertificateParsingException;
028: import java.security.cert.X509Certificate;
029: import java.util.Collections;
030: import java.util.Iterator;
031: import java.util.Properties;
032: import java.util.Set;
033:
034: import javax.net.ssl.TrustManager;
035: import javax.net.ssl.TrustManagerFactory;
036: import javax.net.ssl.X509TrustManager;
037:
038: import com.sun.portal.admin.common.DomainAttributes;
039: import com.sun.portal.admin.common.context.PortalDomainContext;
040:
041: /**
042: * This class is a special trust manager that trusts the Cacao daemon
043: * running on a host that has PS already installed.
044: */
045: public class PSX509TrustManager implements X509TrustManager {
046: static final char[] TRUSTSTORE_PASSWORD = "password".toCharArray();
047: File truststorePath = null;
048: KeyStore truststore = null;
049:
050: /*
051: * The default X509TrustManager returned by SunX509. We'll delegate
052: * decisions to it, and fall back to the logic in this class if the
053: * default X509TrustManager doesn't trust it.
054: */
055: X509TrustManager sunJSSEX509TrustManager = null;
056:
057: PSX509TrustManager(String psConfigDir) throws SecurityException,
058: IOException {
059:
060: FileInputStream fis = null;
061:
062: if (psConfigDir != null) {
063: truststorePath = new File(psConfigDir, "truststore");
064:
065: try {
066: fis = new FileInputStream(truststorePath);
067: } catch (FileNotFoundException e) {
068: // the truststore file doesn't exist yet
069: }
070: }
071:
072: try {
073: truststore = KeyStore.getInstance("JKS");
074: truststore.load(fis, TRUSTSTORE_PASSWORD);
075: initializeDefaultX509TrustManager();
076:
077: if (sunJSSEX509TrustManager == null) {
078: throw new SecurityException(
079: "No default X509TrustManager");
080: }
081: } catch (Exception e) {
082: SecurityException se = new SecurityException(
083: "Unable to create TrustManager");
084:
085: se.initCause(e);
086: throw se;
087: } finally {
088: if (fis != null) {
089: fis.close();
090: }
091: }
092: }
093:
094: // Documented in X509TrustManager
095: public void checkClientTrusted(X509Certificate[] chain,
096: String authType) throws CertificateException {
097:
098: // this trust manager is dedicated to server authentication
099: throw new CertificateException(
100: "Client authentication not supported");
101: }
102:
103: // Documented in X509TrustManager
104: public void checkServerTrusted(X509Certificate[] chain,
105: String authType) throws CertificateException {
106:
107: try {
108: sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
109: } catch (CertificateException e) {
110: if ((e instanceof CertificateEncodingException)
111: || (e instanceof CertificateExpiredException)
112: || (e instanceof CertificateNotYetValidException)
113: || (e instanceof CertificateParsingException)) {
114:
115: throw e;
116: }
117:
118: // The subject DN should have the form "CN=<hostname>_agent"
119: String subjectDN = chain[0].getSubjectDN().getName();
120:
121: if (!subjectDN.startsWith("CN=")
122: || !subjectDN.endsWith("_agent")) {
123: // Most likely the server isn't a Cacao agent because
124: // the subject DN doesn't have the right form.
125: throw e;
126: }
127:
128: String hostName = subjectDN.substring(3,
129: subjectDN.length() - 6);
130:
131: // The subject DN could be either "CN=<hostname>_agent" or
132: // "CN=<hostname>_default_agent"
133: if (hostName.endsWith("_default")) {
134: hostName = hostName.substring(0, hostName.length() - 8);
135: }
136:
137: System.out.println(hostName);
138:
139: // Trust the server cert chain if PS is installed on that
140: // host, or in the case of the console, if that host is
141: // specified in pasconnect.properties or is the local host.
142: if (!isPSInstalledOn(hostName)
143: && !isConsoleTrustedHost(hostName)) {
144: throw e;
145: }
146:
147: // Add the root CA cert to the truststore.
148: addToTruststore(hostName, chain[chain.length - 1]);
149: }
150: }
151:
152: // Documented in X509TrustManager
153: public X509Certificate[] getAcceptedIssuers() {
154: return sunJSSEX509TrustManager.getAcceptedIssuers();
155: }
156:
157: private void initializeDefaultX509TrustManager() throws Exception {
158: TrustManagerFactory tmf = TrustManagerFactory
159: .getInstance("SunX509");
160: tmf.init(truststore);
161: TrustManager[] tms = tmf.getTrustManagers();
162:
163: /*
164: * Iterate over the returned trustmanagers, look
165: * for an instance of X509TrustManager. If found,
166: * use that as our "default" trust manager.
167: */
168: for (int i = 0; i < tms.length; i++) {
169: if (tms[i] instanceof X509TrustManager) {
170: sunJSSEX509TrustManager = (X509TrustManager) tms[i];
171: return;
172: }
173: }
174: }
175:
176: private boolean isPSInstalledOn(String hostName) {
177: try {
178: PortalDomainContext pdc = AdminUtil
179: .getPortalDomainContext();
180:
181: Set installedHosts = pdc.getAttributeValues(
182: AdminUtil.PORTAL_DOMAIN_MBEAN_TYPE, Collections
183: .singletonList(pdc.getID()),
184: DomainAttributes.INSTALLED_HOSTS);
185:
186: for (Iterator i = installedHosts.iterator(); i.hasNext();) {
187: if (AdminUtil.isSameHost(hostName, (String) i.next())) {
188: return true;
189: }
190: }
191:
192: return false;
193: } catch (Exception e) {
194: return false;
195: }
196: }
197:
198: private boolean isConsoleTrustedHost(String hostName) {
199: InputStream is = getClass().getClassLoader()
200: .getResourceAsStream("pasconnect.properties");
201:
202: if (is != null) { // running inside the console
203: Properties pasSettings = new Properties();
204: String trustedHost = "localhost";
205:
206: try {
207: pasSettings.load(is);
208: String pasHost = pasSettings
209: .getProperty("pas.host", "").trim();
210:
211: if (pasHost.length() > 0) {
212: trustedHost = pasHost;
213: }
214: } catch (IOException e) {
215: }
216:
217: try {
218: if (trustedHost.equals("localhost")) {
219: return AdminUtil.isLocal(hostName);
220: } else {
221: return AdminUtil.isSameHost(hostName, trustedHost);
222: }
223: } catch (UnknownHostException e) {
224: return false;
225: }
226: }
227:
228: return false;
229: }
230:
231: private void addToTruststore(String alias, X509Certificate cert) {
232: FileOutputStream fos = null;
233:
234: try {
235: truststore.setCertificateEntry(alias, cert);
236: initializeDefaultX509TrustManager();
237:
238: if (truststorePath != null) {
239: fos = new FileOutputStream(truststorePath);
240: truststore.store(fos, TRUSTSTORE_PASSWORD);
241: }
242: } catch (Exception e) {
243: } finally {
244: if (fos != null) {
245: try {
246: fos.close();
247: } catch (Exception e) {
248: }
249: }
250: }
251: }
252: }
|