Search in sources :

Example 1 with SaslAuth

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;
}
Also used : RpcResponseHeaderProto(org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcResponseHeaderProto) SaslAuth(org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto.SaslAuth) RpcWritable(org.apache.hadoop.ipc.RpcWritable) RemoteException(org.apache.hadoop.ipc.RemoteException) SaslException(javax.security.sasl.SaslException) ByteBuffer(java.nio.ByteBuffer) RpcSaslProto(org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto)

Example 2 with SaslAuth

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;
}
Also used : SaslAuth(org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto.SaslAuth) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString) AuthMethod(org.apache.hadoop.security.SaslRpcServer.AuthMethod)

Aggregations

SaslAuth (org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto.SaslAuth)2 ByteString (com.google.protobuf.ByteString)1 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1 SaslException (javax.security.sasl.SaslException)1 RemoteException (org.apache.hadoop.ipc.RemoteException)1 RpcWritable (org.apache.hadoop.ipc.RpcWritable)1 RpcResponseHeaderProto (org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcResponseHeaderProto)1 RpcSaslProto (org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcSaslProto)1 AuthMethod (org.apache.hadoop.security.SaslRpcServer.AuthMethod)1