use of org.apache.kafka.common.security.kerberos.KerberosError in project kafka by apache.
the class SaslServerAuthenticator method handleSaslToken.
private void handleSaslToken(byte[] clientToken) throws IOException {
if (!enableKafkaSaslAuthenticateHeaders) {
byte[] response = saslServer.evaluateResponse(clientToken);
if (saslServer.isComplete()) {
reauthInfo.calcCompletionTimesAndReturnSessionLifetimeMs();
if (reauthInfo.reauthenticating())
reauthInfo.ensurePrincipalUnchanged(principal());
}
if (response != null) {
netOutBuffer = ByteBufferSend.sizePrefixed(ByteBuffer.wrap(response));
flushNetOutBufferAndUpdateInterestOps();
}
} else {
ByteBuffer requestBuffer = ByteBuffer.wrap(clientToken);
RequestHeader header = RequestHeader.parse(requestBuffer);
ApiKeys apiKey = header.apiKey();
short version = header.apiVersion();
RequestContext requestContext = new RequestContext(header, connectionId, clientAddress(), KafkaPrincipal.ANONYMOUS, listenerName, securityProtocol, ClientInformation.EMPTY, false);
RequestAndSize requestAndSize = requestContext.parseRequest(requestBuffer);
if (apiKey != ApiKeys.SASL_AUTHENTICATE) {
IllegalSaslStateException e = new IllegalSaslStateException("Unexpected Kafka request of type " + apiKey + " during SASL authentication.");
buildResponseOnAuthenticateFailure(requestContext, requestAndSize.request.getErrorResponse(e));
throw e;
}
if (!apiKey.isVersionSupported(version)) {
// This should not normally occur since clients typically check supported versions using ApiVersionsRequest
throw new UnsupportedVersionException("Version " + version + " is not supported for apiKey " + apiKey);
}
/*
* The client sends multiple SASL_AUTHENTICATE requests, and the client is known
* to support the required version if any one of them indicates it supports that
* version.
*/
if (!reauthInfo.connectedClientSupportsReauthentication)
reauthInfo.connectedClientSupportsReauthentication = version > 0;
SaslAuthenticateRequest saslAuthenticateRequest = (SaslAuthenticateRequest) requestAndSize.request;
try {
byte[] responseToken = saslServer.evaluateResponse(Utils.copyArray(saslAuthenticateRequest.data().authBytes()));
if (reauthInfo.reauthenticating() && saslServer.isComplete())
reauthInfo.ensurePrincipalUnchanged(principal());
// For versions with SASL_AUTHENTICATE header, send a response to SASL_AUTHENTICATE request even if token is empty.
byte[] responseBytes = responseToken == null ? new byte[0] : responseToken;
long sessionLifetimeMs = !saslServer.isComplete() ? 0L : reauthInfo.calcCompletionTimesAndReturnSessionLifetimeMs();
sendKafkaResponse(requestContext, new SaslAuthenticateResponse(new SaslAuthenticateResponseData().setErrorCode(Errors.NONE.code()).setAuthBytes(responseBytes).setSessionLifetimeMs(sessionLifetimeMs)));
} catch (SaslAuthenticationException e) {
buildResponseOnAuthenticateFailure(requestContext, new SaslAuthenticateResponse(new SaslAuthenticateResponseData().setErrorCode(Errors.SASL_AUTHENTICATION_FAILED.code()).setErrorMessage(e.getMessage())));
throw e;
} catch (SaslException e) {
KerberosError kerberosError = KerberosError.fromException(e);
if (kerberosError != null && kerberosError.retriable()) {
// Handle retriable Kerberos exceptions as I/O exceptions rather than authentication exceptions
throw e;
} else {
// DO NOT include error message from the `SaslException` in the client response since it may
// contain sensitive data like the existence of the user.
String errorMessage = "Authentication failed during " + reauthInfo.authenticationOrReauthenticationText() + " due to invalid credentials with SASL mechanism " + saslMechanism;
buildResponseOnAuthenticateFailure(requestContext, new SaslAuthenticateResponse(new SaslAuthenticateResponseData().setErrorCode(Errors.SASL_AUTHENTICATION_FAILED.code()).setErrorMessage(errorMessage)));
throw new SaslAuthenticationException(errorMessage, e);
}
}
}
}
Aggregations