Repository: geode Updated Branches: refs/heads/feature/GEODE-3285 7bdd362be -> 5139a6c2f
WIP Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/5139a6c2 Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/5139a6c2 Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/5139a6c2 Branch: refs/heads/feature/GEODE-3285 Commit: 5139a6c2f67f1c0d60666e85f9ddca2fa5f8a547 Parents: 7bdd362 Author: Hitesh Khamesra <hitesh...@yahoo.com> Authored: Mon Jul 31 09:38:30 2017 -0700 Committer: Hitesh Khamesra <hitesh...@yahoo.com> Committed: Mon Jul 31 09:38:30 2017 -0700 ---------------------------------------------------------------------- .../GenericProtocolServerConnection.java | 32 +++++++-- .../tier/sockets/sasl/SaslAuthenticator.java | 13 ++-- .../tier/sockets/sasl/SaslCallbackHandler.java | 41 +++++++++++- .../cache/tier/sockets/sasl/SaslHandler.java | 13 ++++ .../cache/tier/sockets/sasl/SaslMessenger.java | 33 +++++++--- .../GenericProtocolServerConnectionTest.java | 10 +++ .../sockets/sasl/SaslAuthenticatorTest.java | 30 +++++++-- .../sockets/sasl/SaslCallbackHandlerTest.java | 24 +++++++ .../tier/sockets/sasl/SaslMessengerTest.java | 57 ++++++++++++++-- .../RoundTripCacheConnectionJUnitTest.java | 69 +++++++++++++++++++- 10 files changed, 290 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnection.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnection.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnection.java index c5c413a..215d796 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnection.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnection.java @@ -18,12 +18,18 @@ package org.apache.geode.internal.cache.tier.sockets; import org.apache.geode.internal.cache.InternalCache; import org.apache.geode.internal.cache.tier.Acceptor; import org.apache.geode.internal.cache.tier.CachedRegionHelper; +import org.apache.geode.internal.cache.tier.sockets.sasl.SaslAuthenticator; +import org.apache.geode.internal.cache.tier.sockets.sasl.SaslCallbackHandler; +import org.apache.geode.internal.cache.tier.sockets.sasl.SaslMessenger; import org.apache.geode.internal.security.SecurityService; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import java.io.*; import java.net.Socket; +import java.nio.channels.AcceptPendingException; +import java.util.Collections; /** * Holds the socket and protocol handler for the new client protocol. @@ -31,6 +37,7 @@ import java.net.Socket; public class GenericProtocolServerConnection extends ServerConnection { // The new protocol lives in a separate module and gets loaded when this class is instantiated. private final ClientProtocolMessageHandler messageHandler; + private boolean isAutenticated = false; /** * Creates a new <code>GenericProtocolServerConnection</code> that processes messages received @@ -51,7 +58,9 @@ public class GenericProtocolServerConnection extends ServerConnection { Socket socket = this.getSocket(); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); - + DataInputStream dataInputStream = new DataInputStream(inputStream); + DataOutputStream dataOutputStream = new DataOutputStream(outputStream); + authenticateClient(dataInputStream, dataOutputStream); messageHandler.receiveMessage(inputStream, outputStream, this.getCache()); } catch (IOException e) { logger.warn(e); @@ -59,6 +68,21 @@ public class GenericProtocolServerConnection extends ServerConnection { } } + private void authenticateClient(DataInputStream inputStream, DataOutputStream outputStream) + throws IOException { + SaslServer saslServer = Sasl.createSaslServer("PLAIN", "geode", "localhost", Collections.emptyMap(), new SaslCallbackHandler()); + SaslAuthenticator saslAuthenticator = new SaslAuthenticator(saslServer, new SaslMessenger(inputStream, outputStream)); +// if(!isAutenticated) { + if (saslAuthenticator.authenticateClient()) { + outputStream.writeByte(Acceptor.SUCCESSFUL_SERVER_TO_CLIENT); + } else { + outputStream.writeByte(Acceptor.UNSUCCESSFUL_SERVER_TO_CLIENT); + } + isAutenticated = true; +// } + System.out.println("Done authenticating"); + } + @Override protected boolean doHandShake(byte epType, int qSize) { // return (new SaslAuthenticator(theSocket, securityService)).authenticateClient(); http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticator.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticator.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticator.java index 2be0848..caf06c2 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticator.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticator.java @@ -15,9 +15,6 @@ package org.apache.geode.internal.cache.tier.sockets.sasl; -import java.net.Socket; -import java.security.Security; - import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; @@ -26,18 +23,18 @@ import org.apache.logging.log4j.Logger; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.security.SecurityService; +import java.io.IOException; + /** * SaslAuthenticator performs simple authentication using SASL */ public class SaslAuthenticator { protected static final Logger logger = LogService.getLogger(); - private final SecurityService securityService; private final SaslServer saslServer; private final SaslMessenger saslMessenger; - public SaslAuthenticator(SecurityService securityService, SaslServer saslServer, SaslMessenger saslMessenger) { - this.securityService = securityService; + public SaslAuthenticator(SaslServer saslServer, SaslMessenger saslMessenger) { this.saslServer = saslServer; this.saslMessenger = saslMessenger; } @@ -51,10 +48,12 @@ public class SaslAuthenticator { byte[] response = saslMessenger.readMessage(); challenge = saslServer.evaluateResponse(response); } + System.out.println(">>>>>>> Completed authentication"); return true; - } catch (SaslException e) { + } catch (IOException e) { logger.warn("client authentication failed", e); + return false; } } http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandler.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandler.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandler.java index 8fe1193..099a7be 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandler.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandler.java @@ -19,7 +19,11 @@ import java.io.IOException; 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.TextOutputCallback; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; /** * SASL invokes a callback handler during authentication @@ -29,7 +33,42 @@ public class SaslCallbackHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (Callback callback: callbacks) { + System.out.println("ClientCallbackHandler processing callback " + callback); - } + if (callback instanceof TextOutputCallback) { + // display the message according to the specified type + TextOutputCallback toc = (TextOutputCallback) callback; + switch (toc.getMessageType()) { + case TextOutputCallback.INFORMATION: + System.out.println(toc.getMessage()); + break; + case TextOutputCallback.ERROR: + System.out.println("ERROR: " + toc.getMessage()); + break; + case TextOutputCallback.WARNING: + System.out.println("WARNING: " + toc.getMessage()); + break; + default: + throw new IOException("Unsupported message type: " + + toc.getMessageType()); + } + + } else if (callback instanceof NameCallback) { + NameCallback nc = (NameCallback) callback; + System.out.println("name from name callback: " +nc.getDefaultName()); + } else if (callback instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) callback; + System.out.println("client is setting password"); + pc.setPassword("secretsecret".toCharArray()); + } else if (callback instanceof AuthorizeCallback) { + AuthorizeCallback ac = (AuthorizeCallback) callback; + ac.setAuthorized(true); + } else { + throw new UnsupportedCallbackException + (callback, "Unrecognized Callback"); + } + } + } } http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslHandler.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslHandler.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslHandler.java new file mode 100644 index 0000000..3338459 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslHandler.java @@ -0,0 +1,13 @@ +package org.apache.geode.internal.cache.tier.sockets.sasl; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import java.io.IOException; + +public class SaslHandler implements CallbackHandler { + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessenger.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessenger.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessenger.java index 99d6c23..5a37fcb 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessenger.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessenger.java @@ -1,17 +1,32 @@ package org.apache.geode.internal.cache.tier.sockets.sasl; -/** - * Created by bschuchardt on 7/26/17. - */ -class SaslMessenger { +import org.apache.geode.internal.HeapDataOutputStream; +import org.apache.geode.internal.InternalDataSerializer; +import org.apache.geode.internal.util.BlobHelper; - public void sendMessage(byte[] capture) { - // TODO - send the message +import java.io.*; +import java.net.Socket; + +public class SaslMessenger { + private DataInput inputStream; + private DataOutput outputStream; + + public SaslMessenger(DataInput inputStream, DataOutput outputStream) { + this.inputStream = inputStream; + this.outputStream = outputStream; } - public byte[] readMessage() { - // TODO - read a message - return null; + public void sendMessage(byte[] capture) throws IOException { + //InternalDataSerializer.writeByteArray(capture, outputStream); + outputStream.writeInt(capture.length); + outputStream.write(capture); } + public byte[] readMessage() throws IOException { + //byte[] ret = InternalDataSerializer.readByteArray(inputStream); + int byteArrayLength = inputStream.readInt(); + byte[] ret = new byte[byteArrayLength]; + inputStream.readFully(ret); + return ret; + } } http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java index 3bfcd8b..5e4320b 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java @@ -47,6 +47,16 @@ public class GenericProtocolServerConnectionTest { } } + @Test + public void testAuthenticationSuccess() throws IOException { + ServerConnection serverConnection = IOExceptionThrowingServerConnection(); + Assert.assertTrue(serverConnection.processMessages); + serverConnection.doOneMessage(); + } + + @Test + public void testAuthenticationFailure() {} + private static ServerConnection IOExceptionThrowingServerConnection() throws IOException { Socket socketMock = mock(Socket.class); when(socketMock.getInetAddress()).thenReturn(InetAddress.getByName("localhost")); http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticatorTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticatorTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticatorTest.java index ecf427a..9028b56 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticatorTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslAuthenticatorTest.java @@ -21,6 +21,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.List; import javax.security.sasl.SaslException; @@ -37,11 +39,10 @@ import org.apache.geode.test.junit.categories.UnitTest; public class SaslAuthenticatorTest { @Test public void authenticateClientPassesResponsesToSaslServerTillComplete() throws Exception { - SecurityService securityServiceStub = mock(SecurityService.class); SaslServer saslServerMock = mock(SaslServer.class); SaslMessenger saslMessengerStub = mock(SaslMessenger.class); SaslAuthenticator - saslServer = new SaslAuthenticator(securityServiceStub, saslServerMock, saslMessengerStub); + saslServer = new SaslAuthenticator(saslServerMock, saslMessengerStub); ArgumentCaptor<byte[]> saslServerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); ArgumentCaptor<byte[]> messengerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); byte[][] challengesFromServer = { @@ -72,12 +73,11 @@ public class SaslAuthenticatorTest { } @Test - public void authenticateClientReturnsFalseIfCredentialsAreWrong() throws SaslException { - SecurityService securityServiceStub = mock(SecurityService.class); + public void authenticateClientReturnsFalseIfCredentialsAreWrong() throws IOException { SaslServer saslServerMock = mock(SaslServer.class); SaslMessenger saslMessengerStub = mock(SaslMessenger.class); SaslAuthenticator - saslServer = new SaslAuthenticator(securityServiceStub, saslServerMock, saslMessengerStub); + saslServer = new SaslAuthenticator(saslServerMock, saslMessengerStub); ArgumentCaptor<byte[]> saslServerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); ArgumentCaptor<byte[]> messengerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); byte[][] challengesFromServer = { @@ -96,5 +96,23 @@ public class SaslAuthenticatorTest { } @Test - public void authenticateClientReturnsFalseIfClientStopsResponding(){} + public void authenticateClientReturnsFalseIfClientStopsResponding() throws IOException { + SaslServer saslServerMock = mock(SaslServer.class); + SaslMessenger saslMessengerStub = mock(SaslMessenger.class); + SaslAuthenticator + saslServer = new SaslAuthenticator(saslServerMock, saslMessengerStub); + ArgumentCaptor<byte[]> saslServerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); + ArgumentCaptor<byte[]> messengerArgumentCaptor = ArgumentCaptor.forClass(byte[].class); + byte[][] challengesFromServer = { + new byte[] {0, 1, 2}, + new byte[0], + }; + when(saslServerMock.evaluateResponse(isA(byte[].class))).thenReturn(challengesFromServer[0]).thenReturn(new byte[0]); + when(saslServerMock.isComplete()).thenReturn(false); + when(saslMessengerStub.readMessage()).thenThrow(new SocketTimeoutException()); + + boolean authenticateClient = saslServer.authenticateClient(); + + assertFalse(authenticateClient); + } } http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandlerTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandlerTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandlerTest.java new file mode 100644 index 0000000..2c679c4 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslCallbackHandlerTest.java @@ -0,0 +1,24 @@ +package org.apache.geode.internal.cache.tier.sockets.sasl; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.test.junit.categories.UnitTest; + +@Category(UnitTest.class) +public class SaslCallbackHandlerTest { + @Test + public void testHandlePassesCredentialsToSecurityManaget() { +// SecurityManager securityManagerMock = mock(SecurityManager.class); +// new SaslCallbackHandler(securityManagerMock); +// List list = new ArrayList(); +// SaslCallbackHandler.handle(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessengerTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessengerTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessengerTest.java index 4cfc244..ce19785 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessengerTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/sasl/SaslMessengerTest.java @@ -1,8 +1,57 @@ -import static org.junit.Assert.*; +package org.apache.geode.internal.cache.tier.sockets.sasl; -/** - * Created by bschuchardt on 7/27/17. - */ +import com.sun.xml.internal.messaging.saaj.util.ByteInputStream; +import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; +import org.apache.geode.internal.ByteArrayDataInput; +import org.apache.geode.internal.HeapDataOutputStream; +import org.apache.geode.internal.InternalDataSerializer; +import org.apache.geode.test.junit.categories.UnitTest; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.io.*; + +import static org.junit.Assert.assertArrayEquals; + +@Category(UnitTest.class) public class SaslMessengerTest { + private DataInputStream inputStream; + private HeapDataOutputStream outputStream; + private SaslMessenger saslMessenger; + private byte[] message; + private byte[] outPutArray; + + @Before + public void setup() { + message = new byte[]{2, 2}; + outPutArray = new byte[1000]; + outputStream = new HeapDataOutputStream(outPutArray); + saslMessenger = new SaslMessenger(inputStream, outputStream); + } + + @Test + public void sendMessageWritesMessageToStream() throws IOException { + saslMessenger.sendMessage(message); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray()); + byte[] ret =InternalDataSerializer.readByteArray(new DataInputStream(byteArrayInputStream)); + assertArrayEquals(message, ret); + } + + @Test + public void readMessageReturnsTheNextMessage() throws IOException { + HeapDataOutputStream tempOutputStream = new HeapDataOutputStream(outPutArray); + InternalDataSerializer.writeByteArray(message, tempOutputStream); + byte[] serializedBytes = tempOutputStream.toByteArray(); + + inputStream = new DataInputStream(new ByteInputStream(serializedBytes, serializedBytes.length)); + SaslMessenger saslMessenger = new SaslMessenger(inputStream, tempOutputStream); + + byte[] readMessage = saslMessenger.readMessage(); + assertArrayEquals(message, readMessage); + } + + @Test + public void readMessageRetunrsOnlyTheNextMessageIfThereAreMultiple() {} } http://git-wip-us.apache.org/repos/asf/geode/blob/5139a6c2/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java index 78f7ee0..e28c8cc 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java @@ -25,14 +25,18 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTOR import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; +import java.util.Collections; import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.apache.geode.internal.cache.tier.Acceptor; import org.awaitility.Awaitility; import org.junit.After; import org.junit.Assert; @@ -70,6 +74,9 @@ import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTy import org.apache.geode.test.junit.categories.IntegrationTest; import org.apache.geode.util.test.TestUtil; +import javax.security.auth.callback.*; +import javax.security.sasl.Sasl; + /** * Test that switching on the header byte makes instances of * {@link GenericProtocolServerConnection}. @@ -138,7 +145,6 @@ public class RoundTripCacheConnectionJUnitTest { Awaitility.await().atMost(5, TimeUnit.SECONDS).until(socket::isConnected); outputStream = socket.getOutputStream(); outputStream.write(110); - serializationService = new ProtobufSerializationService(); } @@ -151,6 +157,7 @@ public class RoundTripCacheConnectionJUnitTest { @Test public void testNewProtocolHeaderLeadsToNewProtocolServerConnection() throws Exception { + clientAuthentication(socket, "secretsecret1"); ProtobufProtocolSerializer protobufProtocolSerializer = new ProtobufProtocolSerializer(); ClientProtocol.Message putMessage = MessageUtil.makePutRequestMessage(serializationService, TEST_KEY, TEST_VALUE, TEST_REGION, @@ -165,6 +172,12 @@ public class RoundTripCacheConnectionJUnitTest { } @Test + public void testNewProtocolFailsToAuthenticate() throws Exception { + int response = clientAuthentication(socket, "wrongPassword"); + assertEquals(Acceptor.UNSUCCESSFUL_SERVER_TO_CLIENT, response); + } + + @Test public void testNewProtocolWithMultikeyOperations() throws Exception { System.setProperty("geode.feature-protobuf-protocol", "true"); @@ -319,6 +332,31 @@ public class RoundTripCacheConnectionJUnitTest { assertEquals(Scope.DISTRIBUTED_NO_ACK, Scope.fromString(region.getScope())); } + private int clientAuthentication(Socket socket, String password) throws IOException { + OutputStream outputStream = socket.getOutputStream(); + DataOutputStream dataOutputStream = new DataOutputStream(outputStream); + DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); + + String[] mechanisms = new String[]{"PLAIN"}; + CallbackHandler callbackHandler = new ClientCallbackHandler(password); + javax.security.sasl.SaslClient + saslClient = + Sasl.createSaslClient(mechanisms, "myId", "geode", "localhost", Collections.emptyMap(), + callbackHandler); + int length = dataInputStream.readInt(); + if (length > 1000000) { + throw new IllegalStateException("invalid length read from stream"); + } + byte[] challenge = new byte[length]; + dataInputStream.readFully(challenge); + + + byte[] response = saslClient.evaluateChallenge(challenge); + dataOutputStream.writeInt(response.length); + dataOutputStream.write(response); + return dataInputStream.readByte(); + } + private void validatePutResponse(Socket socket, ProtobufProtocolSerializer protobufProtocolSerializer) throws Exception { ClientProtocol.Message message = @@ -457,5 +495,34 @@ public class RoundTripCacheConnectionJUnitTest { return socketCreator.connectForClient("localhost", cacheServerPort, 5000); } + static class ClientCallbackHandler implements CallbackHandler { + private String password; + + public ClientCallbackHandler(String password) { + this.password = password; + } + + @Override + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + System.out.println("ClientCallbackHandler invoked with " + callbacks.length + " callbacks"); + + for (int i = 0; i < callbacks.length; i++) { + System.out.println("ClientCallbackHandler processing callback " + callbacks[i]); + + if (callbacks[i] instanceof NameCallback) { + NameCallback nc = (NameCallback) callbacks[i]; + nc.setName("user123"); + } else if (callbacks[i] instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) callbacks[i]; + pc.setPassword(this.password.toCharArray()); + } else if (callbacks[i] instanceof TextOutputCallback) { + } else { + throw new UnsupportedCallbackException + (callbacks[i], "Unrecognized Callback"); + } + } + } + } }