This is an automated email from the ASF dual-hosted git repository.

tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git


The following commit(s) were added to refs/heads/main by this push:
     new 6b407996 PROTON-2781 Cleanups in the SASL layer API docs and some code 
tidying
6b407996 is described below

commit 6b40799641eba9506f66df61fcbdca26ca2408f5
Author: Timothy Bish <[email protected]>
AuthorDate: Fri Dec 8 16:48:42 2023 -0500

    PROTON-2781 Cleanups in the SASL layer API docs and some code tidying
    
    Add some details in API docs and improve some error messages and code.
---
 .../org/apache/qpid/protonj2/engine/Engine.java    |  3 +-
 .../qpid/protonj2/engine/EngineSaslDriver.java     | 13 +++++---
 .../qpid/protonj2/engine/sasl/SaslContext.java     |  5 +++
 .../protonj2/engine/sasl/SaslSystemException.java  | 13 ++++----
 .../sasl/client/AbstractScramSHAMechanism.java     |  9 +++---
 .../sasl/client/SaslCredentialsProvider.java       |  4 +++
 .../engine/sasl/client/SaslMechanisms.java         |  2 +-
 .../client/AbstractScramSHAMechanismTestBase.java  | 37 ++++------------------
 8 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/Engine.java 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/Engine.java
index 88a44279..f4bda43c 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/Engine.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/Engine.java
@@ -232,7 +232,8 @@ public interface Engine extends Consumer<ProtonBuffer> {
      * default no-op driver must be returned that indicates this.  The SASL 
driver provides
      * the engine with client and server side SASL handshaking support.  An 
{@link Engine}
      * implementation can support pluggable SASL drivers or exert tight 
control over the
-     * driver as it sees fit.
+     * driver as it sees fit. The engine implementation in use will dictate 
how a SASL
+     * driver is assigned or discovered.
      *
      * @return the SASL driver for the engine.
      */
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/EngineSaslDriver.java 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/EngineSaslDriver.java
index 57737b83..b0011c94 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/EngineSaslDriver.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/EngineSaslDriver.java
@@ -30,10 +30,10 @@ import 
org.apache.qpid.protonj2.engine.sasl.SaslServerContext;
  */
 public interface EngineSaslDriver {
 
-       /**
-        * The SASL driver state used to determine at what point the current 
SASL negotiation process
-        * is currently in.  If the state is 'none' then no SASL negotiations 
will be performed.
-        */
+    /**
+     * The SASL driver state used to determine at what point the current SASL 
negotiation process
+     * is currently in.  If the state is 'none' then no SASL negotiations will 
be performed.
+     */
     public enum SaslState {
 
         /**
@@ -116,6 +116,11 @@ public interface EngineSaslDriver {
 
     /**
      * Set the maximum frame size the remote can send before an error is 
indicated.
+     * <p>
+     * The AMQP specification defines a default of 512 bytes for this value 
however in
+     * some cases this value is to small for the data needed in some SASL 
mechanisms.
+     * This allows the user to configure a larger acceptable value, the lowest 
possible
+     * value remains the default 512 bytes.
      *
      * @param maxFrameSize
      *      The maximum allowed frame size from the remote sender.
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslContext.java 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslContext.java
index 347d9f2e..ec0a47bc 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslContext.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslContext.java
@@ -76,6 +76,11 @@ public interface SaslContext {
     Role getRole();
 
     /**
+     * Returns if the SASL context has been marked as completed. A completed 
context
+     * does not imply the SASL authentication was successful, the caller 
should check
+     * the state of the {@link #getSaslOutcome()} value to determine if the 
SASL
+     * authentication process was successful or not.
+     *
      * @return true if SASL authentication has completed
      */
     boolean isDone();
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslSystemException.java
 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslSystemException.java
index df747a75..29d4aa31 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslSystemException.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/SaslSystemException.java
@@ -27,15 +27,14 @@ import javax.security.sasl.SaslException;
 public class SaslSystemException extends SaslException {
 
     private static final long serialVersionUID = 1L;
+
     private final boolean permanent;
 
     /**
      * Creates an exception indicating a system error.
      *
      * @param permanent
-     *        {@code true} if the error is permanent and requires (manual)
-     *        intervention.
-     *
+     *                 <code>true</code> if the error is permanent and 
requires (manual) intervention
      */
     public SaslSystemException(boolean permanent) {
         this(permanent, null);
@@ -55,10 +54,12 @@ public class SaslSystemException extends SaslException {
     }
 
     /**
-     * Checks if the condition that caused this exception is of a permanent
-     * nature.
+     * Checks if the condition that caused this exception is of a permanent 
nature.
+     * <p>
+     * A permanent error should be treated as terminal for transports that 
implement
+     * reconnection logic and the implementation should stop attempting 
connections.
      *
-     * @return {@code true} if the error condition is permanent.
+     * @return <code>true</code> if the error condition is permanent.
      */
     public final boolean isPermanent() {
         return permanent;
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanism.java
 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanism.java
index 022bd63b..61cc7777 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanism.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanism.java
@@ -20,7 +20,6 @@ import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
 import java.util.Base64;
 
 import javax.crypto.Mac;
@@ -112,7 +111,7 @@ abstract class AbstractScramSHAMechanism extends 
AbstractMechanism {
 
         if (state != State.COMPLETE) {
             throw new SaslException(String.format(
-                "SASL exchange was not fully completed.  Expected state %s but 
actual state %s", State.COMPLETE, state));
+                "SASL exchange was not fully completed. Expected state %s but 
actual state %s", State.COMPLETE, state));
         }
     }
 
@@ -186,13 +185,13 @@ abstract class AbstractScramSHAMechanism extends 
AbstractMechanism {
         String[] parts = serverFinalMessage.split(",");
 
         if (!parts[0].startsWith("v=")) {
-            throw new SaslException("Server final message did not contain 
verifier");
+            throw new SaslException("Server final message did not contain 
expected verifier");
         }
 
         byte[] serverSignature = 
Base64.getDecoder().decode(parts[0].substring(2));
 
-        if (!Arrays.equals(this.serverSignature, serverSignature)) {
-            throw new SaslException("Server signature did not match");
+        if (!MessageDigest.isEqual(this.serverSignature, serverSignature)) {
+            throw new SaslException("Server signature did not match expected 
signature.");
         }
     }
 
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslCredentialsProvider.java
 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslCredentialsProvider.java
index ab9ce8aa..c3701c08 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslCredentialsProvider.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslCredentialsProvider.java
@@ -42,6 +42,10 @@ public interface SaslCredentialsProvider {
     String password();
 
     /**
+     * Returns the local principal for use in SASL authentication which is 
generally
+     * provided by the IO layer (TLS). This method can return null if there is 
no
+     * local {@link Principal} in use.
+     *
      * @return the local principal value to use when performing SASL 
authentication.
      */
     Principal localPrincipal();
diff --git 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslMechanisms.java
 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslMechanisms.java
index 97dce38e..debc3270 100644
--- 
a/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslMechanisms.java
+++ 
b/protonj2/src/main/java/org/apache/qpid/protonj2/engine/sasl/client/SaslMechanisms.java
@@ -155,7 +155,7 @@ public enum SaslMechanisms {
             }
         }
 
-        throw new IllegalArgumentException("No Matching SASL Mechanism with 
name: " + mechanism.toString());
+        throw new IllegalArgumentException("No Matching SASL Mechanism with 
name: " + mechanism);
     }
 
     /**
diff --git 
a/protonj2/src/test/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanismTestBase.java
 
b/protonj2/src/test/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanismTestBase.java
index 32b1f833..0af9b2be 100644
--- 
a/protonj2/src/test/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanismTestBase.java
+++ 
b/protonj2/src/test/java/org/apache/qpid/protonj2/engine/sasl/client/AbstractScramSHAMechanismTestBase.java
@@ -17,7 +17,7 @@
 package org.apache.qpid.protonj2.engine.sasl.client;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import javax.security.sasl.SaslException;
 
@@ -75,12 +75,7 @@ public abstract class AbstractScramSHAMechanismTestBase 
extends MechanismTestBas
         ProtonBuffer challenge = 
ProtonBufferAllocator.defaultAllocator().copy("badserverfirst".getBytes());
         challenge.setWriteOffset(challenge.capacity());
 
-        try {
-            mechanism.getChallengeResponse(getTestCredentials(), challenge);
-            fail("Exception not thrown");
-        } catch (SaslException s) {
-            // PASS
-        }
+        assertThrows(SaslException.class, () -> 
mechanism.getChallengeResponse(getTestCredentials(), challenge));
     }
 
     /**
@@ -101,12 +96,7 @@ public abstract class AbstractScramSHAMechanismTestBase 
extends MechanismTestBas
         ProtonBuffer challenge = 
ProtonBufferAllocator.defaultAllocator().copy("m=notsupported,s=,i=".getBytes());
         challenge.setWriteOffset(challenge.capacity());
 
-        try {
-            mechanism.getChallengeResponse(getTestCredentials(), challenge);
-            fail("Exception not thrown");
-        } catch (SaslException s) {
-            // PASS
-        }
+        assertThrows(SaslException.class, () -> 
mechanism.getChallengeResponse(getTestCredentials(), challenge));
     }
 
     /**
@@ -127,12 +117,7 @@ public abstract class AbstractScramSHAMechanismTestBase 
extends MechanismTestBas
             "r=invalidnonce,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096".getBytes());
         challenge.setWriteOffset(challenge.capacity());
 
-        try {
-            mechanism.getChallengeResponse(getTestCredentials(), challenge);
-            fail("Exception not thrown");
-        } catch (SaslException s) {
-            // PASS
-        }
+        assertThrows(SaslException.class, () -> 
mechanism.getChallengeResponse(getTestCredentials(), challenge));
     }
 
     /**
@@ -155,12 +140,7 @@ public abstract class AbstractScramSHAMechanismTestBase 
extends MechanismTestBas
         ProtonBuffer challenge = 
ProtonBufferAllocator.defaultAllocator().copy("v=badserverfinal".getBytes());
         challenge.setWriteOffset(challenge.capacity());
 
-        try {
-            mechanism.getChallengeResponse(getTestCredentials(), challenge);
-            fail("Exception not thrown");
-        } catch (SaslException e) {
-            // PASS
-        }
+        assertThrows(SaslException.class, () -> 
mechanism.getChallengeResponse(getTestCredentials(), challenge));
     }
 
     @Test
@@ -173,11 +153,6 @@ public abstract class AbstractScramSHAMechanismTestBase 
extends MechanismTestBas
         ProtonBuffer clientFinalMessage = 
mechanism.getChallengeResponse(getTestCredentials(), serverFirstMessage);
         assertEquals(expectedClientFinalMessage, clientFinalMessage);
 
-        try {
-            mechanism.verifyCompletion();
-            fail("Exception not thrown");
-        } catch (SaslException e) {
-            // PASS
-        }
+        assertThrows(SaslException.class, () -> mechanism.verifyCompletion());
     }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to