kafka-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ij...@apache.org
Subject [kafka] branch trunk updated: MINOR: Improve PlainSaslServer error message for empty tokens (#6249)
Date Tue, 12 Feb 2019 19:58:39 GMT
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 <ismael@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 <rajinisivaram@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);


Mime
View raw message