use of org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto.SaslAuth in project hadoop by apache.
the class SaslRpcClient method saslConnect.
/**
* Do client side SASL authentication with server via the given InputStream
* and OutputStream
*
* @param inS
* InputStream to use
* @param outS
* OutputStream to use
* @return AuthMethod used to negotiate the connection
* @throws IOException
*/
public AuthMethod saslConnect(IpcStreams ipcStreams) throws IOException {
// redefined if/when a SASL negotiation starts, can be queried if the
// negotiation fails
authMethod = AuthMethod.SIMPLE;
sendSaslMessage(ipcStreams.out, negotiateRequest);
// loop until sasl is complete or a rpc error occurs
boolean done = false;
do {
ByteBuffer bb = ipcStreams.readResponse();
RpcWritable.Buffer saslPacket = RpcWritable.Buffer.wrap(bb);
RpcResponseHeaderProto header = saslPacket.getValue(RpcResponseHeaderProto.getDefaultInstance());
switch(header.getStatus()) {
// might get a RPC error during
case ERROR:
case FATAL:
throw new RemoteException(header.getExceptionClassName(), header.getErrorMsg());
default:
break;
}
if (header.getCallId() != AuthProtocol.SASL.callId) {
throw new SaslException("Non-SASL response during negotiation");
}
RpcSaslProto saslMessage = saslPacket.getValue(RpcSaslProto.getDefaultInstance());
if (saslPacket.remaining() > 0) {
throw new SaslException("Received malformed response length");
}
// handle sasl negotiation process
RpcSaslProto.Builder response = null;
switch(saslMessage.getState()) {
case NEGOTIATE:
{
// create a compatible SASL client, throws if no supported auths
SaslAuth saslAuthType = selectSaslClient(saslMessage.getAuthsList());
// define auth being attempted, caller can query if connect fails
authMethod = AuthMethod.valueOf(saslAuthType.getMethod());
byte[] responseToken = null;
if (authMethod == AuthMethod.SIMPLE) {
// switching to SIMPLE
// not going to wait for success ack
done = true;
} else {
byte[] challengeToken = null;
if (saslAuthType.hasChallenge()) {
// server provided the first challenge
challengeToken = saslAuthType.getChallenge().toByteArray();
saslAuthType = SaslAuth.newBuilder(saslAuthType).clearChallenge().build();
} else if (saslClient.hasInitialResponse()) {
challengeToken = new byte[0];
}
responseToken = (challengeToken != null) ? saslClient.evaluateChallenge(challengeToken) : new byte[0];
}
response = createSaslReply(SaslState.INITIATE, responseToken);
response.addAuths(saslAuthType);
break;
}
case CHALLENGE:
{
if (saslClient == null) {
// demand a specific negotiation
throw new SaslException("Server sent unsolicited challenge");
}
byte[] responseToken = saslEvaluateToken(saslMessage, false);
response = createSaslReply(SaslState.RESPONSE, responseToken);
break;
}
case SUCCESS:
{
// switch to simple
if (saslClient == null) {
authMethod = AuthMethod.SIMPLE;
} else {
saslEvaluateToken(saslMessage, true);
}
done = true;
break;
}
default:
{
throw new SaslException("RPC client doesn't support SASL " + saslMessage.getState());
}
}
if (response != null) {
sendSaslMessage(ipcStreams.out, response.build());
}
} while (!done);
return authMethod;
}
use of org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto.SaslAuth in project hadoop by apache.
the class SaslRpcClient method selectSaslClient.
/**
* Instantiate a sasl client for the first supported auth type in the
* given list. The auth type must be defined, enabled, and the user
* must possess the required credentials, else the next auth is tried.
*
* @param authTypes to attempt in the given order
* @return SaslAuth of instantiated client
* @throws AccessControlException - client doesn't support any of the auths
* @throws IOException - misc errors
*/
private SaslAuth selectSaslClient(List<SaslAuth> authTypes) throws SaslException, AccessControlException, IOException {
SaslAuth selectedAuthType = null;
boolean switchToSimple = false;
for (SaslAuth authType : authTypes) {
if (!isValidAuthType(authType)) {
// don't know what it is, try next
continue;
}
AuthMethod authMethod = AuthMethod.valueOf(authType.getMethod());
if (authMethod == AuthMethod.SIMPLE) {
switchToSimple = true;
} else {
saslClient = createSaslClient(authType);
if (saslClient == null) {
// client lacks credentials, try next
continue;
}
}
selectedAuthType = authType;
break;
}
if (saslClient == null && !switchToSimple) {
List<String> serverAuthMethods = new ArrayList<String>();
for (SaslAuth authType : authTypes) {
serverAuthMethods.add(authType.getMethod());
}
throw new AccessControlException("Client cannot authenticate via:" + serverAuthMethods);
}
if (LOG.isDebugEnabled() && selectedAuthType != null) {
LOG.debug("Use " + selectedAuthType.getMethod() + " authentication for protocol " + protocol.getSimpleName());
}
return selectedAuthType;
}
Aggregations