001 /*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.11/src/java/org/apache/commons/ssl/TomcatServerXML.java $
003 * $Revision: 121 $
004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005 *
006 * ====================================================================
007 * Licensed to the Apache Software Foundation (ASF) under one
008 * or more contributor license agreements. See the NOTICE file
009 * distributed with this work for additional information
010 * regarding copyright ownership. The ASF licenses this file
011 * to you under the Apache License, Version 2.0 (the
012 * "License"); you may not use this file except in compliance
013 * with the License. You may obtain a copy of the License at
014 *
015 * http://www.apache.org/licenses/LICENSE-2.0
016 *
017 * Unless required by applicable law or agreed to in writing,
018 * software distributed under the License is distributed on an
019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020 * KIND, either express or implied. See the License for the
021 * specific language governing permissions and limitations
022 * under the License.
023 * ====================================================================
024 *
025 * This software consists of voluntary contributions made by many
026 * individuals on behalf of the Apache Software Foundation. For more
027 * information on the Apache Software Foundation, please see
028 * <http://www.apache.org/>.
029 *
030 */
031
032 package org.apache.commons.ssl;
033
034 import org.w3c.dom.Document;
035 import org.w3c.dom.Element;
036 import org.w3c.dom.NodeList;
037
038 import javax.xml.parsers.DocumentBuilder;
039 import javax.xml.parsers.DocumentBuilderFactory;
040 import java.io.File;
041 import java.io.FileInputStream;
042 import java.io.IOException;
043 import java.io.InputStream;
044 import java.util.Collections;
045 import java.util.Map;
046 import java.util.SortedMap;
047 import java.util.TreeMap;
048
049 /**
050 * @author Credit Union Central of British Columbia
051 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
052 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
053 * @since 22-Feb-2007
054 */
055 public class TomcatServerXML {
056 private final static LogWrapper log = LogWrapper.getLogger(TomcatServerXML.class);
057
058 /**
059 * KeyMaterial extracted from Tomcat's conf/server.xml. There might be
060 * several KeyMaterials to extract if Tomcat has different SSL Certificates
061 * listening on different ports. This particular KeyMaterial will come from
062 * the lowest secure port that Tomcat is properly configured to open.
063 */
064 public final static KeyMaterial KEY_MATERIAL;
065
066 /**
067 * TrustMaterial extracted from Tomcat's conf/server.xml. There might be
068 * several TrustMaterials to extract if Tomcat has different SSL Certificates
069 * listening on different ports. This particular TrustMaterial will come
070 * from the lowest secure port that Tomcat is properly configured to open.
071 * </p><p>
072 * There's a good chance this will be set to TrustMaterial.DEFAULT (which
073 * use's the JVM's '$JAVA_HOME/jre/lib/security/cacerts' file).
074 * </p><p>
075 * Note: With SSLServerSockets, TrustMaterial only matters when the
076 * incoming client socket (SSLSocket) presents a client certificate.
077 * </p>
078 */
079 public final static TrustMaterial TRUST_MATERIAL;
080
081 /**
082 * new Integer( port ) --> KeyMaterial mapping of SSL Certificates found
083 * inside Tomcat's conf/server.xml file.
084 */
085 public final static SortedMap KEY_MATERIAL_BY_PORT;
086
087 /**
088 * new Integer( port ) --> TrustMaterial mapping of SSL configuration
089 * found inside Tomcat's conf/server.xml file.
090 * </p><p>
091 * Many of these will probably be TrustMaterial.DEFAULT (which uses the
092 * JVM's '$JAVA_HOME/jre/lib/security/cacerts' file).
093 * </p><p>
094 * Note: With SSLServerSockets, TrustMaterial only matters when the
095 * incoming client socket (SSLSocket) presents a client certificate.
096 * </p>
097 */
098 public final static SortedMap TRUST_MATERIAL_BY_PORT;
099
100 static {
101 String tomcatHome = System.getProperty("catalina.home");
102 String serverXML = tomcatHome + "/conf/server.xml";
103 TreeMap keyMap = new TreeMap();
104 TreeMap trustMap = new TreeMap();
105 InputStream in = null;
106 Document doc = null;
107 try {
108 if (tomcatHome != null) {
109 File f = new File(serverXML);
110 if (f.exists()) {
111 try {
112 in = new FileInputStream(serverXML);
113 }
114 catch (IOException ioe) {
115 // oh well, no soup for us.
116 log.warn("Commons-SSL failed to load Tomcat's [" + serverXML + "] " + ioe);
117 }
118 }
119 }
120 if (in != null) {
121 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
122 try {
123 DocumentBuilder db = dbf.newDocumentBuilder();
124 doc = db.parse(in);
125 }
126 catch (Exception e) {
127 log.warn("Commons-SSL failed to parse Tomcat's [" + serverXML + "] " + e);
128 }
129 }
130 if (doc != null) {
131 loadTomcatConfig(doc, keyMap, trustMap);
132 }
133 }
134 finally {
135 if (in != null) {
136 try { in.close(); } catch (Exception e) { /* . */ }
137 }
138 }
139 KEY_MATERIAL_BY_PORT = Collections.unmodifiableSortedMap(keyMap);
140 TRUST_MATERIAL_BY_PORT = Collections.unmodifiableSortedMap(trustMap);
141
142 KeyMaterial km = null;
143 TrustMaterial tm = null;
144 if (!keyMap.isEmpty()) {
145 km = (KeyMaterial) keyMap.get(keyMap.firstKey());
146 }
147 if (!trustMap.isEmpty()) {
148 tm = (TrustMaterial) trustMap.get(trustMap.firstKey());
149 }
150 KEY_MATERIAL = km;
151 TRUST_MATERIAL = tm;
152
153 }
154
155 private static void loadTomcatConfig(Document d, Map keyMap, Map trustMap) {
156 final String userHome = System.getProperty("user.home");
157 NodeList nl = d.getElementsByTagName("Connector");
158 for (int i = 0; i < nl.getLength(); i++) {
159 KeyMaterial km = null;
160 TrustMaterial tm = null;
161
162 Element element = (Element) nl.item(i);
163 String secure = element.getAttribute("secure");
164 String portString = element.getAttribute("port");
165 Integer port = null;
166 String pass;
167 try {
168 portString = portString != null ? portString.trim() : "";
169 port = new Integer(portString);
170 }
171 catch (NumberFormatException nfe) {
172 // oh well
173 }
174 if (port != null && Util.isYes(secure)) {
175 // Key Material
176 String keystoreFile = element.getAttribute("keystoreFile");
177 pass = element.getAttribute("keystorePass");
178 if (!element.hasAttribute("keystoreFile")) {
179 keystoreFile = userHome + "/.keystore";
180 }
181 if (!element.hasAttribute("keystorePass")) {
182 pass = "changeit";
183 }
184 char[] keystorePass = pass != null ? pass.toCharArray() : null;
185
186 // Trust Material
187 String truststoreFile = element.getAttribute("truststoreFile");
188 pass = element.getAttribute("truststorePass");
189 if (!element.hasAttribute("truststoreFile")) {
190 truststoreFile = null;
191 }
192 if (!element.hasAttribute("truststorePass")) {
193 pass = null;
194 }
195 char[] truststorePass = pass != null ? pass.toCharArray() : null;
196
197
198 if (keystoreFile == null) {
199 km = null;
200 } else {
201 try {
202 km = new KeyMaterial(keystoreFile, keystorePass);
203 }
204 catch (Exception e) {
205 log.warn("Commons-SSL failed to load [" + keystoreFile + "] " + e);
206 }
207 }
208 if (truststoreFile == null) {
209 tm = TrustMaterial.DEFAULT;
210 } else {
211 try {
212 tm = new TrustMaterial(truststoreFile, truststorePass);
213 }
214 catch (Exception e) {
215 log.warn("Commons-SSL failed to load [" + truststoreFile + "] " + e);
216 }
217 }
218
219 Object o = keyMap.put(port, km);
220 if (o != null) {
221 log.debug("Commons-SSL TomcatServerXML keyMap clobbered port: " + port);
222 }
223 o = trustMap.put(port, tm);
224 if (o != null) {
225 log.debug("Commons-SSL TomcatServerXML trustMap clobbered port: " + port);
226 }
227 }
228 }
229 }
230
231 }