use of org.apache.drill.exec.rpc.user.security.UserAuthenticationException in project drill by apache.
the class UserServer method getHandshakeHandler.
@Override
protected ServerHandshakeHandler<UserToBitHandshake> getHandshakeHandler(final BitToUserConnection connection) {
return new ServerHandshakeHandler<UserToBitHandshake>(RpcType.HANDSHAKE, UserToBitHandshake.PARSER) {
@Override
protected void consumeHandshake(ChannelHandlerContext ctx, UserToBitHandshake inbound) throws Exception {
BitToUserHandshake handshakeResp = getHandshakeResponse(inbound);
OutboundRpcMessage msg = new OutboundRpcMessage(RpcMode.RESPONSE, this.handshakeType, coordinationId, handshakeResp);
ctx.writeAndFlush(msg);
if (handshakeResp.getStatus() != HandshakeStatus.SUCCESS && handshakeResp.getStatus() != HandshakeStatus.AUTH_REQUIRED) {
// If handling handshake results in an error, throw an exception to terminate the connection.
throw new RpcException("Handshake request failed: " + handshakeResp.getErrorMessage());
}
}
@Override
public BitToUserHandshake getHandshakeResponse(UserToBitHandshake inbound) throws Exception {
logger.trace("Handling handshake from user to bit. {}", inbound);
// if timeout is unsupported or is set to false, disable timeout.
if (!inbound.hasSupportTimeout() || !inbound.getSupportTimeout()) {
connection.disableReadTimeout();
logger.warn("Timeout Disabled as client doesn't support it.", connection.getName());
}
BitToUserHandshake.Builder respBuilder = BitToUserHandshake.newBuilder().setRpcVersion(UserRpcConfig.RPC_VERSION).setServerInfos(UserRpcUtils.getRpcEndpointInfos(SERVER_NAME)).addAllSupportedMethods(UserRpcConfig.SUPPORTED_SERVER_METHODS);
try {
if (inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
final String errMsg = String.format("Invalid rpc version. Expected %d, actual %d.", UserRpcConfig.RPC_VERSION, inbound.getRpcVersion());
return handleFailure(respBuilder, HandshakeStatus.RPC_VERSION_MISMATCH, errMsg, null);
}
connection.setHandshake(inbound);
if (!config.isAuthEnabled()) {
connection.finalizeSession(inbound.getCredentials().getUserName());
respBuilder.setStatus(HandshakeStatus.SUCCESS);
return respBuilder.build();
}
final boolean clientSupportsSasl = inbound.hasSaslSupport() && (inbound.getSaslSupport().ordinal() > SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal());
final int saslSupportOrdinal = (clientSupportsSasl) ? inbound.getSaslSupport().ordinal() : SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal();
if (saslSupportOrdinal <= SaslSupport.SASL_AUTH.ordinal() && config.isEncryptionEnabled()) {
throw new UserAuthenticationException("The server doesn't allow client without encryption support." + " Please upgrade your client or talk to your system administrator.");
}
if (!clientSupportsSasl) {
// for backward compatibility < 1.10
final String userName = inbound.getCredentials().getUserName();
if (logger.isTraceEnabled()) {
logger.trace("User {} on connection {} is likely using an older client.", userName, connection.getRemoteAddress());
}
try {
String password = "";
final UserProperties props = inbound.getProperties();
for (int i = 0; i < props.getPropertiesCount(); i++) {
Property prop = props.getProperties(i);
if (DrillProperties.PASSWORD.equalsIgnoreCase(prop.getKey())) {
password = prop.getValue();
break;
}
}
final PlainFactory plainFactory;
try {
plainFactory = (PlainFactory) config.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
} catch (final SaslException e) {
throw new UserAuthenticationException("The server no longer supports username/password" + " based authentication. Please talk to your system administrator.");
}
plainFactory.getAuthenticator().authenticate(userName, password);
connection.changeHandlerTo(config.getMessageHandler());
connection.finalizeSession(userName);
respBuilder.setStatus(HandshakeStatus.SUCCESS);
if (logger.isTraceEnabled()) {
logger.trace("Authenticated {} successfully using PLAIN from {}", userName, connection.getRemoteAddress());
}
return respBuilder.build();
} catch (UserAuthenticationException ex) {
return handleFailure(respBuilder, HandshakeStatus.AUTH_FAILED, ex.getMessage(), ex);
}
}
// Offer all the configured mechanisms to client. If certain mechanism doesn't support encryption
// like PLAIN, those should fail during the SASL handshake negotiation.
respBuilder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
// set the encrypted flag in handshake message. For older clients this field is optional so will be ignored
respBuilder.setEncrypted(connection.isEncryptionEnabled());
respBuilder.setMaxWrappedSize(connection.getMaxWrappedSize());
// for now, this means PLAIN credentials will be sent over twice
// (during handshake and during sasl exchange)
respBuilder.setStatus(HandshakeStatus.AUTH_REQUIRED);
return respBuilder.build();
} catch (Exception e) {
return handleFailure(respBuilder, HandshakeStatus.UNKNOWN_FAILURE, e.getMessage(), e);
}
}
};
}
use of org.apache.drill.exec.rpc.user.security.UserAuthenticationException in project drill by apache.
the class PlainServer method evaluateResponse.
@Override
public byte[] evaluateResponse(byte[] response) throws SaslException {
if (completed) {
throw new IllegalStateException("PLAIN authentication already completed");
}
if (response == null) {
throw new SaslException("Received null response");
}
final String payload = new String(response, StandardCharsets.UTF_8);
// Separator defined in PlainClient is 0
// three parts: [ authorizationID, authenticationID, password ]
final String[] parts = payload.split(UTF_8_NULL, 3);
if (parts.length != 3) {
throw new SaslException("Received corrupt response. Expected 3 parts, but received " + parts.length);
}
String authorizationID = parts[0];
final String authenticationID = parts[1];
final String password = parts[2];
if (authorizationID.isEmpty()) {
authorizationID = authenticationID;
}
try {
authenticator.authenticate(authenticationID, password);
} catch (final UserAuthenticationException e) {
throw new SaslException(e.getMessage());
}
if (!authorizationID.equals(authenticationID)) {
throw new SaslException("Drill expects authorization ID and authentication ID to match. " + "Use inbound impersonation feature so one entity can act on behalf of another.");
}
this.authorizationID = authorizationID;
completed = true;
return null;
}
use of org.apache.drill.exec.rpc.user.security.UserAuthenticationException in project drill by apache.
the class DrillRestLoginService method login.
@Override
public UserIdentity login(String username, Object credentials) {
if (!(credentials instanceof String)) {
return null;
}
try {
// Authenticate WebUser locally using UserAuthenticator. If WebServer is started that guarantees the PLAIN
// mechanism is configured and authenticator is also available
final AuthenticatorFactory plainFactory = drillbitContext.getAuthProvider().getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
final UserAuthenticator userAuthenticator = ((PlainFactory) plainFactory).getAuthenticator();
// Authenticate the user with configured Authenticator
userAuthenticator.authenticate(username, credentials.toString());
logger.debug("WebUser {} is successfully authenticated", username);
final SystemOptionManager sysOptions = drillbitContext.getOptionManager();
final boolean isAdmin = ImpersonationUtil.hasAdminPrivileges(username, sysOptions.getOption(ExecConstants.ADMIN_USERS_KEY).string_val, sysOptions.getOption(ExecConstants.ADMIN_USER_GROUPS_KEY).string_val);
// Create the UserPrincipal corresponding to logged in user.
final Principal userPrincipal = new DrillUserPrincipal(username, isAdmin);
final Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
subject.getPrivateCredentials().add(credentials);
if (isAdmin) {
subject.getPrincipals().addAll(DrillUserPrincipal.ADMIN_PRINCIPALS);
return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.ADMIN_USER_ROLES);
} else {
subject.getPrincipals().addAll(DrillUserPrincipal.NON_ADMIN_PRINCIPALS);
return identityService.newUserIdentity(subject, userPrincipal, DrillUserPrincipal.NON_ADMIN_USER_ROLES);
}
} catch (final Exception e) {
if (e instanceof UserAuthenticationException) {
logger.debug("Authentication failed for WebUser '{}'", username, e);
} else {
logger.error("UnExpected failure occurred for WebUser {} during login.", username, e);
}
return null;
}
}
Aggregations