Bug 27050

Summary: keystoreFile parameter, when specified as relative, is not treated relative to $CATALINA_BASE or catalina.base property
Product: Tomcat 5 Reporter: Dominik Drzewiecki <drzewo>
Component: Connector:CoyoteAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: critical    
Priority: P3    
Version: 5.0.19   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   

Description Dominik Drzewiecki 2004-02-18 21:51:47 UTC
Tomcat docs on configuring SSL says (on keystoreFile attribute of http
Connector): "You can specify an absolute pathname, or a relative pathname that
is resolved against the $CATALINA_BASE environment variable." 

However, specifying relative keystoreFile does not make tomcat resolve this file
against $CATALINA_BASE (or -Dcatalina.base property). It seems it is resolved
against current working directory.

How to reproduce this error:
1. install tomcat (as nt service)
2. create separate (striped down) base (say <BASE>) somewhere on your disk
(conf, logs, work, temp, webapps(empty) directories)
3. create keystore <BASE>/conf/catalina.keystore
4. update <BASE>/conf/server.xml to enable https connector as 
    <Connector port="9443" 
     maxThreads="50" minSpareThreads="5" maxSpareThreads="25"
     enableLookups="false" disableUploadTimeout="true"
     acceptCount="100" debug="0" scheme="https" secure="true"
     clientAuth="false" sslProtocol="TLS" 
     keystoreFile="conf/catalina.keystore"
    />
5. using tomcatw.exe" //ES//Tomcat5 update "java options" so they reference new
base, particularly append -Dcatalina.base="<BASE>" to "Java Options"
6. net start tomcat5
7. observe stdout.log
2004-02-18 22:25:42 org.apache.coyote.http11.Http11Protocol init
SEVERE: Error initializing endpoint
java.io.FileNotFoundException: conf\catalina.keystore (The system cannot find
the file specified)
8. now, use tomcatw.exe" //ES//Tomcat5 in order to update Service "Work Path" to
refer to the new base
9. Now tomcat DOES start https and finds conf/catalina.keystore relative to the
new work dir

How to obtain this error (the easier way):
1. unpack/install tomcat
2. create separate (striped down) base (say <BASE>) somewhere on your disk (bin,
conf, logs, work, temp, webapps(empty) directories)
3. create keystore <BASE>/conf/catalina.keystore
4. update <BASE>/conf/server.xml to enable https connector as 
    <Connector port="9443" 
     maxThreads="50" minSpareThreads="5" maxSpareThreads="25"
     enableLookups="false" disableUploadTimeout="true"
     acceptCount="100" debug="0" scheme="https" secure="true"
     clientAuth="false" sslProtocol="TLS" 
     keystoreFile="conf/catalina.keystore"
    />
5. open cmd
6. set CATALINA_BASE=<BASE> (dir containing conf subdir)
7. cd %CATALINA_BASE%\bin
8. catalina.bat start
9. oops, we're still getting 
2004-02-18 22:25:42 org.apache.coyote.http11.Http11Protocol init
SEVERE: Error initializing endpoint
java.io.FileNotFoundException: conf\catalina.keystore (The system cannot find
the file specified)
10. cd ..
11. bin\catalina.bat start
12. NO java.io.FNFE this time

All this leads me to the conclusion that keystoreFile attribute value is
resolved against current working directory instaed of $CATALINA_BASE
Probably truststoreFile attribute suffers from the same problem.

Tested on both j2sdk1.4.2_03 as well on j2sdk1.5.0-beta1
Comment 1 Jan Luehe 2004-02-18 22:40:41 UTC
Fixed.

DIFFS:

Index: JSSESocketFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java,v
retrieving revision 1.13
diff -u -r1.13 JSSESocketFactory.java
--- JSSESocketFactory.java      24 Jan 2004 04:56:32 -0000      1.13
+++ JSSESocketFactory.java      18 Feb 2004 22:39:36 -0000
@@ -58,6 +58,7 @@
  */ 
 package org.apache.tomcat.util.net.jsse;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -309,7 +310,13 @@
         InputStream istream = null;
         try {
             ks = KeyStore.getInstance(type);
-            istream = new FileInputStream(path);
+            File keyStoreFile = new File(path);
+            if (!keyStoreFile.isAbsolute()) {
+                keyStoreFile = new File(System.getProperty("catalina.base"),
+                                        path);
+            }
+            istream = new FileInputStream(keyStoreFile);
+
             ks.load(istream, pass.toCharArray());
             istream.close();
             istream = null;