[jboss-remoting-commits] JBoss Remoting SVN: r5771 - in remoting3/trunk/jboss-remoting/src: main/java/org/jboss/remoting3/remote and 3 other directories.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Sun Feb 28 10:51:39 EST 2010


Author: david.lloyd at jboss.com
Date: 2010-02-28 10:51:38 -0500 (Sun, 28 Feb 2010)
New Revision: 5771

Added:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/GreetingUtils.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslClientContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslServerContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUnwrappingMessageHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/ServerAuthenticationProvider.java
Removed:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteOpenListener.java
Modified:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/CloseHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundReplyInputHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyBufferWriter.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestBufferWriter.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionProvider.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ProtocolServiceType.java
   remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/InvocationTestBase.java
   remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/LocalTestCase.java
   remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java
Log:
Add authentication layer

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/CloseHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/CloseHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/CloseHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -22,6 +22,8 @@
 
 package org.jboss.remoting3;
 
+import java.util.EventListener;
+
 /**
  * A handler which is notified of a resource close.
  *
@@ -30,7 +32,7 @@
  * @apiviz.exclude
  * @remoting.implement
  */
-public interface CloseHandler<T> {
+public interface CloseHandler<T> extends EventListener {
 
     /**
      * Receive a notification that the resource was closed.

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -591,7 +591,8 @@
         return expectedType.cast(provider.getProviderInterface());
     }
 
-    private <T> Registration addMarshallingRegistration(final String name, final T target, final ConcurrentMap<String, T> map, final String descr) throws DuplicateRegistrationException {
+    public <T> Registration addProtocolService(final ProtocolServiceType<T> type, final String name, final T provider) throws DuplicateRegistrationException {
+        final ConcurrentMap<String, T> map = getMapFor(type);
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(ADD_MARSHALLING_PROTOCOL_PERM);
@@ -599,16 +600,12 @@
         if ("default".equals(name)) {
             throw new IllegalArgumentException("'default' is not an allowed name");
         }
-        if (map.putIfAbsent(name, target) != null) {
-            throw new DuplicateRegistrationException(descr + " '" + name + "' is already registered");
+        if (map.putIfAbsent(name, provider) != null) {
+            throw new DuplicateRegistrationException(type.getDescription() + " '" + name + "' is already registered");
         }
-        return new MapRegistration<T>(map, name, target);
+        return new MapRegistration<T>(map, name, provider);
     }
 
-    public <T> Registration addProtocolService(final ProtocolServiceType<T> type, final String name, final T provider) throws DuplicateRegistrationException {
-        return addMarshallingRegistration(name, provider, getMapFor(type), type.getDescription());
-    }
-
     public String toString() {
         return "endpoint \"" + name + "\" <" + Integer.toHexString(hashCode()) + ">";
     }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -138,4 +138,14 @@
      * Specify whether a local connection or client should call by reference (the usual default) or value.
      */
     public static final Option<Boolean> CALL_BY_VALUE = Option.simple(RemotingOptions.class, "CALL_BY_VALUE", Boolean.class);
+
+    /**
+     * Specify the name of a preregistered server authentication provider to use.
+     */
+    public static final Option<String> AUTHENTICATION_PROVIDER = Option.simple(RemotingOptions.class, "AUTHENTICATION_PROVIDER", String.class);
+
+    /**
+     * Specify a set of SASL server mechanisms to allow.  If not specified, no mechanisms will be excluded.
+     */
+    public static final Option<Sequence<String>> SASL_SERVER_MECHANISMS = Option.sequence(RemotingOptions.class, "SASL_SERVER_MECHANISMS", String.class);
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import org.jboss.marshalling.MarshallerFactory;
+import org.jboss.marshalling.Marshalling;
+import org.jboss.marshalling.MarshallingConfiguration;
+import org.jboss.remoting3.CloseHandler;
+import org.jboss.remoting3.spi.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerContext;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.Result;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+final class ClientAuthenticationHandler implements MessageHandler {
+
+    private final RemoteConnection remoteConnection;
+    private final SaslClient saslClient;
+    private final Result<ConnectionHandlerFactory> factoryResult;
+
+    public ClientAuthenticationHandler(final RemoteConnection remoteConnection, final SaslClient saslClient, final Result<ConnectionHandlerFactory> factoryResult) {
+        this.remoteConnection = remoteConnection;
+        this.saslClient = saslClient;
+        this.factoryResult = factoryResult;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        final byte msgType = buffer.get();
+        switch (msgType) {
+            case RemoteProtocol.AUTH_CHALLENGE:
+            case RemoteProtocol.AUTH_COMPLETE: {
+                final byte[] response;
+                try {
+                    response = saslClient.evaluateChallenge(Buffers.take(buffer, buffer.remaining()));
+                } catch (SaslException e) {
+                    // todo log it
+                    factoryResult.setException(e);
+                    IoUtils.safeClose(remoteConnection);
+                    return;
+                }
+                if (msgType == RemoteProtocol.AUTH_COMPLETE) {
+                    if ((response != null || response.length > 0)) {
+                        // todo log extraneous message
+                        IoUtils.safeClose(remoteConnection);
+                        return;
+                    }
+                    // auth complete.
+                    factoryResult.setResult(new ConnectionHandlerFactory() {
+                        public ConnectionHandler createInstance(final ConnectionHandlerContext connectionContext) {
+                            // this happens immediately.
+                            final MarshallerFactory marshallerFactory = Marshalling.getMarshallerFactory("river");
+                            final MarshallingConfiguration marshallingConfiguration = new MarshallingConfiguration();
+                            final RemoteConnectionHandler connectionHandler = new RemoteConnectionHandler(connectionContext, remoteConnection, marshallerFactory, marshallingConfiguration);
+                            remoteConnection.addCloseHandler(new CloseHandler<Object>() {
+                                public void handleClose(final Object closed) {
+                                    IoUtils.safeClose(connectionHandler);
+                                }
+                            });
+                            remoteConnection.setMessageHandler(new RemoteMessageHandler(connectionHandler, remoteConnection));
+                            return connectionHandler;
+                        }
+                    });
+                    return;
+                }
+                break;
+            }
+        }
+    }
+
+    public void handleEof() {
+        factoryResult.setException(new EOFException("End of file on input"));
+        IoUtils.safeClose(remoteConnection);
+    }
+
+    public void handleException(final IOException e) {
+        // todo log it
+        factoryResult.setException(e);
+        IoUtils.safeClose(remoteConnection);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,117 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.remoting3.RemotingOptions;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.Option;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Result;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+final class ClientGreetingHandler implements MessageHandler {
+    private final RemoteConnection connection;
+    private final Result<ConnectionHandlerFactory> factoryResult;
+    private final CallbackHandler callbackHandler;
+
+    public ClientGreetingHandler(final RemoteConnection connection, final Result<ConnectionHandlerFactory> factoryResult, final CallbackHandler callbackHandler) {
+        this.connection = connection;
+        this.factoryResult = factoryResult;
+        this.callbackHandler = callbackHandler;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        List<String> saslMechs = new ArrayList<String>();
+        switch (buffer.get()) {
+            case RemoteProtocol.GREETING: {
+                while (buffer.hasRemaining()) {
+                    final byte type = buffer.get();
+                    final int len = buffer.get() & 0xff;
+                    switch (type) {
+                        case RemoteProtocol.GREETING_VERSION: {
+                            // We only support version zero, so knowing the other side's version is not useful presently
+                            buffer.get();
+                            if (len > 1) Buffers.skip(buffer, len - 1);
+                            break;
+                        }
+                        case RemoteProtocol.GREETING_SASL_MECH: {
+                            saslMechs.add(Buffers.getModifiedUtf8(Buffers.slice(buffer, len)));
+                            break;
+                        }
+                        default: {
+                            // unknown, skip it for forward compatibility.
+                            Buffers.skip(buffer, len);
+                            break;
+                        }
+                    }
+                }
+                // OK now send our authentication request
+                final OptionMap optionMap = connection.getOptionMap();
+                final String userName = optionMap.get(RemotingOptions.AUTH_USER_NAME);
+                final String hostName = connection.getChannel().getPeerAddress().getHostName();
+                final Map<String, ?> propertyMap = SaslUtils.createPropertyMap(optionMap);
+                final SaslClient saslClient;
+                try {
+                    saslClient = Sasl.createSaslClient(saslMechs.toArray(new String[saslMechs.size()]), userName == null ? "anonymous" : userName, "remote", hostName, propertyMap, callbackHandler);
+                } catch (SaslException e) {
+                    factoryResult.setException(e);
+                    // todo log exception @ error
+                    // todo send "goodbye" & close
+                    IoUtils.safeClose(connection);
+                    return;
+                }
+                connection.setMessageHandler(new ClientAuthenticationHandler(connection, saslClient, factoryResult));
+                return;
+            }
+            default: {
+                // todo log invalid greeting
+                IoUtils.safeClose(connection);
+                return;
+            }
+        }
+    }
+
+    public void handleEof() {
+        factoryResult.setException(new EOFException("End of file on input"));
+        IoUtils.safeClose(connection);
+    }
+
+    public void handleException(final IOException e) {
+        // todo log it
+        factoryResult.setException(e);
+        IoUtils.safeClose(connection);
+    }
+}
\ No newline at end of file

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,83 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.xnio.ChannelListener;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Options;
+import org.jboss.xnio.Result;
+import org.jboss.xnio.channels.ConnectedStreamChannel;
+
+import javax.security.auth.callback.CallbackHandler;
+
+final class ClientOpenListener implements ChannelListener<ConnectedStreamChannel<InetSocketAddress>> {
+
+    private final OptionMap optionMap;
+    private final ConnectionProviderContext connectionProviderContext;
+    private final Result<ConnectionHandlerFactory> factoryResult;
+    private final CallbackHandler callbackHandler;
+
+    public ClientOpenListener(final OptionMap optionMap, final ConnectionProviderContext connectionProviderContext, final Result<ConnectionHandlerFactory> factoryResult, final CallbackHandler callbackHandler) {
+        this.optionMap = optionMap;
+        this.connectionProviderContext = connectionProviderContext;
+        this.factoryResult = factoryResult;
+        this.callbackHandler = callbackHandler;
+    }
+
+    public void handleEvent(final ConnectedStreamChannel<InetSocketAddress> channel) {
+        try {
+            channel.setOption(Options.TCP_NODELAY, Boolean.TRUE);
+        } catch (IOException e) {
+            // ignore
+        }
+        final RemoteConnection connection = new RemoteConnection(connectionProviderContext.getExecutor(), channel, optionMap);
+
+        // Send client greeting packet...
+        final ByteBuffer buffer = connection.allocate();
+        try {
+            // length placeholder
+            buffer.putInt(0);
+            // version ID
+            GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION, RemoteProtocol.VERSION);
+            // that's it!
+            buffer.flip();
+            connection.sendBlocking(buffer);
+        } catch (IOException e1) {
+            // todo log it
+            factoryResult.setException(e1);
+            IoUtils.safeClose(connection);
+        } finally {
+            connection.free(buffer);
+        }
+
+        connection.setMessageHandler(new ClientGreetingHandler(connection, factoryResult, callbackHandler));
+        // start up the read cycle
+        channel.resumeReads();
+    }
+}
\ No newline at end of file

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/GreetingUtils.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/GreetingUtils.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/GreetingUtils.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.nio.ByteBuffer;
+import org.jboss.xnio.Buffers;
+
+final class GreetingUtils {
+
+    private GreetingUtils() {
+    }
+
+    static void writeString(ByteBuffer buffer, byte type, String data) {
+        buffer.put(type);
+        buffer.put((byte) 0); // length placeholder
+        int s = buffer.position();
+        Buffers.putModifiedUtf8(buffer, data);
+        final int len = buffer.position() - s;
+        if (len > 255) {
+            // truncate long name
+            buffer.position(s + 255);
+            buffer.put(s-1, (byte) 255);
+        } else {
+            buffer.put(s-1, (byte) len);
+        }
+    }
+
+    static void writeByte(ByteBuffer buffer, byte type, byte value) {
+        buffer.put(type);
+        buffer.put((byte) 1);
+        buffer.put(value);
+    }
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundReplyInputHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundReplyInputHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundReplyInputHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -43,8 +43,9 @@
             buffer.put(RemoteProtocol.REQUEST_ACK_CHUNK);
             buffer.putInt(rid);
             buffer.flip();
-            connectionHandler.sendBlocking(buffer);
-            connectionHandler.flushBlocking();
+            final RemoteConnection connection = connectionHandler.getRemoteConnection();
+            connection.sendBlocking(buffer);
+            connection.flushBlocking();
         } finally {
             connectionHandler.getBufferPool().free(buffer);
         }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -45,8 +45,9 @@
             buffer.put(RemoteProtocol.REQUEST_ACK_CHUNK);
             buffer.putInt(rid);
             buffer.flip();
-            connectionHandler.sendBlocking(buffer);
-            connectionHandler.flushBlocking();
+            final RemoteConnection connection = connectionHandler.getRemoteConnection();
+            connection.sendBlocking(buffer);
+            connection.flushBlocking();
         } catch (IOException e) {
             RemoteConnectionHandler.log.trace(e, "Failed to acknowledge chunk for %s", this);
         } finally {

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyBufferWriter.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyBufferWriter.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyBufferWriter.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -73,14 +73,14 @@
                 buffer.put(7, (byte) (buffer.get(3) | RemoteProtocol.MSG_FLAG_LAST));
             }
             RemoteConnectionHandler.log.trace("Sending buffer %s for %s", buffer, this);
-            connectionHandler.sendBlocking(buffer);
+            connectionHandler.getRemoteConnection().sendBlocking(buffer);
         } finally {
             connectionHandler.getBufferPool().free(buffer);
         }
     }
 
     public void flush() throws IOException {
-        inboundRequest.getRemoteConnectionHandler().flushBlocking();
+        inboundRequest.getRemoteConnectionHandler().getRemoteConnection().flushBlocking();
     }
 
     public String toString() {

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundReplyHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -71,7 +71,7 @@
                         buffer.put(RemoteProtocol.REPLY_EXCEPTION_ABORT);
                         buffer.putInt(rid);
                         buffer.flip();
-                        connectionHandler.sendBlocking(buffer);
+                        connectionHandler.getRemoteConnection().sendBlocking(buffer);
                     } finally {
                         bufferPool.free(buffer);
                     }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestBufferWriter.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestBufferWriter.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestBufferWriter.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -73,13 +73,13 @@
                 }
             }
             RemoteConnectionHandler.log.trace("Sending buffer %s for %s", buffer, this);
-            remoteConnectionHandler.sendBlocking(buffer);
+            remoteConnectionHandler.getRemoteConnection().sendBlocking(buffer);
         } finally {
             remoteConnectionHandler.getBufferPool().free(buffer);
         }
     }
 
     public void flush() throws IOException {
-        outboundRequest.getRemoteConnectionHandler().flushBlocking();
+        outboundRequest.getRemoteConnectionHandler().getRemoteConnection().flushBlocking();
     }
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -79,7 +79,7 @@
             buf.putInt(rid);
             buf.flip();
             try {
-                connectionHandler.sendBlocking(buf);
+                connectionHandler.getRemoteConnection().sendBlocking(buf);
             } catch (IOException e1) {
                 // todo log it
             }
@@ -100,7 +100,7 @@
             buf.put(RemoteProtocol.CLIENT_CLOSED);
             buf.putInt(outboundClient.getId());
             buf.flip();
-            connectionHandler.sendBlocking(buf);
+            connectionHandler.getRemoteConnection().sendBlocking(buf);
         } finally {
             bufferPool.free(buf);
         }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,178 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Executor;
+import org.jboss.remoting3.spi.AbstractHandleableCloseable;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Pool;
+import org.jboss.xnio.channels.Channels;
+import org.jboss.xnio.channels.ConnectedChannel;
+import org.jboss.xnio.channels.ConnectedStreamChannel;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.auth.callback.CallbackHandler;
+
+final class RemoteConnection extends AbstractHandleableCloseable<RemoteConnection> implements Closeable {
+    private final ConnectedStreamChannel<InetSocketAddress> channel;
+    private final Pool<ByteBuffer> bufferPool = Buffers.createHeapByteBufferAllocator(4096);
+    private final MessageHandler.Setter messageHandlerSetter;
+    private final OptionMap optionMap;
+
+    RemoteConnection(final Executor executor, final ConnectedStreamChannel<InetSocketAddress> channel, final OptionMap optionMap) {
+        super(executor);
+        this.channel = channel;
+        messageHandlerSetter = Channels.createMessageReader(channel, optionMap);
+        this.optionMap = optionMap;
+    }
+
+    public void close() throws IOException {
+        channel.close();
+    }
+
+    OptionMap getOptionMap() {
+        return optionMap;
+    }
+
+    ConnectedChannel<InetSocketAddress> getChannel() {
+        return channel;
+    }
+
+    ByteBuffer allocate() {
+        return bufferPool.allocate();
+    }
+
+    void free(ByteBuffer buffer) {
+        bufferPool.free(buffer);
+    }
+
+    void setMessageHandler(MessageHandler handler) {
+        messageHandlerSetter.set(handler);
+    }
+
+    void sendBlocking(final ByteBuffer buffer) throws IOException {
+        try {
+            sendBlockingNoClose(buffer);
+        } catch (IOException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (RuntimeException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (Error e) {
+            IoUtils.safeClose(this);
+            throw e;
+        }
+    }
+
+    void sendBlockingNoClose(final ByteBuffer buffer) throws IOException {
+        buffer.putInt(0, buffer.remaining() - 4);
+        boolean intr = false;
+        try {
+            while (buffer.hasRemaining()) {
+                if (channel.write(buffer) == 0) {
+                    try {
+                        channel.awaitWritable();
+                    } catch (InterruptedIOException e) {
+                        intr = Thread.interrupted();
+                    }
+                }
+            }
+        } finally {
+            if (intr) Thread.currentThread().interrupt();
+        }
+    }
+
+    void flushBlocking() throws IOException {
+        try {
+            while (! channel.flush()) {
+                channel.awaitWritable();
+            }
+        } catch (IOException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (RuntimeException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (Error e) {
+            IoUtils.safeClose(this);
+            throw e;
+        }
+    }
+
+    void shutdownWritesBlocking() throws IOException {
+        try {
+            while (! channel.shutdownWrites()) {
+                channel.awaitWritable();
+            }
+        } catch (IOException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (RuntimeException e) {
+            IoUtils.safeClose(this);
+            throw e;
+        } catch (Error e) {
+            IoUtils.safeClose(this);
+            throw e;
+        }
+    }
+
+    void sendAuthReject(final String msg) throws IOException {
+        final ByteBuffer buf = allocate();
+        try {
+            buf.putInt(0);
+            buf.put(RemoteProtocol.AUTH_REJECTED);
+            Buffers.putModifiedUtf8(buf, msg);
+            buf.flip();
+            sendBlocking(buf);
+            flushBlocking();
+        } finally {
+            free(buf);
+        }
+    }
+
+    void sendAuthMessage(final byte msgType, final byte[] message) throws IOException {
+        final ByteBuffer buf = allocate();
+        try {
+            buf.putInt(0);
+            buf.put(msgType);
+            if (message != null) buf.put(message);
+            buf.flip();
+            sendBlocking(buf);
+            flushBlocking();
+        } finally {
+            free(buf);
+        }
+    }
+
+    void shutdownReads() throws IOException {
+        channel.shutdownReads();
+    }
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -23,7 +23,6 @@
 package org.jboss.remoting3.remote;
 
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.nio.ByteBuffer;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -42,7 +41,7 @@
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.Pool;
 import org.jboss.xnio.Result;
-import org.jboss.xnio.channels.StreamChannel;
+import org.jboss.xnio.channels.Channels;
 import org.jboss.xnio.log.Logger;
 
 final class RemoteConnectionHandler implements ConnectionHandler {
@@ -56,7 +55,7 @@
     private final MarshallingConfiguration marshallingConfiguration;
 
     private final ConnectionHandlerContext connectionContext;
-    private final StreamChannel channel;
+    private final RemoteConnection remoteConnection;
     private final Random random = new Random();
 
     private final IntKeyMap<OutboundClient> outboundClients = new IntKeyMap<OutboundClient>();
@@ -67,63 +66,13 @@
 
     private final AtomicBoolean closed = new AtomicBoolean();
 
-    public RemoteConnectionHandler(final ConnectionHandlerContext connectionContext, final StreamChannel channel, final MarshallerFactory marshallerFactory, final MarshallingConfiguration marshallingConfiguration) {
+    public RemoteConnectionHandler(final ConnectionHandlerContext connectionContext, final RemoteConnection remoteConnection, final MarshallerFactory marshallerFactory, final MarshallingConfiguration marshallingConfiguration) {
         this.connectionContext = connectionContext;
-        this.channel = channel;
+        this.remoteConnection = remoteConnection;
         this.marshallerFactory = marshallerFactory;
         this.marshallingConfiguration = marshallingConfiguration;
     }
 
-    void sendBlocking(final ByteBuffer buffer) throws IOException {
-        try {
-            sendBlockingNoClose(buffer);
-        } catch (IOException e) {
-            IoUtils.safeClose(this);
-            throw e;
-        } catch (RuntimeException e) {
-            IoUtils.safeClose(this);
-            throw e;
-        } catch (Error e) {
-            IoUtils.safeClose(this);
-            throw e;
-        }
-    }
-
-    void sendBlockingNoClose(final ByteBuffer buffer) throws IOException {
-        buffer.putInt(0, buffer.remaining() - 4);
-        boolean intr = false;
-        try {
-            while (buffer.hasRemaining()) {
-                if (channel.write(buffer) == 0) {
-                    try {
-                        channel.awaitWritable();
-                    } catch (InterruptedIOException e) {
-                        intr = Thread.interrupted();
-                    }
-                }
-            }
-        } finally {
-            if (intr) Thread.currentThread().interrupt();
-        }
-    }
-
-    void flushBlocking() throws IOException {
-        try {
-            while (! channel.flush()) {
-                channel.awaitWritable();
-            }
-        } catch (IOException e) {
-            IoUtils.safeClose(this);
-            throw e;
-        } catch (RuntimeException e) {
-            IoUtils.safeClose(this);
-            throw e;
-        } catch (Error e) {
-            IoUtils.safeClose(this);
-            throw e;
-        }
-    }
-
     public Cancellable open(final String serviceType, final String groupName, final Result<RequestHandler> result) {
         final OutboundClient outboundClient;
         int id;
@@ -143,7 +92,7 @@
             Buffers.putModifiedUtf8(buffer, groupName);
             buffer.put((byte) 0);
             buffer.flip();
-            sendBlocking(buffer);
+            remoteConnection.sendBlocking(buffer);
         } catch (IOException e) {
             result.setException(e);
         } catch (Throwable e) {
@@ -161,7 +110,7 @@
     public void close() throws IOException {
         if (! closed.getAndSet(true)) {
             try {
-                channel.close();
+                remoteConnection.close();
             } finally {
                 // other actions here
                 for (IntKeyMap.Entry<OutboundClient> entry : outboundClients) {
@@ -208,10 +157,6 @@
         return connectionContext;
     }
 
-    StreamChannel getChannel() {
-        return channel;
-    }
-
     Random getRandom() {
         return random;
     }
@@ -235,4 +180,8 @@
     AtomicBoolean getClosed() {
         return closed;
     }
+
+    RemoteConnection getRemoteConnection() {
+        return remoteConnection;
+    }
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionProvider.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionProvider.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionProvider.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -22,15 +22,17 @@
 
 package org.jboss.remoting3.remote;
 
-import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.UnknownHostException;
+import org.jboss.remoting3.RemotingOptions;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
 import org.jboss.remoting3.spi.ConnectionHandlerFactory;
 import org.jboss.remoting3.spi.ConnectionProvider;
 import org.jboss.remoting3.spi.ConnectionProviderContext;
 import org.jboss.remoting3.spi.NetworkServerProvider;
+import org.jboss.remoting3.spi.ProtocolServiceType;
 import org.jboss.xnio.Cancellable;
 import org.jboss.xnio.ChannelListener;
 import org.jboss.xnio.Connector;
@@ -68,7 +70,7 @@
         // Open a client channel
         final IoFuture<? extends ConnectedStreamChannel<InetSocketAddress>> futureChannel;
         try {
-            futureChannel = connector.connectTo(new InetSocketAddress(InetAddress.getByName(host), port), new RemoteOpenListener(false, connectOptions, connectionProviderContext, result), null);
+            futureChannel = connector.connectTo(new InetSocketAddress(InetAddress.getByName(host), port), new ClientOpenListener(connectOptions, connectionProviderContext, result, callbackHandler), null);
         } catch (UnknownHostException e) {
             result.setException(e);
             return IoUtils.nullCancellable();
@@ -82,20 +84,12 @@
 
     private class ProviderInterface implements NetworkServerProvider {
         public ChannelListener<ConnectedStreamChannel<InetSocketAddress>> getServerListener(final OptionMap optionMap) {
-            return new RemoteOpenListener(true, optionMap, connectionProviderContext, new Result<ConnectionHandlerFactory>() {
-                public boolean setResult(final ConnectionHandlerFactory result) {
-                    connectionProviderContext.accept(result);
-                    return true;
-                }
-
-                public boolean setException(final IOException exception) {
-                    return true;
-                }
-
-                public boolean setCancelled() {
-                    return true;
-                }
-            });
+            final String providerName = optionMap.get(RemotingOptions.AUTHENTICATION_PROVIDER);
+            final ServerAuthenticationProvider authenticationProvider = connectionProviderContext.getProtocolServiceProvider(ProtocolServiceType.SERVER_AUTHENTICATION_PROVIDER, providerName == null ? "default" : providerName);
+            if (authenticationProvider == null) {
+                throw new IllegalArgumentException("Missing authentication provider: " + (providerName == null ? "default" : providerName));
+            }
+            return new ServerOpenListener(optionMap, connectionProviderContext);
         }
     }
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -40,10 +40,12 @@
 
 final class RemoteMessageHandler implements org.jboss.xnio.channels.MessageHandler {
 
-    private RemoteConnectionHandler remoteConnectionHandler;
+    private final RemoteConnection connection;
+    private final RemoteConnectionHandler remoteConnectionHandler;
 
-    public RemoteMessageHandler(final RemoteConnectionHandler remoteConnectionHandler) {
+    RemoteMessageHandler(final RemoteConnectionHandler remoteConnectionHandler, final RemoteConnection connection) {
         this.remoteConnectionHandler = remoteConnectionHandler;
+        this.connection = connection;
     }
 
     public void handleMessage(final ByteBuffer buffer) {
@@ -75,7 +77,7 @@
                     outBuf.putInt(id);
                     outBuf.flip();
                     try {
-                        connectionHandler.sendBlocking(outBuf);
+                        connection.sendBlocking(outBuf);
                     } catch (IOException e) {
                         // the channel has suddenly failed
                         RemoteConnectionHandler.log.trace("Send failed: %s", e);
@@ -302,7 +304,7 @@
                 return;
             }
             default: {
-                RemoteConnectionHandler.log.error("Received invalid packet type on %s, closing", connectionHandler.getChannel());
+                RemoteConnectionHandler.log.error("Received invalid packet type on %s, closing", connectionHandler);
                 IoUtils.safeClose(connectionHandler);
             }
         }

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteOpenListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteOpenListener.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteOpenListener.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -1,73 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3.remote;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import org.jboss.marshalling.MarshallerFactory;
-import org.jboss.marshalling.Marshalling;
-import org.jboss.marshalling.MarshallingConfiguration;
-import org.jboss.remoting3.spi.ConnectionHandler;
-import org.jboss.remoting3.spi.ConnectionHandlerContext;
-import org.jboss.remoting3.spi.ConnectionHandlerFactory;
-import org.jboss.remoting3.spi.ConnectionProviderContext;
-import org.jboss.xnio.ChannelListener;
-import org.jboss.xnio.OptionMap;
-import org.jboss.xnio.Options;
-import org.jboss.xnio.Result;
-import org.jboss.xnio.channels.Channels;
-import org.jboss.xnio.channels.ConnectedStreamChannel;
-
-final class RemoteOpenListener implements ChannelListener<ConnectedStreamChannel<InetSocketAddress>> {
-
-    private final boolean server;
-    private final OptionMap optionMap;
-    private final ConnectionProviderContext connectionProviderContext;
-    private final Result<ConnectionHandlerFactory> factoryResult;
-
-    public RemoteOpenListener(final boolean server, final OptionMap optionMap, final ConnectionProviderContext connectionProviderContext, final Result<ConnectionHandlerFactory> factoryResult) {
-        this.server = server;
-        this.optionMap = optionMap;
-        this.connectionProviderContext = connectionProviderContext;
-        this.factoryResult = factoryResult;
-    }
-
-    public void handleEvent(final ConnectedStreamChannel<InetSocketAddress> channel) {
-        try {
-            channel.setOption(Options.TCP_NODELAY, Boolean.TRUE);
-        } catch (IOException e) {
-            // ignore
-        }
-        // TODO: For now, just build a pre-set-up connection without a negotiation phase
-        factoryResult.setResult(new ConnectionHandlerFactory() {
-            public ConnectionHandler createInstance(final ConnectionHandlerContext connectionContext) {
-                final MarshallerFactory marshallerFactory = Marshalling.getMarshallerFactory("river");
-                final MarshallingConfiguration marshallingConfiguration = new MarshallingConfiguration();
-                final RemoteConnectionHandler connectionHandler = new RemoteConnectionHandler(connectionContext, channel, marshallerFactory, marshallingConfiguration);
-                Channels.createMessageReader(channel, optionMap).set(new RemoteMessageHandler(connectionHandler));
-                channel.resumeReads();
-                return connectionHandler;
-            }
-        });
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -33,6 +33,11 @@
  */
 public final class RemoteProtocol {
 
+    /**
+     * The highest-supported version of the remote protocol supported by this implementation.
+     */
+    public static final byte VERSION = 0;
+
     static final int MSG_FLAG_FIRST = 1;
     static final int MSG_FLAG_LAST = 2;
 
@@ -49,6 +54,19 @@
     static final byte REPLY_ACK_CHUNK = 10;
     static final byte REPLY_EXCEPTION_ABORT = 11;
 
+    static final byte AUTH_REQUEST = 12;
+    static final byte AUTH_CHALLENGE = 13;
+    static final byte AUTH_RESPONSE = 14;
+    static final byte AUTH_COMPLETE = 15;
+    static final byte AUTH_REJECTED = 16;
+
+    static final byte ALIVE = 99;
+
+    // Greeting types
+
+    static final byte GREETING_VERSION = 0;   // sent by client & server
+    static final byte GREETING_SASL_MECH = 1; // sent by server
+
     /**
      * Create an instance of the connection provider for the "remote" protocol.
      *

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslClientContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslClientContext.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslClientContext.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.nio.ByteBuffer;
+
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+final class SaslClientContext implements SaslContext {
+    private final SaslClient saslClient;
+
+    SaslClientContext(final SaslClient saslClient) {
+        this.saslClient = saslClient;
+    }
+
+    public String getMechanismName() {
+        return saslClient.getMechanismName();
+    }
+
+    public Object getNegotiatedProperty(final String name) {
+        return saslClient.getNegotiatedProperty(name);
+    }
+
+    public ByteBuffer unwrap(final ByteBuffer src) throws SaslException {
+        final byte[] unwrapped;
+        if (src.hasArray()) {
+            final byte[] orig = src.array();
+            final int start = src.arrayOffset() + src.position();
+            final int len = src.remaining();
+            unwrapped = saslClient.unwrap(orig, start, len);
+        } else {
+            final int len = src.remaining();
+            final byte[] orig = new byte[len];
+            src.get(orig);
+            unwrapped = saslClient.unwrap(orig, 0, len);
+        }
+        return ByteBuffer.wrap(unwrapped);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslContext.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslContext.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,35 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.nio.ByteBuffer;
+
+import javax.security.sasl.SaslException;
+
+interface SaslContext {
+    String getMechanismName();
+
+    Object getNegotiatedProperty(String name);
+
+    ByteBuffer unwrap(ByteBuffer src) throws SaslException;
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslServerContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslServerContext.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslServerContext.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.nio.ByteBuffer;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+final class SaslServerContext implements SaslContext {
+    private final SaslServer saslServer;
+
+    SaslServerContext(final SaslServer saslServer) {
+        this.saslServer = saslServer;
+    }
+
+    public String getMechanismName() {
+        return saslServer.getMechanismName();
+    }
+
+    public Object getNegotiatedProperty(final String name) {
+        return saslServer.getNegotiatedProperty(name);
+    }
+
+    public ByteBuffer unwrap(final ByteBuffer src) throws SaslException {
+        final byte[] unwrapped;
+        if (src.hasArray()) {
+            final byte[] orig = src.array();
+            final int start = src.arrayOffset() + src.position();
+            final int len = src.remaining();
+            unwrapped = saslServer.unwrap(orig, start, len);
+        } else {
+            final int len = src.remaining();
+            final byte[] orig = new byte[len];
+            src.get(orig);
+            unwrapped = saslServer.unwrap(orig, 0, len);
+        }
+        return ByteBuffer.wrap(unwrapped);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUnwrappingMessageHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUnwrappingMessageHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUnwrappingMessageHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.sasl.SaslException;
+
+final class SaslUnwrappingMessageHandler implements MessageHandler, MessageHandler.Setter {
+    private final SaslContext saslContext;
+    private volatile MessageHandler delegate;
+
+    SaslUnwrappingMessageHandler(final SaslContext saslContext, final MessageHandler delegate) {
+        this.saslContext = saslContext;
+        this.delegate = delegate;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        try {
+            delegate.handleMessage(saslContext.unwrap(buffer));
+        } catch (SaslException e) {
+            delegate.handleException(e);
+        }
+    }
+
+    public void handleEof() {
+        delegate.handleEof();
+    }
+
+    public void handleException(final IOException e) {
+        delegate.handleException(e);
+    }
+
+    public void set(final MessageHandler messageHandler) {
+        delegate = messageHandler;
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.Option;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Options;
+import org.jboss.xnio.SaslQop;
+import org.jboss.xnio.Sequence;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+final class SaslUtils {
+
+    private SaslUtils() {
+    }
+
+    static final byte[] EMPTY = new byte[0];
+
+    static Map<String, Object> createPropertyMap(OptionMap optionMap) {
+        final Map<String,Object> propertyMap = new HashMap<String, Object>();
+
+        add(optionMap, Options.SASL_POLICY_FORWARD_SECRECY, propertyMap, Sasl.POLICY_FORWARD_SECRECY);
+        add(optionMap, Options.SASL_POLICY_NOACTIVE, propertyMap, Sasl.POLICY_NOACTIVE);
+        add(optionMap, Options.SASL_POLICY_NOANONYMOUS, propertyMap, Sasl.POLICY_NOANONYMOUS);
+        add(optionMap, Options.SASL_POLICY_NODICTIONARY, propertyMap, Sasl.POLICY_NODICTIONARY);
+        add(optionMap, Options.SASL_POLICY_NOPLAINTEXT, propertyMap, Sasl.POLICY_NOPLAINTEXT);
+        add(optionMap, Options.SASL_POLICY_PASS_CREDENTIALS, propertyMap, Sasl.POLICY_PASS_CREDENTIALS);
+        add(optionMap, Options.SASL_REUSE, propertyMap, Sasl.REUSE);
+        add(optionMap, Options.SASL_SERVER_AUTH, propertyMap, Sasl.SERVER_AUTH);
+        addQopList(optionMap, Options.SASL_QOP, propertyMap, Sasl.QOP);
+        add(optionMap, Options.SASL_STRENGTH, propertyMap, Sasl.STRENGTH);
+        return propertyMap;
+    }
+
+    private static void add(OptionMap optionMap, Option<?> option, Map<String, Object> map, String propName) {
+        final Object value = optionMap.get(option);
+        if (value != null) map.put(propName, value.toString().toLowerCase());
+    }
+
+    private static void addQopList(OptionMap optionMap, Option<Sequence<SaslQop>> option, Map<String, Object> map, String propName) {
+        final Sequence<SaslQop> seq = optionMap.get(option);
+        final StringBuilder builder = new StringBuilder();
+        final Iterator<SaslQop> iterator = seq.iterator();
+        while (iterator.hasNext()) {
+            builder.append(iterator.next());
+            if (iterator.hasNext()) {
+                builder.append(',');
+            }
+        }
+    }
+
+    private static final Set<String> SECURE_QOP;
+
+    static {
+        final Set<String> set = new HashSet<String>();
+        set.add("auth-int");
+        set.add("auth-conf");
+        SECURE_QOP = set;
+    }
+
+    static boolean isSecureQop(Object qop) {
+        return SECURE_QOP.contains(qop);
+    }
+
+    static void wrapFramed(SaslClient saslClient, ByteBuffer message) throws SaslException {
+        final byte[] result;
+        if (message.hasArray()) {
+            result = saslClient.wrap(message.array(), message.arrayOffset() + 4, message.position());
+        } else {
+            final int end = message.position();
+            message.position(4);
+            final byte[] bytes = Buffers.take(message, end - 4);
+            result = saslClient.wrap(bytes, 0, bytes.length);
+        }
+        message.position(4);
+        message.put(result);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import org.jboss.marshalling.MarshallerFactory;
+import org.jboss.marshalling.Marshalling;
+import org.jboss.marshalling.MarshallingConfiguration;
+import org.jboss.remoting3.CloseHandler;
+import org.jboss.remoting3.spi.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerContext;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+final class ServerAuthenticationHandler implements MessageHandler {
+    private final RemoteConnection remoteConnection;
+    private final SaslServer saslServer;
+    private final ConnectionProviderContext connectionProviderContext;
+
+    ServerAuthenticationHandler(final RemoteConnection remoteConnection, final SaslServer saslServer, final ConnectionProviderContext connectionProviderContext) {
+        this.saslServer = saslServer;
+        this.remoteConnection = remoteConnection;
+        this.connectionProviderContext = connectionProviderContext;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        switch (buffer.get()) {
+            case RemoteProtocol.AUTH_RESPONSE: {
+                final byte[] challenge;
+                try {
+                    try {
+                        challenge = saslServer.evaluateResponse(Buffers.take(buffer, buffer.remaining()));
+                    } catch (SaslException e) {
+                        // todo log it
+                        remoteConnection.sendAuthReject("Authentication failed");
+                        return;
+                    }
+                    final boolean complete = saslServer.isComplete();
+                    if (complete) {
+                        remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_COMPLETE, challenge);
+                        connectionProviderContext.accept(new ConnectionHandlerFactory() {
+                            public ConnectionHandler createInstance(final ConnectionHandlerContext connectionContext) {
+                                final MarshallerFactory marshallerFactory = Marshalling.getMarshallerFactory("river");
+                                final MarshallingConfiguration marshallingConfiguration = new MarshallingConfiguration();
+                                final RemoteConnectionHandler connectionHandler = new RemoteConnectionHandler(connectionContext, remoteConnection, marshallerFactory, marshallingConfiguration);
+                                remoteConnection.addCloseHandler(new CloseHandler<Object>() {
+                                    public void handleClose(final Object closed) {
+                                        IoUtils.safeClose(connectionHandler);
+                                    }
+                                });
+                                remoteConnection.setMessageHandler(new RemoteMessageHandler(connectionHandler, remoteConnection));
+                                return connectionHandler;
+                            }
+                        });
+                    } else {
+                        remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_CHALLENGE, challenge);
+                    }
+                } catch (IOException e) {
+                    // todo log it; close channel
+                    IoUtils.safeClose(remoteConnection);
+                }
+            }
+            default: {
+                // todo log invalid msg
+                IoUtils.safeClose(remoteConnection);
+            }
+        }
+    }
+
+    public void handleEof() {
+        IoUtils.safeClose(remoteConnection);
+    }
+
+    public void handleException(final IOException e) {
+        IoUtils.safeClose(remoteConnection);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.channels.MessageHandler;
+
+final class ServerGreetingHandler implements MessageHandler {
+    private final RemoteConnection connection;
+    private final ConnectionProviderContext connectionProviderContext;
+    private final Set<String> saslMechs;
+    private final ServerAuthenticationProvider provider;
+    private final Map<String, Object> propertyMap;
+
+    public ServerGreetingHandler(final RemoteConnection connection, final ConnectionProviderContext connectionProviderContext, final Set<String> saslMechs, final ServerAuthenticationProvider provider, final Map<String, Object> propertyMap) {
+        this.connection = connection;
+        this.connectionProviderContext = connectionProviderContext;
+        this.saslMechs = saslMechs;
+        this.provider = provider;
+        this.propertyMap = propertyMap;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        switch (buffer.get()) {
+            case RemoteProtocol.GREETING: {
+                while (buffer.hasRemaining()) {
+                    final byte type = buffer.get();
+                    final int len = buffer.get() & 0xff;
+                    switch (type) {
+                        case RemoteProtocol.GREETING_VERSION: {
+                            // We only support version zero, so knowing the other side's version is not useful presently
+                            buffer.get();
+                            if (len > 1) Buffers.skip(buffer, len - 1);
+                            break;
+                        }
+                        default: {
+                            // unknown, skip it for forward compatibility.
+                            Buffers.skip(buffer, len);
+                            break;
+                        }
+                    }
+                }
+                connection.setMessageHandler(new ServerInitialAuthenticationHandler(connection, propertyMap, saslMechs, provider, connectionProviderContext));
+                return;
+            }
+            default: {
+                // todo log invalid greeting
+                IoUtils.safeClose(connection);
+            }
+        }
+    }
+
+    public void handleEof() {
+        IoUtils.safeClose(connection);
+    }
+
+    public void handleException(final IOException e) {
+        // todo log it
+        IoUtils.safeClose(connection);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,92 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.xnio.Buffers;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.channels.MessageHandler;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServer;
+
+final class ServerInitialAuthenticationHandler implements MessageHandler {
+    private final RemoteConnection remoteConnection;
+    private final Map<String, ?> saslPropertyMap;
+    private final Set<String> allowedMechsMap;
+    private final ServerAuthenticationProvider authenticationProvider;
+    private final ConnectionProviderContext connectionProviderContext;
+
+    ServerInitialAuthenticationHandler(final RemoteConnection remoteConnection, final Map<String, ?> saslPropertyMap, final Set<String> allowedMechsMap, final ServerAuthenticationProvider authenticationProvider, final ConnectionProviderContext connectionProviderContext) {
+        this.remoteConnection = remoteConnection;
+        this.saslPropertyMap = saslPropertyMap;
+        this.allowedMechsMap = allowedMechsMap;
+        this.authenticationProvider = authenticationProvider;
+        this.connectionProviderContext = connectionProviderContext;
+    }
+
+    public void handleMessage(final ByteBuffer buffer) {
+        switch (buffer.get()) {
+            case RemoteProtocol.AUTH_REQUEST: {
+                try {
+                    // mech name
+                    final String name = Buffers.getModifiedUtf8(buffer);
+                    if (allowedMechsMap.contains(name)) {
+                        final SaslServer server = Sasl.createSaslServer(name, "remote", remoteConnection.getChannel().getLocalAddress().getHostName(), saslPropertyMap, authenticationProvider.getCallbackHandler());
+                        remoteConnection.setMessageHandler(new ServerAuthenticationHandler(remoteConnection, server, connectionProviderContext));
+                        remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_CHALLENGE, SaslUtils.EMPTY);
+                        return;
+                    } else {
+                        remoteConnection.sendAuthReject("Invalid mechanism name");
+                        return;
+                    }
+                } catch (IOException e) {
+                    IoUtils.safeClose(remoteConnection);
+                    // todo log it
+                    return;
+                }
+            }
+            default: {
+                // todo log invalid msg
+                IoUtils.safeClose(remoteConnection);
+            }
+        }
+    }
+
+    public void handleEof() {
+        try {
+            remoteConnection.shutdownReads();
+        } catch (IOException e) {
+            // todo log it
+        }
+    }
+
+    public void handleException(final IOException e) {
+        // todo log it
+    }
+}

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java (from rev 5760, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteOpenListener.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import org.jboss.remoting3.RemotingOptions;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.remoting3.spi.ProtocolServiceType;
+import org.jboss.xnio.ChannelListener;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Options;
+import org.jboss.xnio.Sequence;
+import org.jboss.xnio.channels.ConnectedStreamChannel;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServerFactory;
+
+final class ServerOpenListener implements ChannelListener<ConnectedStreamChannel<InetSocketAddress>> {
+
+    private final OptionMap optionMap;
+    private final ConnectionProviderContext connectionProviderContext;
+
+    ServerOpenListener(final OptionMap optionMap, final ConnectionProviderContext connectionProviderContext) {
+        this.optionMap = optionMap;
+        this.connectionProviderContext = connectionProviderContext;
+    }
+
+    public void handleEvent(final ConnectedStreamChannel<InetSocketAddress> channel) {
+        try {
+            channel.setOption(Options.TCP_NODELAY, Boolean.TRUE);
+        } catch (IOException e) {
+            // ignore
+        }
+        final RemoteConnection connection = new RemoteConnection(connectionProviderContext.getExecutor(), channel, optionMap);
+
+        // Calculate available server mechanisms
+        final Sequence<String> mechs = optionMap.get(RemotingOptions.SASL_SERVER_MECHANISMS);
+        final Set<String> includes = mechs != null ? new HashSet<String>(mechs) : null;
+        final Set<String> serverMechanisms = new LinkedHashSet<String>();
+        final Map<String, Object> propertyMap = SaslUtils.createPropertyMap(optionMap);
+        final Enumeration<SaslServerFactory> e = Sasl.getSaslServerFactories();
+        while (e.hasMoreElements()) {
+            final SaslServerFactory saslServerFactory = e.nextElement();
+            for (String name : saslServerFactory.getMechanismNames(propertyMap)) {
+                if (includes == null || includes.contains(name)) {
+                    serverMechanisms.add(name);
+                }
+            }
+        }
+
+        // Send server greeting packet...
+        final ByteBuffer buffer = connection.allocate();
+        try {
+            // length placeholder
+            buffer.putInt(0);
+            // version ID
+            GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION, RemoteProtocol.VERSION);
+            // SASL server mechs
+            for (String name : serverMechanisms) {
+                GreetingUtils.writeString(buffer, RemoteProtocol.GREETING_SASL_MECH, name);
+            }
+            // that's it!
+            buffer.flip();
+            connection.sendBlocking(buffer);
+        } catch (Exception e1) {
+            // todo log it
+            IoUtils.safeClose(connection);
+        } finally {
+            connection.free(buffer);
+        }
+        final String authProvider = optionMap.get(RemotingOptions.AUTHENTICATION_PROVIDER);
+        if (authProvider == null) {
+            // todo log no valid auth provider
+            IoUtils.safeClose(connection);
+        }
+        final ServerAuthenticationProvider provider = connectionProviderContext.getProtocolServiceProvider(ProtocolServiceType.SERVER_AUTHENTICATION_PROVIDER, authProvider);
+        if (provider == null) {
+            // todo log no valid auth provider
+            IoUtils.safeClose(connection);
+        }
+        connection.setMessageHandler(new ServerGreetingHandler(connection, connectionProviderContext, serverMechanisms, provider, propertyMap));
+        // start up the read cycle
+        channel.resumeReads();
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/ServerAuthenticationProvider.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/ServerAuthenticationProvider.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/ServerAuthenticationProvider.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.security;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ */
+public interface ServerAuthenticationProvider {
+    CallbackHandler getCallbackHandler();
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ProtocolServiceType.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ProtocolServiceType.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ProtocolServiceType.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -29,6 +29,7 @@
 import org.jboss.marshalling.ClassExternalizerFactory;
 import org.jboss.marshalling.ProviderDescriptor;
 import java.io.Serializable;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
 
 public final class ProtocolServiceType<T> implements Serializable {
 
@@ -77,6 +78,8 @@
 
     public static final ProtocolServiceType<ClassExternalizerFactory> CLASS_EXTERNALIZER_FACTORY;
 
+    public static final ProtocolServiceType<ServerAuthenticationProvider> SERVER_AUTHENTICATION_PROVIDER;
+
     private static final ProtocolServiceType<?>[] SERVICE_TYPES;
 
     public static ProtocolServiceType<?>[] getServiceTypes() {
@@ -96,6 +99,7 @@
                 CLASS_RESOLVER = new ProtocolServiceType<ClassResolver>(ClassResolver.class, "CLASS_RESOLVER", "Class resolver", index++),
                 OBJECT_RESOLVER = new ProtocolServiceType<ObjectResolver>(ObjectResolver.class, "OBJECT_RESOLVER", "Object resolver", index++),
                 CLASS_EXTERNALIZER_FACTORY = new ProtocolServiceType<ClassExternalizerFactory>(ClassExternalizerFactory.class, "CLASS_EXTERNALIZER_FACTORY", "Class externalizer factory", index++),
+                SERVER_AUTHENTICATION_PROVIDER = new ProtocolServiceType<ServerAuthenticationProvider>(ServerAuthenticationProvider.class, "SERVER_AUTHENTICATION_PROVIDER", "Server authentication provider", index++)
         };
     }
 

Modified: remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/InvocationTestBase.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/InvocationTestBase.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/InvocationTestBase.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -62,13 +62,15 @@
         }
     }
 
-    private static void enter() {
-        log.info("Entering: %s", new Throwable().getStackTrace()[1].getMethodName());
+    static void enter() {
+        final StackTraceElement e = new Throwable().getStackTrace()[1];
+        log.info("Entering: %s#%s", e.getClassName(), e.getMethodName());
     }
 
-    private static void exit() {
-        log.info("Exiting: %s", new Throwable().getStackTrace()[1].getMethodName());
-        log.info("-----------------------------------------");
+    static void exit() {
+        final StackTraceElement e = new Throwable().getStackTrace()[1];
+        log.info("Exiting: %s#%s", e.getClassName(), e.getMethodName());
+        log.info("-------------------------------------------------------------");
     }
 
     protected abstract Connection getConnection() throws IOException;

Modified: remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/LocalTestCase.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/LocalTestCase.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/LocalTestCase.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -28,7 +28,7 @@
 import org.jboss.xnio.OptionMap;
 import org.testng.annotations.Test;
 
- at Test
+ at Test(suiteName = "Local tests")
 public final class LocalTestCase extends InvocationTestBase {
 
     protected Connection getConnection() throws IOException {

Modified: remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java	2010-02-28 00:58:32 UTC (rev 5770)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java	2010-02-28 15:51:38 UTC (rev 5771)
@@ -28,7 +28,10 @@
 import java.net.URI;
 import org.jboss.remoting3.CloseHandler;
 import org.jboss.remoting3.Connection;
+import org.jboss.remoting3.RemotingOptions;
+import org.jboss.remoting3.security.ServerAuthenticationProvider;
 import org.jboss.remoting3.spi.NetworkServerProvider;
+import org.jboss.remoting3.spi.ProtocolServiceType;
 import org.jboss.xnio.AcceptingServer;
 import org.jboss.xnio.ChannelListener;
 import org.jboss.xnio.IoFuture;
@@ -37,21 +40,63 @@
 import org.jboss.xnio.Xnio;
 import org.jboss.xnio.channels.BoundChannel;
 import org.jboss.xnio.channels.ConnectedStreamChannel;
+import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
- at Test
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.RealmCallback;
+
+ at Test(suiteName = "Remote tests")
 public final class RemoteTestCase extends InvocationTestBase {
 
+    @BeforeTest
+    public void setUp() throws IOException {
+        enter();
+        try {
+            super.setUp();
+            endpoint.addProtocolService(ProtocolServiceType.SERVER_AUTHENTICATION_PROVIDER, "test", new ServerAuthenticationProvider() {
+                public CallbackHandler getCallbackHandler() {
+                    return new CallbackHandler() {
+                        public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                            for (Callback callback : callbacks) {
+                                if (callback instanceof NameCallback) {
+                                    final NameCallback nameCallback = (NameCallback) callback;
+                                    if (! nameCallback.getName().equals("user")) {
+                                        throw new AuthenticationException("Invalid user name");
+                                    }
+                                } else if (callback instanceof PasswordCallback) {
+                                    final PasswordCallback passwordCallback = (PasswordCallback) callback;
+                                    passwordCallback.setPassword("password".toCharArray());
+                                } else if (callback instanceof RealmCallback) {
+                                    // allow
+                                } else {
+                                    throw new UnsupportedCallbackException(callback);
+                                }
+                            }
+                        }
+                    };
+                }
+            });
+        } finally {
+            exit();
+        }
+    }
+
     protected Connection getConnection() throws IOException {
         final NetworkServerProvider provider = endpoint.getConnectionProviderInterface("remote", NetworkServerProvider.class);
-        final ChannelListener<ConnectedStreamChannel<InetSocketAddress>> listener = provider.getServerListener(OptionMap.EMPTY);
+        final ChannelListener<ConnectedStreamChannel<InetSocketAddress>> listener = provider.getServerListener(OptionMap.builder().set(RemotingOptions.AUTHENTICATION_PROVIDER, "test").getMap());
         final Xnio xnio = Xnio.getInstance();
         try {
             final AcceptingServer<InetSocketAddress, ?, ?> server = xnio.createSslTcpServer(listener, OptionMap.EMPTY);
 //            final AcceptingServer<InetSocketAddress, ?, ?> server = xnio.createTcpServer(listener, OptionMap.EMPTY);
             final IoFuture<? extends BoundChannel<InetSocketAddress>> future = server.bind(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0));
             final InetSocketAddress localAddress = future.get().getLocalAddress();
-            final Connection connection = endpoint.connect(new URI("remote", null, localAddress.getAddress().getHostAddress(), localAddress.getPort(), null, null, null), OptionMap.EMPTY).get();
+            final Connection connection = endpoint.connect(new URI("remote", null, localAddress.getAddress().getHostAddress(), localAddress.getPort(), null, null, null), OptionMap.EMPTY, "user", "realm", "password".toCharArray()).get();
             connection.addCloseHandler(new CloseHandler<Connection>() {
                 public void handleClose(final Connection closed) {
                     IoUtils.safeClose(server);



More information about the jboss-remoting-commits mailing list