Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ public void setAuthenticationEndAndSessionReauthenticationTimes(long nowNanos) {
double pctToUse = pctWindowFactorToTakeNetworkLatencyAndClockDriftIntoAccount + RNG.nextDouble()
* pctWindowJitterToAvoidReauthenticationStormAcrossManyChannelsSimultaneously;
sessionLifetimeMsToUse = (long) (positiveSessionLifetimeMs * pctToUse);
clientSessionReauthenticationTimeNanos = authenticationEndNanos + 1000 * 1000 * sessionLifetimeMsToUse;
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arithmetic Overflow Vulnerability

Direct multiplication without overflow checking can cause arithmetic overflow when large session lifetime values are used. This could lead to incorrect re-authentication timing calculations, potentially causing premature session expiration or authentication failures.

Suggested change
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
Standards
  • CWE-190
  • OWASP-A04
  • NIST-SSDF-PW.1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Duplication

The same overflow handling pattern is duplicated in SaslClientAuthenticator and SaslServerAuthenticator. Consider extracting a common helper method that both classes can use for session expiration time calculation to improve maintainability.

Standards
  • Clean-Code-DRY
  • Maintainability-Quality-Duplication
  • Design-Pattern-Extract-Method

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client Authentication Overflow

Client-side session re-authentication time calculation is vulnerable to arithmetic overflow when large session lifetimes are used. This could lead to premature session expiration or authentication failures. The fix properly handles this by using Math.addExact and a new Utils.msToNs method with overflow detection.

Suggested change
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
Standards
  • CWE-190
  • OWASP-A07
  • NIST-SSDF-PW.1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method Extraction Opportunity

The calculation of session expiration time appears in both SaslClientAuthenticator and SaslServerAuthenticator classes with identical logic. This duplication creates maintenance burden where changes must be made in multiple places consistently.

Standards
  • Clean-Code-DRY
  • Refactoring-Extract-Method
  • Maintainability-Quality-Duplication

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time Calculation Overflow

Direct multiplication of milliseconds to nanoseconds can cause arithmetic overflow with large session lifetimes. This could lead to authentication timing vulnerabilities where sessions expire prematurely or never expire due to integer overflow. The fix correctly uses Math.addExact and a new utility method to detect overflow.

Suggested change
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
Standards
  • CWE-190
  • CWE-682
  • OWASP-A06

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Exception Handling

The code calls Utils.msToNs which can throw IllegalArgumentException, but there's no exception handling. If sessionLifetimeMsToUse is very large, the exception will propagate up the call stack potentially causing unexpected behavior in authentication logic.

Standards
  • Algorithm-Correctness-Exception-Handling
  • Logic-Verification-Error-Flow
  • Business-Rule-Robustness

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate Code Pattern

Similar overflow protection code was added to both SaslClientAuthenticator and SaslServerAuthenticator. The pattern of converting milliseconds to nanoseconds with overflow protection appears in multiple places, suggesting an opportunity for a more comprehensive time utility class.

Standards
  • Clean-Code-DRY
  • Design-Pattern-Utility-Class
  • Maintainability-Quality-Reusability

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer Overflow Vulnerability in Session Expiration Calculation

Integer overflow when calculating session expiration time can lead to premature session expiration or authentication bypass. When sessionLifetimeMsToUse is very large, multiplying by 1000*1000 causes overflow, potentially setting expiration to a negative or small value. This could allow attackers to bypass authentication controls.

Suggested change
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
clientSessionReauthenticationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(sessionLifetimeMsToUse));
Standards
  • CWE-190
  • OWASP-A07
  • NIST-SSDF-PW.1

log.debug(
"Finished {} with session expiration in {} ms and session re-authentication on or after {} ms",
authenticationOrReauthenticationText(), positiveSessionLifetimeMs, sessionLifetimeMsToUse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ else if (!maxReauthSet)
else
retvalSessionLifetimeMs = zeroIfNegative(Math.min(credentialExpirationMs - authenticationEndMs, connectionsMaxReauthMs));

sessionExpirationTimeNanos = authenticationEndNanos + 1000 * 1000 * retvalSessionLifetimeMs;
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the change in SaslClientAuthenticator.java, this change uses Math.addExact and Utils.msToNs to prevent potential overflow. This is consistent and correct.

Suggested change
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authentication Timing Overflow

Server-side authentication expiration calculation is vulnerable to arithmetic overflow with large session lifetime values. This could cause incorrect session expiration timing, potentially leading to authentication failures or premature session termination.

Suggested change
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
Standards
  • CWE-190
  • OWASP-A04
  • NIST-SSDF-PW.1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authentication Session Calculation

Direct arithmetic calculation of session expiration time is vulnerable to integer overflow when large values (like Long.MAX_VALUE) are used. This could cause premature session expiration or authentication failures. The fix properly handles this by using Math.addExact and a new Utils.msToNs method with overflow detection.

Suggested change
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
Standards
  • CWE-190
  • OWASP-A07
  • NIST-SSDF-PW.1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server Authentication Overflow

Direct multiplication of milliseconds to nanoseconds can cause arithmetic overflow with large session lifetimes. This could lead to authentication timing vulnerabilities where sessions expire prematurely or never expire due to integer overflow. The fix correctly uses Math.addExact and a new utility method to detect overflow.

Suggested change
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
Standards
  • CWE-190
  • CWE-682
  • OWASP-A06

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Exception Handling

The code calls Utils.msToNs which can throw IllegalArgumentException, but there's no exception handling. If retvalSessionLifetimeMs is very large, the exception will propagate up the call stack potentially causing unexpected behavior in authentication logic.

Standards
  • Algorithm-Correctness-Exception-Handling
  • Logic-Verification-Error-Flow
  • Business-Rule-Robustness

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer Overflow Vulnerability in Session Expiration Calculation

Integer overflow when calculating session expiration time can lead to premature session termination or authentication bypass. When retvalSessionLifetimeMs is very large, multiplying by 1000*1000 causes overflow, potentially setting expiration to a negative or small value. This could allow attackers to bypass authentication controls.

Suggested change
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
sessionExpirationTimeNanos = Math.addExact(authenticationEndNanos, Utils.msToNs(retvalSessionLifetimeMs));
Standards
  • CWE-190
  • OWASP-A07
  • NIST-SSDF-PW.1

}

if (credentialExpirationMs != null) {
Expand Down
13 changes: 13 additions & 0 deletions clients/src/main/java/org/apache/kafka/common/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1697,4 +1697,17 @@ public static ConfigDef mergeConfigs(List<ConfigDef> configDefs) {
public interface ThrowingRunnable {
void run() throws Exception;
}

/**
* convert millisecond to nanosecond, or throw exception if overflow
* @param timeMs the time in millisecond
* @return the converted nanosecond
*/
public static long msToNs(long timeMs) {
try {
return Math.multiplyExact(1000 * 1000, timeMs);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Integer Overflow

The multiplication 1000 * 1000 is performed first before multiplying with timeMs, which could lead to integer overflow for large timeMs values. Reordering to Math.multiplyExact(timeMs, 1000 * 1000) would be safer to catch overflow earlier.

Suggested change
return Math.multiplyExact(1000 * 1000, timeMs);
return Math.multiplyExact(timeMs, 1000L * 1000L);
Standards
  • ISO-IEC-25010-Reliability-Maturity
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • DbC-Precondition

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic Number Usage

The code uses magic numbers (1000 * 1000) for millisecond to nanosecond conversion. Extract these values to named constants to improve code readability and maintainability, making the intent clearer and facilitating future modifications.

Standards
  • Clean-Code-Magic-Numbers
  • Maintainability-Quality-Readability

} catch (ArithmeticException e) {
Comment on lines +1706 to +1709

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defensive Boundary Check

The method relies solely on exception handling to detect overflow. Adding an explicit boundary check (timeMs > Long.MAX_VALUE / (1000 * 1000)) before multiplication would improve performance for edge cases by avoiding exception creation and provide clearer intent about the mathematical constraints.

Standards
  • Algorithm-Correctness-Boundary-Checks
  • Mathematical-Accuracy-Overflow-Prevention

throw new IllegalArgumentException("Cannot convert " + timeMs + " millisecond to nanosecond due to arithmetic overflow", e);
Comment on lines +1707 to +1710

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defensive Boundary Check

Adding a boundary check before the multiplication could prevent the exception entirely for known large values. For values exceeding Long.MAX_VALUE/1_000_000, an early check would be more efficient than throwing and catching exceptions, which have performance overhead.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Time-Behavior
  • Optimization-Pattern-Early-Validation
  • Exception-Handling-Performance-Impact

Comment on lines +1708 to +1710

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Overflow Risk

The multiplication order creates unnecessary intermediate overflow risk. Calculating '1000 * 1000' first creates an intermediate value of 1,000,000 before multiplying by timeMs. Changing to 'Math.multiplyExact(timeMs, 1000L * 1000L)' would prevent potential overflow for smaller timeMs values.

Standards
  • Algorithm-Correctness-Numeric-Overflow
  • Mathematical-Accuracy-Calculation-Order
  • Logic-Verification-Boundary-Conditions

Comment on lines +1708 to +1710

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded Error Message

Error message is hardcoded and not internationalized. For a core utility method, this could make troubleshooting more difficult in non-English environments and violates internationalization best practices.

Standards
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Error-Handling

Comment on lines +1708 to +1710

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error Message Clarity

The multiplication order (1000 * 1000 first, then result * timeMs) could cause intermediate overflow for large timeMs values. Reordering to (timeMs * 1000) * 1000 would provide better overflow protection by handling the largest value first.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Fault-Tolerance
  • Optimization-Pattern-Numeric-Calculation
  • Algorithmic-Complexity-Overflow-Protection

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent Error Message

Error message uses singular 'millisecond' regardless of the timeMs value. For values other than 1, this creates grammatically incorrect error messages. Consistent error messaging improves troubleshooting and system observability.

Standards
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Error-Handling

}
Comment on lines +1706 to +1711

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The msToNs method converts milliseconds to nanoseconds and throws an IllegalArgumentException if an arithmetic overflow occurs. Consider using a more specific exception type, such as ArithmeticException, to provide better context to callers.

Suggested change
public static long msToNs(long timeMs) {
try {
return Math.multiplyExact(1000 * 1000, timeMs);
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Cannot convert " + timeMs + " millisecond to nanosecond due to arithmetic overflow", e);
}
public static long msToNs(long timeMs) {
try {
return Math.multiplyExact(1000 * 1000, timeMs);
} catch (ArithmeticException e) {
throw e; // re-throw the ArithmeticException
}
}

Comment on lines +1710 to +1711

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect Error Message

The error message uses plural 'milliseconds' but singular 'nanosecond'. This inconsistency in plurality creates a grammatical error. The message should use either both singular or both plural forms for consistency.

Standards
  • Logic-Verification-Error-Handling
  • Business-Rule-Message-Consistency

Comment on lines +1707 to +1711

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uncaught Arithmetic Exception

The multiplication 1000 * 1000 is performed before the multiplyExact call, bypassing overflow protection for that operation. This could lead to undetected overflow in the initial calculation before multiplyExact is applied to the result.

Suggested change
try {
return Math.multiplyExact(1000 * 1000, timeMs);
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Cannot convert " + timeMs + " millisecond to nanosecond due to arithmetic overflow", e);
}
try {
return Math.multiplyExact(Math.multiplyExact(1000, 1000), timeMs);
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Cannot convert " + timeMs + " millisecond to nanosecond due to arithmetic overflow", e);
}
Standards
  • ISO-IEC-25010-Reliability-Maturity
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • DbC-Precondition-Validation

}
Comment on lines +1706 to +1712

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Utility Method Naming

The utility method 'msToNs' uses abbreviated naming that reduces readability. While common in some contexts, fully descriptive method names like 'millisecondsToNanoseconds' improve code self-documentation, especially for utility methods that may be used across the codebase.

Standards
  • Clean-Code-Meaningful-Names
  • Maintainability-Quality-Naming
  • Clean-Code-Functions

}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public class SaslAuthenticatorTest {
private static final long CONNECTIONS_MAX_REAUTH_MS_VALUE = 100L;
private static final int BUFFER_SIZE = 4 * 1024;
private static Time time = Time.SYSTEM;
private static boolean needLargeExpiration = false;

private NioEchoServer server;
private Selector selector;
Expand All @@ -178,6 +179,7 @@ public void setup() throws Exception {

@AfterEach
public void teardown() throws Exception {
needLargeExpiration = false;
if (server != null)
this.server.close();
if (selector != null)
Expand Down Expand Up @@ -1607,6 +1609,42 @@ public void testCannotReauthenticateWithDifferentPrincipal() throws Exception {
server.verifyReauthenticationMetrics(0, 1);
}

@Test
public void testReauthenticateWithLargeReauthValue() throws Exception {
// enable it, we'll get a large expiration timestamp token
needLargeExpiration = true;
String node = "0";
SecurityProtocol securityProtocol = SecurityProtocol.SASL_SSL;

configureMechanisms(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM,
List.of(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM));
// set a large re-auth timeout in server side
saslServerConfigs.put(BrokerSecurityConfigs.CONNECTIONS_MAX_REAUTH_MS_CONFIG, Long.MAX_VALUE);
Comment on lines +1615 to +1622

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Connection Loss

Test uses Long.MAX_VALUE for CONNECTIONS_MAX_REAUTH_MS_CONFIG which triggers arithmetic overflow. This causes connection termination as shown in the test's verification logic. In production, similar overflow could cause unexpected connection drops affecting system availability.

Suggested change
needLargeExpiration = true;
String node = "0";
SecurityProtocol securityProtocol = SecurityProtocol.SASL_SSL;
configureMechanisms(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM,
List.of(OAuthBearerLoginModule.OAUTHBEARER_MECHANISM));
// set a large re-auth timeout in server side
saslServerConfigs.put(BrokerSecurityConfigs.CONNECTIONS_MAX_REAUTH_MS_CONFIG, Long.MAX_VALUE);
needLargeExpiration = true;
// Use a large but safe value that won't cause overflow when converted to nanoseconds
long safeMaxReauthMs = Long.MAX_VALUE / (1000 * 1000);
saslServerConfigs.put(BrokerSecurityConfigs.CONNECTIONS_MAX_REAUTH_MS_CONFIG, safeMaxReauthMs);
Standards
  • ISO-IEC-25010-Performance-Efficiency-Reliability
  • Optimization-Pattern-Boundary-Testing
  • Algorithmic-Complexity-Edge-Case-Handling

server = createEchoServer(securityProtocol);

// set to default value for sasl login configs for initialization in ExpiringCredentialRefreshConfig
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_REFRESH_WINDOW_FACTOR, SaslConfigs.DEFAULT_LOGIN_REFRESH_WINDOW_FACTOR);
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_REFRESH_WINDOW_JITTER, SaslConfigs.DEFAULT_LOGIN_REFRESH_WINDOW_JITTER);
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_REFRESH_MIN_PERIOD_SECONDS, SaslConfigs.DEFAULT_LOGIN_REFRESH_MIN_PERIOD_SECONDS);
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_REFRESH_BUFFER_SECONDS, SaslConfigs.DEFAULT_LOGIN_REFRESH_BUFFER_SECONDS);
saslClientConfigs.put(SaslConfigs.SASL_LOGIN_CALLBACK_HANDLER_CLASS, AlternateLoginCallbackHandler.class);

createCustomClientConnection(securityProtocol, OAuthBearerLoginModule.OAUTHBEARER_MECHANISM, node, true);

// channel should be not null before sasl handshake
assertNotNull(selector.channel(node));

TestUtils.waitForCondition(() -> {
selector.poll(1000);
// this channel should be closed due to session timeout calculation overflow
return selector.channel(node) == null;
}, "channel didn't close with large re-authentication value");
Comment on lines +1637 to +1641

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Exception Overhead

The test waits for an exception to occur inside the poll operation, which may cause performance overhead in test execution. Exception-based control flow can introduce latency due to stack trace generation and exception handling machinery.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Time-Behavior
  • Optimization-Pattern-Exception-Handling
  • Performance-Testing-Efficiency

Comment on lines +1637 to +1641

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exception Handling Missing

TestUtils.waitForCondition lacks exception handling for timeout scenarios. If the channel doesn't close as expected, the test will fail with a timeout exception without clear diagnostic information, making troubleshooting difficult.

Suggested change
TestUtils.waitForCondition(() -> {
selector.poll(1000);
// this channel should be closed due to session timeout calculation overflow
return selector.channel(node) == null;
}, "channel didn't close with large re-authentication value");
try {
TestUtils.waitForCondition(() -> {
selector.poll(1000);
// this channel should be closed due to session timeout calculation overflow
return selector.channel(node) == null;
}, "channel didn't close with large re-authentication value");
} catch (InterruptedException e) {
throw new AssertionError("Test interrupted while waiting for channel to close: " + e.getMessage(), e);
}
Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Error-Handling

Comment on lines +1637 to +1641

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Error Handling

The test asserts channel closure but doesn't verify the specific error condition. Without checking logs or exception type, it cannot confirm whether the channel closed due to the expected overflow error or some other unrelated issue.

Standards
  • Algorithm-Correctness-Exception-Handling
  • Logic-Verification-Test-Validation
  • Business-Rule-Error-Verification

Comment on lines +1637 to +1641

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Error Handling

The TestUtils.waitForCondition doesn't handle timeout exceptions. If the condition never satisfies (channel doesn't close), the test will hang indefinitely rather than failing with a clear timeout message.

Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Error-Handling

Comment on lines +1637 to +1641

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete Error Handling

The test expects channel closure on overflow but doesn't verify the specific error. Without validating the exact exception type or error message, the test might pass for wrong reasons. This could mask authentication bypass vulnerabilities if channel closes for unrelated reasons.

Standards
  • CWE-390
  • OWASP-A07
  • NIST-SSDF-PW.8


// ensure metrics are as expected
server.verifyAuthenticationMetrics(0, 0);
server.verifyReauthenticationMetrics(0, 0);
}

@Test
public void testCorrelationId() {
SaslClientAuthenticator authenticator = new SaslClientAuthenticator(
Expand Down Expand Up @@ -1936,7 +1974,7 @@ private void createClientConnection(SecurityProtocol securityProtocol, String sa
if (enableSaslAuthenticateHeader)
createClientConnection(securityProtocol, node);
else
createClientConnectionWithoutSaslAuthenticateHeader(securityProtocol, saslMechanism, node);
createCustomClientConnection(securityProtocol, saslMechanism, node, false);
}

private NioEchoServer startServerApiVersionsUnsupportedByClient(final SecurityProtocol securityProtocol, String saslMechanism) throws Exception {
Expand Down Expand Up @@ -2024,15 +2062,13 @@ protected void enableKafkaSaslAuthenticateHeaders(boolean flag) {
return server;
}

private void createClientConnectionWithoutSaslAuthenticateHeader(final SecurityProtocol securityProtocol,
final String saslMechanism, String node) throws Exception {

final ListenerName listenerName = ListenerName.forSecurityProtocol(securityProtocol);
final Map<String, ?> configs = Collections.emptyMap();
final JaasContext jaasContext = JaasContext.loadClientContext(configs);
final Map<String, JaasContext> jaasContexts = Collections.singletonMap(saslMechanism, jaasContext);

SaslChannelBuilder clientChannelBuilder = new SaslChannelBuilder(ConnectionMode.CLIENT, jaasContexts,
private SaslChannelBuilder saslChannelBuilderWithoutHeader(
final SecurityProtocol securityProtocol,
final String saslMechanism,
final Map<String, JaasContext> jaasContexts,
final ListenerName listenerName
) {
return new SaslChannelBuilder(ConnectionMode.CLIENT, jaasContexts,
securityProtocol, listenerName, false, saslMechanism,
null, null, null, time, new LogContext(), null) {

Expand All @@ -2059,6 +2095,42 @@ protected void setSaslAuthenticateAndHandshakeVersions(ApiVersionsResponse apiVe
};
}
};
}

private void createCustomClientConnection(
final SecurityProtocol securityProtocol,
final String saslMechanism,
String node,
boolean withSaslAuthenticateHeader
) throws Exception {

final ListenerName listenerName = ListenerName.forSecurityProtocol(securityProtocol);
final Map<String, ?> configs = Collections.emptyMap();
final JaasContext jaasContext = JaasContext.loadClientContext(configs);
final Map<String, JaasContext> jaasContexts = Collections.singletonMap(saslMechanism, jaasContext);

SaslChannelBuilder clientChannelBuilder;
if (!withSaslAuthenticateHeader) {
clientChannelBuilder = saslChannelBuilderWithoutHeader(securityProtocol, saslMechanism, jaasContexts, listenerName);
} else {
clientChannelBuilder = new SaslChannelBuilder(ConnectionMode.CLIENT, jaasContexts,
securityProtocol, listenerName, false, saslMechanism,
null, null, null, time, new LogContext(), null) {

@Override
protected SaslClientAuthenticator buildClientAuthenticator(Map<String, ?> configs,
AuthenticateCallbackHandler callbackHandler,
String id,
String serverHost,
String servicePrincipal,
TransportLayer transportLayer,
Subject subject) {

return new SaslClientAuthenticator(configs, callbackHandler, id, subject,
servicePrincipal, serverHost, saslMechanism, transportLayer, time, new LogContext());
}
};
}
Comment on lines +2112 to +2133

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract Common Method

The SaslChannelBuilder creation with header could be extracted into a separate method similar to saslChannelBuilderWithoutHeader. This would improve code symmetry, reduce duplication, and make the createCustomClientConnection method more concise and easier to maintain.

Standards
  • Clean-Code-Functions
  • Refactoring-Extract-Method
  • Maintainability-Quality-Symmetry

clientChannelBuilder.configure(saslClientConfigs);
this.selector = NetworkTestUtils.createSelector(clientChannelBuilder, time);
InetSocketAddress addr = new InetSocketAddress("localhost", server.port());
Expand Down Expand Up @@ -2507,10 +2579,11 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
+ ++numInvocations;
String headerJson = "{" + claimOrHeaderJsonText("alg", "none") + "}";
/*
* Use a short lifetime so the background refresh thread replaces it before we
* If we're testing large expiration scenario, use a large lifetime.
* Otherwise, use a short lifetime so the background refresh thread replaces it before we
* re-authenticate
*/
String lifetimeSecondsValueToUse = "1";
String lifetimeSecondsValueToUse = needLargeExpiration ? String.valueOf(Long.MAX_VALUE) : "1";
String claimsJson;
try {
claimsJson = String.format("{%s,%s,%s}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,35 @@ public void testSessionExpiresAtTokenExpiry() throws IOException {
}
}

@Test
public void testSessionWontExpireWithLargeExpirationTime() throws IOException {
String mechanism = OAuthBearerLoginModule.OAUTHBEARER_MECHANISM;
SaslServer saslServer = mock(SaslServer.class);
MockTime time = new MockTime(0, 1, 1000);
// set a Long.MAX_VALUE as the expiration time
Duration largeExpirationTime = Duration.ofMillis(Long.MAX_VALUE);

try (
MockedStatic<?> ignored = mockSaslServer(saslServer, mechanism, time, largeExpirationTime);
MockedStatic<?> ignored2 = mockKafkaPrincipal("[principal-type]", "[principal-name");
TransportLayer transportLayer = mockTransportLayer()
) {

SaslServerAuthenticator authenticator = getSaslServerAuthenticatorForOAuth(mechanism, transportLayer, time, largeExpirationTime.toMillis());

mockRequest(saslHandshakeRequest(mechanism), transportLayer);
authenticator.authenticate();

when(saslServer.isComplete()).thenReturn(false).thenReturn(true);
mockRequest(saslAuthenticateRequest(), transportLayer);

Throwable t = assertThrows(IllegalArgumentException.class, () -> authenticator.authenticate());
assertEquals(ArithmeticException.class, t.getCause().getClass());
assertEquals("Cannot convert " + Long.MAX_VALUE + " millisecond to nanosecond due to arithmetic overflow",
Comment on lines +295 to +296

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent Error Message

The test expects a specific error message that doesn't match the actual implementation in Utils.msToNs(). The test checks for "arithmetic overflow" while the implementation throws "due to arithmetic overflow", which will cause the test to fail.

Standards
  • Logic-Verification-Test-Correctness
  • Algorithm-Correctness-Error-Messaging
  • Business-Rule-Consistency

t.getMessage());
Comment on lines +294 to +297

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Exception Handling

The test verifies exception type and message but doesn't verify the complete exception chain. The test should also verify that the ArithmeticException is properly wrapped inside the IllegalArgumentException to ensure proper exception propagation.

Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Error-Handling

Comment on lines +294 to +297

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve Error Handling

Test verifies exception handling but doesn't check if the connection is properly terminated after overflow. In production, a failed authentication due to overflow should ensure the connection is closed securely. Consider enhancing the test to verify proper connection termination to prevent potential authentication bypass.

Standards
  • CWE-755
  • OWASP-A07
  • NIST-SSDF-PW.8

}
}

private SaslServerAuthenticator getSaslServerAuthenticatorForOAuth(String mechanism, TransportLayer transportLayer, Time time, Long maxReauth) {
Map<String, ?> configs = Collections.singletonMap(BrokerSecurityConfigs.SASL_ENABLED_MECHANISMS_CONFIG,
Collections.singletonList(mechanism));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,13 @@ public void testTryAll() throws Throwable {
assertEquals(expected, recorded);
}

@Test
public void testMsToNs() {
assertEquals(1000000, Utils.msToNs(1));
assertEquals(0, Utils.msToNs(0));
assertThrows(IllegalArgumentException.class, () -> Utils.msToNs(Long.MAX_VALUE));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test case verifies that an IllegalArgumentException is thrown when msToNs is called with Long.MAX_VALUE. Consider adding additional test cases with different large values to ensure robustness.

        assertThrows(IllegalArgumentException.class, () -> Utils.msToNs(Long.MAX_VALUE));
        assertThrows(IllegalArgumentException.class, () -> Utils.msToNs(Long.MAX_VALUE - 1));
        assertThrows(IllegalArgumentException.class, () -> Utils.msToNs(Long.MAX_VALUE / 2));

Comment on lines +1114 to +1116

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent Test Values

The test verifies positive and zero cases but lacks testing for negative values. Since the msToNs method doesn't explicitly prohibit negative values, the test should verify correct handling of negative millisecond inputs to ensure complete logical coverage.

Standards
  • Logic-Verification-Test-Coverage
  • Algorithm-Correctness-Edge-Cases

Comment on lines +1114 to +1116

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boundary Value Testing

Test only checks extreme values (0, 1, Long.MAX_VALUE) but misses important boundary cases. Adding tests for values near overflow threshold (Long.MAX_VALUE/1_000_000) would better verify the reliability of the msToNs method under edge conditions.

Standards
  • ISO-IEC-25010-Reliability-Maturity
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • SRE-Testing-Reliability

Comment on lines +1115 to +1116

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage Enhancement

Test coverage for msToNs() only verifies extreme values (0 and Long.MAX_VALUE). Adding tests for boundary values (e.g., Long.MAX_VALUE/1000000) would ensure robust overflow detection across the full range of potential inputs.

Standards
  • ISO-IEC-25010-Performance-Efficiency-Reliability
  • Test-Coverage-Optimization
  • Boundary-Value-Testing

}

private Callable<Void> recordingCallable(Map<String, Object> recordingMap, String success, TestException failure) {
return () -> {
if (success == null)
Expand Down
Loading