You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by ij...@apache.org on 2019/02/12 19:58:39 UTC
[kafka] branch trunk updated: MINOR: Improve PlainSaslServer error
message for empty tokens (#6249)
This is an automated email from the ASF dual-hosted git repository.
ijuma pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new 6373551 MINOR: Improve PlainSaslServer error message for empty tokens (#6249)
6373551 is described below
commit 637355138a426eb678b2cc9348ac07f970f20764
Author: Ismael Juma <is...@juma.me.uk>
AuthorDate: Tue Feb 12 11:58:26 2019 -0800
MINOR: Improve PlainSaslServer error message for empty tokens (#6249)
Empty username or password would result in the "expected 3 tokens"
error instead of "username not specified" or "password not specified".
Reviewers: Rajini Sivaram <ra...@googlemail.com>
---
.../security/plain/internals/PlainSaslServer.java | 46 +++++++++++++++-------
.../plain/internals/PlainSaslServerTest.java | 40 +++++++++++++++++++
2 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/common/security/plain/internals/PlainSaslServer.java b/clients/src/main/java/org/apache/kafka/common/security/plain/internals/PlainSaslServer.java
index 18df038..7a65fe6 100644
--- a/clients/src/main/java/org/apache/kafka/common/security/plain/internals/PlainSaslServer.java
+++ b/clients/src/main/java/org/apache/kafka/common/security/plain/internals/PlainSaslServer.java
@@ -16,8 +16,10 @@
*/
package org.apache.kafka.common.security.plain.internals;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import javax.security.auth.callback.Callback;
@@ -67,7 +69,7 @@ public class PlainSaslServer implements SaslServer {
* </p>
*/
@Override
- public byte[] evaluateResponse(byte[] response) throws SaslException, SaslAuthenticationException {
+ public byte[] evaluateResponse(byte[] responseBytes) throws SaslAuthenticationException {
/*
* Message format (from https://tools.ietf.org/html/rfc4616):
*
@@ -81,23 +83,17 @@ public class PlainSaslServer implements SaslServer {
* ;; any UTF-8 encoded Unicode character except NUL
*/
- String[] tokens;
- try {
- tokens = new String(response, "UTF-8").split("\u0000");
- } catch (UnsupportedEncodingException e) {
- throw new SaslException("UTF-8 encoding not supported", e);
- }
- if (tokens.length != 3)
- throw new SaslException("Invalid SASL/PLAIN response: expected 3 tokens, got " + tokens.length);
- String authorizationIdFromClient = tokens[0];
- String username = tokens[1];
- String password = tokens[2];
+ String response = new String(responseBytes, StandardCharsets.UTF_8);
+ List<String> tokens = extractTokens(response);
+ String authorizationIdFromClient = tokens.get(0);
+ String username = tokens.get(1);
+ String password = tokens.get(2);
if (username.isEmpty()) {
- throw new SaslException("Authentication failed: username not specified");
+ throw new SaslAuthenticationException("Authentication failed: username not specified");
}
if (password.isEmpty()) {
- throw new SaslException("Authentication failed: password not specified");
+ throw new SaslAuthenticationException("Authentication failed: password not specified");
}
NameCallback nameCallback = new NameCallback("username", username);
@@ -118,6 +114,26 @@ public class PlainSaslServer implements SaslServer {
return new byte[0];
}
+ private List<String> extractTokens(String string) {
+ List<String> tokens = new ArrayList<>();
+ int startIndex = 0;
+ for (int i = 0; i < 4; ++i) {
+ int endIndex = string.indexOf("\u0000", startIndex);
+ if (endIndex == -1) {
+ tokens.add(string.substring(startIndex));
+ break;
+ }
+ tokens.add(string.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+
+ if (tokens.size() != 3)
+ throw new SaslAuthenticationException("Invalid SASL/PLAIN response: expected 3 tokens, got " +
+ tokens.size());
+
+ return tokens;
+ }
+
@Override
public String getAuthorizationID() {
if (!complete)
diff --git a/clients/src/test/java/org/apache/kafka/common/security/plain/internals/PlainSaslServerTest.java b/clients/src/test/java/org/apache/kafka/common/security/plain/internals/PlainSaslServerTest.java
index b8c77df..5fb2042 100644
--- a/clients/src/test/java/org/apache/kafka/common/security/plain/internals/PlainSaslServerTest.java
+++ b/clients/src/test/java/org/apache/kafka/common/security/plain/internals/PlainSaslServerTest.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
import org.apache.kafka.common.errors.SaslAuthenticationException;
import org.apache.kafka.common.security.JaasContext;
@@ -69,6 +70,45 @@ public class PlainSaslServerTest {
saslServer.evaluateResponse(saslMessage(USER_B, USER_A, PASSWORD_A));
}
+ @Test
+ public void emptyTokens() {
+ Exception e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("", "", "")));
+ assertEquals("Authentication failed: username not specified", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("", "", "p")));
+ assertEquals("Authentication failed: username not specified", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("", "u", "")));
+ assertEquals("Authentication failed: password not specified", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("a", "", "")));
+ assertEquals("Authentication failed: username not specified", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("a", "", "p")));
+ assertEquals("Authentication failed: username not specified", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(saslMessage("a", "u", "")));
+ assertEquals("Authentication failed: password not specified", e.getMessage());
+
+ String nul = "\u0000";
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(
+ String.format("%s%s%s%s%s%s", "a", nul, "u", nul, "p", nul).getBytes(StandardCharsets.UTF_8)));
+ assertEquals("Invalid SASL/PLAIN response: expected 3 tokens, got 4", e.getMessage());
+
+ e = assertThrows(SaslAuthenticationException.class, () ->
+ saslServer.evaluateResponse(
+ String.format("%s%s%s", "", nul, "u").getBytes(StandardCharsets.UTF_8)));
+ assertEquals("Invalid SASL/PLAIN response: expected 3 tokens, got 2", e.getMessage());
+ }
+
private byte[] saslMessage(String authorizationId, String userName, String password) {
String nul = "\u0000";
String message = String.format("%s%s%s%s%s", authorizationId, nul, userName, nul, password);