Skip to content

Commit bd79c40

Browse files
HBASE-24579: Failed SASL authentication does not result in an exception on client side (#1921)
Signed-off-by: Wellington Chevreuil <wchevreuil@apache.org> Signed-off-by: Viraj Jasani <vjasani@apache.org>
1 parent f73480f commit bd79c40

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ public boolean saslConnect(InputStream inS, OutputStream outS) throws IOExceptio
148148
inStream.readFully(saslToken);
149149
}
150150
}
151+
152+
try {
153+
readStatus(inStream);
154+
}
155+
catch (IOException e){
156+
if(e instanceof RemoteException){
157+
LOG.debug("Sasl connection failed: ", e);
158+
throw e;
159+
}
160+
}
151161
if (LOG.isDebugEnabled()) {
152162
LOG.debug("SASL client context established. Negotiated QoP: "
153163
+ saslClient.getNegotiatedProperty(Sasl.QOP));

hbase-client/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@
5252
import org.apache.hadoop.hbase.util.Bytes;
5353
import org.apache.hadoop.io.DataInputBuffer;
5454
import org.apache.hadoop.io.DataOutputBuffer;
55+
import org.apache.hadoop.io.WritableUtils;
5556
import org.apache.hadoop.security.token.Token;
5657
import org.apache.hadoop.security.token.TokenIdentifier;
5758
import org.apache.log4j.Level;
5859
import org.apache.log4j.Logger;
60+
import org.junit.Assert;
5961
import org.junit.BeforeClass;
6062
import org.junit.ClassRule;
6163
import org.junit.Rule;
@@ -318,4 +320,33 @@ private HBaseSaslRpcClient createSaslRpcClientSimple(String principal, String pa
318320
private Token<? extends TokenIdentifier> createTokenMock() {
319321
return mock(Token.class);
320322
}
323+
324+
@Test(expected = IOException.class)
325+
public void testFailedEvaluateResponse() throws IOException {
326+
//prep mockin the SaslClient
327+
SimpleSaslClientAuthenticationProvider mockProvider =
328+
Mockito.mock(SimpleSaslClientAuthenticationProvider.class);
329+
SaslClient mockClient = Mockito.mock(SaslClient.class);
330+
Assert.assertNotNull(mockProvider);
331+
Assert.assertNotNull(mockClient);
332+
Mockito.when(mockProvider.createClient(Mockito.any(), Mockito.any(), Mockito.any(),
333+
Mockito.any(), Mockito.anyBoolean(), Mockito.any())).thenReturn(mockClient);
334+
HBaseSaslRpcClient rpcClient = new HBaseSaslRpcClient(HBaseConfiguration.create(),
335+
mockProvider, createTokenMock(),
336+
Mockito.mock(InetAddress.class), Mockito.mock(SecurityInfo.class), false);
337+
338+
//simulate getting an error from a failed saslServer.evaluateResponse
339+
DataOutputBuffer errorBuffer = new DataOutputBuffer();
340+
errorBuffer.writeInt(SaslStatus.ERROR.state);
341+
WritableUtils.writeString(errorBuffer, IOException.class.getName());
342+
WritableUtils.writeString(errorBuffer, "Invalid Token");
343+
344+
DataInputBuffer in = new DataInputBuffer();
345+
in.reset(errorBuffer.getData(), 0, errorBuffer.getLength());
346+
DataOutputBuffer out = new DataOutputBuffer();
347+
348+
//simulate that authentication exchange has completed quickly after sending the token
349+
Mockito.when(mockClient.isComplete()).thenReturn(true);
350+
rpcClient.saslConnect(in, out);
351+
}
321352
}

0 commit comments

Comments
 (0)