You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dw...@apache.org on 2008/08/26 20:19:42 UTC

svn commit: r689161 - in /geronimo/server/trunk/repository/org/apache/activemq: 4.1.2-G647819.README.TXT AMQ1272-stomp-auth-v412.patch

Author: dwoods
Date: Tue Aug 26 11:19:42 2008
New Revision: 689161

URL: http://svn.apache.org/viewvc?rev=689161&view=rev
Log:
GERONIMO-4262 include readme and patch file

Added:
    geronimo/server/trunk/repository/org/apache/activemq/4.1.2-G647819.README.TXT
    geronimo/server/trunk/repository/org/apache/activemq/AMQ1272-stomp-auth-v412.patch

Added: geronimo/server/trunk/repository/org/apache/activemq/4.1.2-G647819.README.TXT
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/repository/org/apache/activemq/4.1.2-G647819.README.TXT?rev=689161&view=auto
==============================================================================
--- geronimo/server/trunk/repository/org/apache/activemq/4.1.2-G647819.README.TXT (added)
+++ geronimo/server/trunk/repository/org/apache/activemq/4.1.2-G647819.README.TXT Tue Aug 26 11:19:42 2008
@@ -0,0 +1,54 @@
+Private Build of ActiveMQ for Geronimo.   
+
+How to build ActiveMQ 4.1.2 with AMQ-1272 security patch:
+---------------------------------------------------------
+Checkout the ActiveMQ 4.1 branch
+  svn co https://svn.apache.org/repos/asf/activemq/tags/activemq-4.1.2 activemq-4.1.2
+  
+svn info for ActiveMQ image:
+Path: .
+URL: https://svn.apache.org/repos/asf/activemq/tags/activemq-4.1.2
+Repository Root: https://svn.apache.org/repos/asf
+Repository UUID: 13f79535-47bb-0310-9956-ffa450edef68
+Revision: 648240
+Node Kind: directory
+Schedule: normal
+Last Changed Author: djencks
+Last Changed Rev: 646984
+Last Changed Date: 2008-04-10 18:03:51 -0400 (Thu, 10 Apr 2008)
+
+
+Apply the security patch
+---------------------------------
+cd activemq-4.1.2
+patch -p0 -u < AMQ1272-stomp-auth-v412.patch
+Answer 'y' to any prompts of "Reversed (or previously applied) patch detected!  Assume -R? [n]"
+
+
+Build ActiveMQ
+--------------
+  cd activemq-4.1.2
+  mvn install
+Notes:
+  - we only need to build the activemq-core directory
+  - I used Sun 1.5.0_13 and Maven 2.0.9 on MacOSX to build the jar
+
+  
+Copy patched activemq-core jar to appropriate filename
+------------------------------------------------------
+  cd activemq-4.1.2
+  cp activemq-core/target/activemq-core-4.1.2.jar <geronimo-root>/repository/org/apache/activemq/activemq-core/4.1.2-G647819/activemq-core-4.1.2-G647819.jar
+
+Optional steps:
+---------------
+  cd <geronimo-root>/repository/org/apache/activemq/activemq-core/4.1.2-G647819
+  md5sum activemq-core-4.1.2-G647819.jar > activemq-core-4.1.2-G647819.jar.md5
+  sha1sum activemq-core-4.1.2-G647819.jar > activemq-core-4.1.2-G647819.jar.sha1
+
+
+How the patch (AMQ1272-stomp-auth-v412.patch) was created:
+----------------------------------------------------------
+The patch was created by back porting the AMQ-1272 patch from Dec. 2007 along withe latest updates of the 3 affected files from the AMQ 5.1.0 release.
+  svn diff > AMQ1272-stomp-auth-v412.patch
+The transport/stomp junit tests were not back ported, due to too many other dependencies in AMQ 5.1.0 that would have been pulled in.
+

Added: geronimo/server/trunk/repository/org/apache/activemq/AMQ1272-stomp-auth-v412.patch
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/repository/org/apache/activemq/AMQ1272-stomp-auth-v412.patch?rev=689161&view=auto
==============================================================================
--- geronimo/server/trunk/repository/org/apache/activemq/AMQ1272-stomp-auth-v412.patch (added)
+++ geronimo/server/trunk/repository/org/apache/activemq/AMQ1272-stomp-auth-v412.patch Tue Aug 26 11:19:42 2008
@@ -0,0 +1,426 @@
+Index: activemq-core/src/main/java/org/apache/activemq/transport/stomp/Stomp.java
+===================================================================
+--- activemq-core/src/main/java/org/apache/activemq/transport/stomp/Stomp.java	(revision 688723)
++++ activemq-core/src/main/java/org/apache/activemq/transport/stomp/Stomp.java	(working copy)
+@@ -49,6 +49,8 @@
+         String RECEIPT_REQUESTED = "receipt";
+         String TRANSACTION = "transaction";
+         String CONTENT_LENGTH = "content-length";
++        String TRANSFORMATION = "transformation";
++        String TRANSFORMATION_ERROR = "transformation-error";
+ 
+         public interface Response {
+             String RECEIPT_ID = "receipt-id";
+@@ -114,4 +116,16 @@
+             String MESSAGE_ID = "message-id";
+         }
+     }
++    
++	public enum Transformations {
++		JMS_BYTE, JMS_OBJECT_XML, JMS_OBJECT_JSON, JMS_MAP_XML, JMS_MAP_JSON;
++		
++		public String toString() {
++			return name().replaceAll("_", "-").toLowerCase();
++		}
++		
++		public static Transformations getValue(String value) {
++			return valueOf(value.replaceAll("-", "_").toUpperCase());
++		}
++	}    
+ }
+Index: activemq-core/src/main/java/org/apache/activemq/transport/stomp/ProtocolConverter.java
+===================================================================
+--- activemq-core/src/main/java/org/apache/activemq/transport/stomp/ProtocolConverter.java	(revision 688723)
++++ activemq-core/src/main/java/org/apache/activemq/transport/stomp/ProtocolConverter.java	(working copy)
+@@ -24,7 +24,6 @@
+ import java.util.Iterator;
+ import java.util.Map;
+ 
+-import javax.jms.Destination;
+ import javax.jms.JMSException;
+ 
+ import org.apache.activemq.command.ActiveMQBytesMessage;
+@@ -32,10 +31,12 @@
+ import org.apache.activemq.command.ActiveMQMessage;
+ import org.apache.activemq.command.ActiveMQTextMessage;
+ import org.apache.activemq.command.Command;
++import org.apache.activemq.command.ConnectionError;
+ import org.apache.activemq.command.ConnectionId;
+ import org.apache.activemq.command.ConnectionInfo;
+ import org.apache.activemq.command.ConsumerId;
+ import org.apache.activemq.command.ConsumerInfo;
++import org.apache.activemq.command.ExceptionResponse;
+ import org.apache.activemq.command.LocalTransactionId;
+ import org.apache.activemq.command.MessageAck;
+ import org.apache.activemq.command.MessageDispatch;
+@@ -49,6 +50,7 @@
+ import org.apache.activemq.command.TransactionId;
+ import org.apache.activemq.command.TransactionInfo;
+ import org.apache.activemq.util.ByteArrayOutputStream;
++import org.apache.activemq.util.IOExceptionSupport;
+ import org.apache.activemq.util.IdGenerator;
+ import org.apache.activemq.util.IntrospectionSupport;
+ import org.apache.activemq.util.LongSequenceGenerator;
+@@ -93,21 +95,27 @@
+     	}
+     }
+ 
+-    protected ResponseHandler createResponseHandler(StompFrame command){
++    protected ResponseHandler createResponseHandler(final StompFrame command) {
+         final String receiptId = (String) command.getHeaders().get(Stomp.Headers.RECEIPT_REQUESTED);
+-        // A response may not be needed.
+-        if( receiptId != null ) {
+-	        return new ResponseHandler() {
+-	    		public void onResponse(ProtocolConverter converter, Response response) throws IOException {
+-	                StompFrame sc = new StompFrame();
+-	                sc.setAction(Stomp.Responses.RECEIPT);
+-	                sc.setHeaders(new HashMap(1));
+-	                sc.getHeaders().put(Stomp.Headers.Response.RECEIPT_ID, receiptId);
+-	        		transportFilter.sendToStomp(sc);
+-	    		}
+-	        };
+-	    }
+-    	return null;
++        if (receiptId != null) {
++            return new ResponseHandler() {
++                public void onResponse(ProtocolConverter converter, Response response) throws IOException {
++                    if (response.isException()) {
++                        // Generally a command can fail.. but that does not invalidate the connection.
++                        // We report back the failure but we don't close the connection.
++                        Throwable exception = ((ExceptionResponse)response).getException();
++                        handleException(exception, command);
++                    } else {
++                        StompFrame sc = new StompFrame();
++                        sc.setAction(Stomp.Responses.RECEIPT);
++                        sc.setHeaders(new HashMap<String, String>(1));
++                        sc.getHeaders().put(Stomp.Headers.Response.RECEIPT_ID, receiptId);
++                        transportFilter.sendToStomp(sc);
++                    }
++                }
++            };
++        }
++        return null;
+     }
+ 
+ 	protected void sendToActiveMQ(Command command, ResponseHandler handler) {
+@@ -123,63 +131,71 @@
+ 		transportFilter.sendToStomp(command);
+ 	}
+ 
+-	/**
+-     * Convert a stomp command
+-     * @param command
+-     */
+-	public void onStompCommad( StompFrame command ) throws IOException, JMSException {
+-		try {
++    /**
++	 * Convert a stomp command
++	 * 
++	 * @param command
++	 */
++    public void onStompCommad(StompFrame command) throws IOException, JMSException {
++        try {
+ 
+-			if( command.getClass() == StompFrameError.class ) {
+-				throw ((StompFrameError)command).getException();
+-			}
++            if (command.getClass() == StompFrameError.class) {
++                throw ((StompFrameError)command).getException();
++            }
+ 
+-			String action = command.getAction();
+-	        if (action.startsWith(Stomp.Commands.SEND))
+-	            onStompSend(command);
+-	        else if (action.startsWith(Stomp.Commands.ACK))
+-	            onStompAck(command);
+-	        else if (action.startsWith(Stomp.Commands.BEGIN))
+-	            onStompBegin(command);
+-	        else if (action.startsWith(Stomp.Commands.COMMIT))
+-	            onStompCommit(command);
+-	        else if (action.startsWith(Stomp.Commands.ABORT))
+-	            onStompAbort(command);
+-	        else if (action.startsWith(Stomp.Commands.SUBSCRIBE))
+-	            onStompSubscribe(command);
+-	        else if (action.startsWith(Stomp.Commands.UNSUBSCRIBE))
+-	            onStompUnsubscribe(command);
+-			else if (action.startsWith(Stomp.Commands.CONNECT))
+-	            onStompConnect(command);
+-	        else if (action.startsWith(Stomp.Commands.DISCONNECT))
+-	            onStompDisconnect(command);
+-	        else
+-	        	throw new ProtocolException("Unknown STOMP action: "+action);
++            String action = command.getAction();
++            if (action.startsWith(Stomp.Commands.SEND)) {
++                onStompSend(command);
++            } else if (action.startsWith(Stomp.Commands.ACK)) {
++                onStompAck(command);
++            } else if (action.startsWith(Stomp.Commands.BEGIN)) {
++                onStompBegin(command);
++            } else if (action.startsWith(Stomp.Commands.COMMIT)) {
++                onStompCommit(command);
++            } else if (action.startsWith(Stomp.Commands.ABORT)) {
++                onStompAbort(command);
++            } else if (action.startsWith(Stomp.Commands.SUBSCRIBE)) {
++                onStompSubscribe(command);
++            } else if (action.startsWith(Stomp.Commands.UNSUBSCRIBE)) {
++                onStompUnsubscribe(command);
++            } else if (action.startsWith(Stomp.Commands.CONNECT)) {
++                onStompConnect(command);
++            } else if (action.startsWith(Stomp.Commands.DISCONNECT)) {
++                onStompDisconnect(command);
++            } else {
++                throw new ProtocolException("Unknown STOMP action: " + action);
++            }
+ 
+         } catch (ProtocolException e) {
+-
+-        	// Let the stomp client know about any protocol errors.
+-        	ByteArrayOutputStream baos = new ByteArrayOutputStream();
+-        	PrintWriter stream = new PrintWriter(new OutputStreamWriter(baos,"UTF-8"));
+-        	e.printStackTrace(stream);
+-        	stream.close();
+-
+-        	HashMap headers = new HashMap();
+-        	headers.put(Stomp.Headers.Error.MESSAGE, e.getMessage());
+-
+-            final String receiptId = (String) command.getHeaders().get(Stomp.Headers.RECEIPT_REQUESTED);
+-            if( receiptId != null ) {
+-            	headers.put(Stomp.Headers.Response.RECEIPT_ID, receiptId);
++            handleException(e, command);
++            // Some protocol errors can cause the connection to get closed.
++            if( e.isFatal() ) {
++               getTransportFilter().onException(e);
+             }
++        }
++    }
++    
++    protected void handleException(Throwable exception, StompFrame command) throws IOException {
++        // Let the stomp client know about any protocol errors.
++        ByteArrayOutputStream baos = new ByteArrayOutputStream();
++        PrintWriter stream = new PrintWriter(new OutputStreamWriter(baos, "UTF-8"));
++        exception.printStackTrace(stream);
++        stream.close();
+ 
+-        	StompFrame errorMessage = new StompFrame(Stomp.Responses.ERROR,headers,baos.toByteArray());
+-			sendToStomp(errorMessage);
++        HashMap<String, String> headers = new HashMap<String, String>();
++        headers.put(Stomp.Headers.Error.MESSAGE, exception.getMessage());
+ 
+-			if( e.isFatal() )
+-				getTransportFilter().onException(e);
++        if (command != null) {
++        	final String receiptId = (String) command.getHeaders().get(Stomp.Headers.RECEIPT_REQUESTED);
++        	if (receiptId != null) {
++        		headers.put(Stomp.Headers.Response.RECEIPT_ID, receiptId);
++        	}
+         }
+-	}
+ 
++        StompFrame errorMessage = new StompFrame(Stomp.Responses.ERROR, headers, baos.toByteArray());
++        sendToStomp(errorMessage);
++    }
++
+ 	protected void onStompSend(StompFrame command) throws IOException, JMSException {
+ 		checkConnected();
+ 
+@@ -352,9 +368,9 @@
+ 
+ 	}
+ 
+-	protected void onStompUnsubscribe(StompFrame command) throws ProtocolException {
+-		checkConnected();
+-    	Map headers = command.getHeaders();
++    protected void onStompUnsubscribe(StompFrame command) throws ProtocolException {
++        checkConnected();
++        Map<String, String> headers = command.getHeaders();
+ 
+         ActiveMQDestination destination=null;
+         Object o = headers.get(Stomp.Headers.Unsubscribe.DESTINATION);
+@@ -385,65 +401,85 @@
+         throw new ProtocolException("No subscription matched.");
+ 	}
+ 
+-	protected void onStompConnect(StompFrame command) throws ProtocolException {
++    protected void onStompConnect(final StompFrame command) throws ProtocolException {
+ 
+-		if(connected.get()) {
+-			throw new ProtocolException("Allready connected.");
+-		}
++        if (connected.get()) {
++            throw new ProtocolException("Allready connected.");
++        }
+ 
+-    	final Map headers = command.getHeaders();
++        final Map<String, String> headers = command.getHeaders();
+ 
+         // allow anyone to login for now
+-        String login = (String)headers.get(Stomp.Headers.Connect.LOGIN);
+-        String passcode = (String)headers.get(Stomp.Headers.Connect.PASSCODE);
+-        String clientId = (String)headers.get(Stomp.Headers.Connect.CLIENT_ID);
++        String login = headers.get(Stomp.Headers.Connect.LOGIN);
++        String passcode = headers.get(Stomp.Headers.Connect.PASSCODE);
++        String clientId = headers.get(Stomp.Headers.Connect.CLIENT_ID);
+ 
+         final ConnectionInfo connectionInfo = new ConnectionInfo();
+ 
+         IntrospectionSupport.setProperties(connectionInfo, headers, "activemq.");
+ 
+         connectionInfo.setConnectionId(connectionId);
+-        if( clientId!=null )
++        if (clientId != null) {
+             connectionInfo.setClientId(clientId);
+-        else
+-            connectionInfo.setClientId(""+connectionInfo.getConnectionId().toString());
++        } else {
++            connectionInfo.setClientId("" + connectionInfo.getConnectionId().toString());
++        }
+ 
+         connectionInfo.setResponseRequired(true);
+         connectionInfo.setUserName(login);
+         connectionInfo.setPassword(passcode);
+ 
+-		sendToActiveMQ(connectionInfo, new ResponseHandler(){
+-			public void onResponse(ProtocolConverter converter, Response response) throws IOException {
++        sendToActiveMQ(connectionInfo, new ResponseHandler() {
++            public void onResponse(ProtocolConverter converter, Response response) throws IOException {
+ 
+-	            final SessionInfo sessionInfo = new SessionInfo(sessionId);
+-	            sendToActiveMQ(sessionInfo,null);
++                if (response.isException()) {
++                    // If the connection attempt fails we close the socket.
++                    Throwable exception = ((ExceptionResponse)response).getException();
++                    handleException(exception, command);
++                    getTransportFilter().onException(IOExceptionSupport.create(exception));
++                    return;
++                }
+ 
++                final SessionInfo sessionInfo = new SessionInfo(sessionId);
++                sendToActiveMQ(sessionInfo, null);
+ 
+-	            final ProducerInfo producerInfo = new ProducerInfo(producerId);
+-	            sendToActiveMQ(producerInfo,new ResponseHandler(){
+-					public void onResponse(ProtocolConverter converter, Response response) throws IOException {
++                final ProducerInfo producerInfo = new ProducerInfo(producerId);
++                sendToActiveMQ(producerInfo, new ResponseHandler() {
++                    public void onResponse(ProtocolConverter converter, Response response) throws IOException {
++                        
++                        if (response.isException()) {
++                            // If the connection attempt fails we close the socket.
++                            Throwable exception = ((ExceptionResponse)response).getException();
++                            handleException(exception, command);
++                            getTransportFilter().onException(IOExceptionSupport.create(exception));
++                        }
++                        
++                        connected.set(true);
++                        HashMap<String, String> responseHeaders = new HashMap<String, String>();
+ 
+-						connected.set(true);
+-	                    HashMap responseHeaders = new HashMap();
++                        responseHeaders.put(Stomp.Headers.Connected.SESSION, connectionInfo.getClientId());
++                        String requestId = headers.get(Stomp.Headers.Connect.REQUEST_ID);
++                        if (requestId == null) {
++                            // TODO legacy
++                            requestId = headers.get(Stomp.Headers.RECEIPT_REQUESTED);
++                        }
++                        if (requestId != null) {
++                            // TODO legacy
++                            responseHeaders.put(Stomp.Headers.Connected.RESPONSE_ID, requestId);
++                            responseHeaders.put(Stomp.Headers.Response.RECEIPT_ID, requestId);
++                        }
+ 
+-	                    responseHeaders.put(Stomp.Headers.Connected.SESSION, connectionInfo.getClientId());
+-	                    String requestId = (String) headers.get(Stomp.Headers.Connect.REQUEST_ID);
+-	                    if( requestId !=null ){
+-		                    responseHeaders.put(Stomp.Headers.Connected.RESPONSE_ID, requestId);
+-	            		}
++                        StompFrame sc = new StompFrame();
++                        sc.setAction(Stomp.Responses.CONNECTED);
++                        sc.setHeaders(responseHeaders);
++                        sendToStomp(sc);
++                    }
++                });
+ 
+-	                    StompFrame sc = new StompFrame();
+-	                    sc.setAction(Stomp.Responses.CONNECTED);
+-	                    sc.setHeaders(responseHeaders);
+-	                    sendToStomp(sc);
+-					}
+-				});
++            }
++        });
++    }
+ 
+-			}
+-		});
+-
+-	}
+-
+ 	protected void onStompDisconnect(StompFrame command) throws ProtocolException {
+ 		checkConnected();
+ 		sendToActiveMQ(new ShutdownInfo(), createResponseHandler(command));
+@@ -466,26 +502,33 @@
+ 
+     	if ( command.isResponse() ) {
+ 
+-			Response response = (Response) command;
+-		    ResponseHandler rh = (ResponseHandler) resposeHandlers.remove(new Integer(response.getCorrelationId()));
+-		    if( rh !=null ) {
+-		    	rh.onResponse(this, response);
+-		    }
++            Response response = (Response)command;
++            ResponseHandler rh = (ResponseHandler) resposeHandlers.remove(Integer.valueOf(response.getCorrelationId()));
++            if (rh != null) {
++                rh.onResponse(this, response);
++            } else {
++                // Pass down any unexpected errors. Should this close the connection?
++                if (response.isException()) {
++                    Throwable exception = ((ExceptionResponse)response).getException();
++                    handleException(exception, null);
++                }
++            }
++        } else if (command.isMessageDispatch()) {
+ 
+-		} else if( command.isMessageDispatch() ) {
+-
+-		    MessageDispatch md = (MessageDispatch)command;
+-		    StompSubscription sub = (StompSubscription) subscriptionsByConsumerId.get(md.getConsumerId());
+-		    if (sub != null) {
+-		        sub.onMessageDispatch(md);
++            MessageDispatch md = (MessageDispatch)command;
++            StompSubscription sub = (StompSubscription) subscriptionsByConsumerId.get(md.getConsumerId());
++            if (sub != null) {
++                sub.onMessageDispatch(md);
+             }
++        } else if (command.getDataStructureType() == ConnectionError.DATA_STRUCTURE_TYPE) {
++            // Pass down any unexpected async errors. Should this close the connection?
++            Throwable exception = ((ConnectionError)command).getException();
++            handleException(exception, null);
+         }
+-	}
++    }
+ 
+-    public  ActiveMQMessage convertMessage(StompFrame command) throws IOException, JMSException {
+-
++    public ActiveMQMessage convertMessage(StompFrame command) throws IOException, JMSException {
+         ActiveMQMessage msg = frameTranslator.convertFrame(command);
+-
+         return msg;
+     }
+ 
+Index: activemq-core/src/main/java/org/apache/activemq/util/IOExceptionSupport.java
+===================================================================
+--- activemq-core/src/main/java/org/apache/activemq/util/IOExceptionSupport.java	(revision 688723)
++++ activemq-core/src/main/java/org/apache/activemq/util/IOExceptionSupport.java	(working copy)
+@@ -19,8 +19,11 @@
+ 
+ import java.io.IOException;
+ 
+-final public class IOExceptionSupport {
++public final class IOExceptionSupport {
+ 
++    private IOExceptionSupport() {
++    }
++
+     public static IOException create(String msg, Throwable cause) {
+         IOException exception = new IOException(msg);
+         exception.initCause(cause);