Hi,

the problem that Tomcat can be shut down by any local user via
AJP12 has been discussed on this list quite some time ago. It
was fixed on the 3.3 branch, but iirc the fix was considered to
big a change for the 3.2 branch. Since this is a rather painful
problem on multiuser systems, I did a crude fix for 3.2.2 along
the lines of what went into 3.3. It does change the shutdown
behaviour, but here's the patch anyway in case it's useful for
anyone.

-- 
Stephan Seyboth - Developer
Caldera (Deutschland) GmbH
http://www.caldera.de/
? jakarta-tomcat-3.2.2-shutdown.patch
Index: src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/Ajp12ConnectionHandler.java,v
retrieving revision 1.28.2.4
diff -u -r1.28.2.4 Ajp12ConnectionHandler.java
--- src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java	2001/05/11 22:37:23	1.28.2.4
+++ src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java	2001/06/27 17:05:25
@@ -83,11 +83,14 @@
     static StringManager sm = StringManager.getManager("org.apache.tomcat.service");
 
     ContextManager contextM;
+    private static String secret;
 
     public Ajp12ConnectionHandler() {
     }
 
     public Object[] init() {
+	if(secret==null)
+	    setSecret(contextM);
 	Object thData[]=new Object[2];
 	AJP12RequestAdapter reqA=new AJP12RequestAdapter();
 	AJP12ResponseAdapter resA=new AJP12ResponseAdapter();
@@ -98,6 +101,38 @@
 	return  thData;
     }
 
+    /* Produce a cookie file that is used to authorize shutdown
+     * requests so they can not be triggered by anyone
+     */
+    public static void setSecret(ContextManager contextM) {
+	secret=Double.toString(Math.random());
+	try {
+	    PrintWriter stopF=new PrintWriter
+		(new FileWriter(contextM.getHome() + "/conf/ajp12.id"));
+	    stopF.println( secret );
+	    stopF.close();
+	} catch( IOException ex ) {
+	    contextM.log( "Can't create " + contextM.getHome()
+			  + "/conf/ajp12.id " + ex );
+	}
+    }
+
+    public static String getSecret(ContextManager contextM) {
+	if (secret!=null)
+	    return secret;
+	try {
+	    BufferedReader stopF=new BufferedReader
+		( new FileReader(contextM.getHome() + "/conf/ajp12.id"));
+	    secret=stopF.readLine();
+	    stopF.close();
+	} catch( IOException ex ) {
+	    contextM.log("Can't read " + contextM.getHome()
+			       + "/conf/ajp12.id");
+	    secret=null;
+	}
+	return secret;
+    }
+
     public void setAttribute(String name, Object value ) {
 	if("context.manager".equals(name) ) {
 	    contextM=(ContextManager)value;
@@ -390,13 +425,20 @@
 		    } else {
 			try {
 			    // close the socket connection before handling any signal
-			    // but get the addresses first so they are not corrupted
+			    // but get the addresses and secret first so they are not corrupted
 			    InetAddress serverAddr = socket.getLocalAddress();
 			    InetAddress clientAddr = socket.getInetAddress();
+			    String cookie=ajpin.readString("");
 			    sin.close();
+			    String secret=Ajp12ConnectionHandler.getSecret(contextM);
 			    if ( (signal== 15) &&
 				 isSameAddress(serverAddr, clientAddr) ) {
 				// Shutdown - probably apache was stoped with apachectl stop
+				// check cookie to make sure shutdown is legitimate
+				if( !secret.equals( cookie)) {
+				    contextM.log("Attempt to stop Tomcat with the wrong secret!");
+				    return;
+				}
 				contextM.stop();
 				// same behavior as in past, because it seems that
 				// stopping everything doesn't work - need to figure
Index: src/share/org/apache/tomcat/task/StopTomcat.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/task/Attic/StopTomcat.java,v
retrieving revision 1.2
diff -u -r1.2 StopTomcat.java
--- src/share/org/apache/tomcat/task/StopTomcat.java	2000/06/23 02:16:27	1.2
+++ src/share/org/apache/tomcat/task/StopTomcat.java	2001/06/27 17:05:31
@@ -99,6 +99,12 @@
 	    }
 	}
 
+	// Read the secret cookie
+	String secret=Ajp12ConnectionHandler.getSecret(cm);
+	if (secret==null) {
+	    System.out.println("Can't read secret for shutdown, aborting!");
+	    System.exit(1);
+	}
 	// use Ajp12 to stop the server...
 	try {
 	    Socket socket = new Socket("localhost", portInt);
@@ -107,6 +113,10 @@
 	    stopMessage[0]=(byte)254;
 	    stopMessage[1]=(byte)15;
 	    os.write( stopMessage );
+	    int len=secret.length();
+	    os.write( len/256 );
+	    os.write( len%256 );
+	    os.write( secret.getBytes() );// works only for ascii	    
 	    socket.close();
 	} catch(Exception ex ) {
 	    ex.printStackTrace();

Reply via email to