costin 02/02/06 21:07:36
Modified: src/share/org/apache/tomcat/modules/server
Ajp13Interceptor.java
Log:
Added the logic to check for the password on ajp13 connections.
Also cut&paste the logic to generate the 'ajp13.id' if useSecret is set
( with a random generated password and the connection info ). If a
secret is set, shutdown via ajp13 is enabled automatically.
All normal code is running as before if no secret is set.
Revision Changes Path
1.18 +110 -6
jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13Interceptor.java
Index: Ajp13Interceptor.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13Interceptor.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- Ajp13Interceptor.java 4 Oct 2001 20:27:47 -0000 1.17
+++ Ajp13Interceptor.java 7 Feb 2002 05:07:36 -0000 1.18
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13Interceptor.java,v
1.17 2001/10/04 20:27:47 costin Exp $
- * $Revision: 1.17 $
- * $Date: 2001/10/04 20:27:47 $
+ * $Header:
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13Interceptor.java,v
1.18 2002/02/07 05:07:36 costin Exp $
+ * $Revision: 1.18 $
+ * $Date: 2002/02/07 05:07:36 $
*
* ====================================================================
*
@@ -70,6 +70,7 @@
import org.apache.tomcat.util.net.*;
import org.apache.tomcat.util.*;
import org.apache.tomcat.util.log.*;
+import org.apache.tomcat.util.io.FileUtil;
/* Frozen, bug fixes only: all active development goes in
jakarta-tomcat-connectors/jk/org/apache/ajp/Ajp14*
@@ -85,6 +86,8 @@
private boolean decoded=true;
private int decodedNote;
+ private String secret;
+ private File ajpidFile;
public Ajp13Interceptor()
{
@@ -109,6 +112,36 @@
shutDownEnable=b;
}
+ /** Enable the use of a secret. The secret will be
+ * randomly generated. mod_jk must read the secret to
+ * communicate with tomcat.
+ *
+ * Note that we don't use the secret only for shutdown, but
+ * for normal request processing. A 'bad' request may forge
+ * auth, etc.
+ */
+ public void setUseSecret(boolean b ) {
+ secret=Double.toString(Math.random());
+ }
+
+ /** Set the 'secret'. If this is set, all sensitive operations
+ * will be disabled unless the request includes a password.
+ *
+ * This requires a recent version of mod_jk and the
+ * worker.NAME.secret property in workers.properties.
+ */
+ public void setSecret( String s ) {
+ secret=s;
+ shutDownEnable=true;
+ }
+
+ /** Specify ajpid file used when shutting down tomcat
+ */
+ public void setAjpidFile( String path ) {
+ ajpidFile=( path==null?null:new File(path));
+ }
+
+
public void setDecodedUri( boolean b ) {
decoded=b;
}
@@ -125,6 +158,50 @@
"req.decoded" );
}
+ public void engineState(ContextManager cm, int state )
+ throws TomcatException
+ {
+
+ if( state==ContextManager.STATE_START ) {
+ // the engine is now started, create the ajp12.id
+ // file that will allow us to stop the server and
+ // know that the server is started ok.
+ Ajp13Interceptor tcpCon=this;
+ int portInt=tcpCon.getPort();
+ InetAddress address=tcpCon.getAddress();
+ File sf=FileUtil.getConfigFile(ajpidFile, new File(cm.getHome()),
+ "conf/ajp13.id");
+ Properties props=new Properties();
+
+ if( ajpidFile != null || debug > 0)
+ log( "Using stop file: "+sf);
+ try {
+ // PrintWriter stopF=new PrintWriter
+ // (new FileWriter(sf));
+ FileOutputStream stopF=new FileOutputStream( sf );
+ props.put( "port", Integer.toString( portInt ));
+ // stopF.println( portInt );
+ if( address==null ) {
+ // stopF.println( "" );
+ } else {
+ //stopF.println( address.getHostAddress() );
+ props.put( "address", address.getHostAddress() );
+ }
+ if( secret !=null ) {
+ //stopF.println( secret );
+ props.put( "secret", secret );
+ } else {
+ // stopF.println();
+ }
+ // stopF.close();
+ props.save( stopF, "Automatically generated, don't edit" );
+ } catch( IOException ex ) {
+ log( "Can't create stop file: "+sf, ex );
+ }
+ }
+
+ }
+
// -------------------- Handler implementation --------------------
@@ -188,13 +265,36 @@
con.setSocket(socket);
boolean moreRequests = true;
+ boolean authenticated = false;
+ // If we are not configured with a secret, assume
+ // we trust the remote party ( as we did before )
+ if( secret == null )
+ authenticated=true;
+
while(moreRequests) {
int status=req.receiveNextRequest();
+ if( !authenticated ) {
+ // we need to authenticate - the user set a
+ // secret and expects the web server to send it
+ String conSecret=con.getSecret();
+ if( conSecret == null ) {
+ log("Unauthenticated server");
+ break;
+ }
+ if( ! secret.equals( conSecret )) {
+ log("Bad server secret");
+ break;
+ }
+ // allow further requests without checking
+ authenticated=true;
+ }
+
if( status==-2) {
// special case - shutdown
// XXX need better communication, refactor it
- if( !doShutdown(socket.getLocalAddress(),
+ if( !doShutdown(con,
+ socket.getLocalAddress(),
socket.getInetAddress())) {
moreRequests = false;
continue;
@@ -228,14 +328,18 @@
this.cm=(ContextManager)contextM;
}
- protected boolean doShutdown(InetAddress serverAddr,
+ protected boolean doShutdown(Ajp13 con,
+ InetAddress serverAddr,
InetAddress clientAddr)
{
try {
+ // continue with the other checks. XXX We may allow shutdown
+ // with the right secret from a different address.
// close the socket connection before handling any signal
// but get the addresses first so they are not corrupted
if(shutDownEnable && Ajp12.isSameAddress(serverAddr, clientAddr)) {
- cm.stop();
+ cm.shutdown();
+ log( "Exiting" );
// same behavior as in past, because it seems that
// stopping everything doesn't work - need to figure
// out what happens with the threads ( XXX )
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>