public boolean saslConnect(InputStream inS, OutputStream outS) throws IOException {
    DataInputStream inStream = new DataInputStream(new BufferedInputStream(inS));
    DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(outS));

    try {
      byte[] saslToken = getInitialResponse();
      if (saslToken != null) {
        outStream.writeInt(saslToken.length);
        outStream.write(saslToken, 0, saslToken.length);
        outStream.flush();
        if (LOG.isDebugEnabled()) {
          LOG.debug("Have sent token of size " + saslToken.length + " from initSASLContext.");
        }
      }
      if (!isComplete()) {
        readStatus(inStream);
        int len = inStream.readInt();
        if (len == SaslUtil.SWITCH_TO_SIMPLE_AUTH) {
          if (!fallbackAllowed) {
            throw new FallbackDisallowedException();
          }
          LOG.debug("Server asks us to fall back to simple auth.");
          dispose();
          return false;
        }
        saslToken = new byte[len];
        if (LOG.isDebugEnabled()) {
          LOG.debug("Will read input token of size " + saslToken.length
            + " for processing by initSASLContext");
        }
        inStream.readFully(saslToken);
      }

      while (!isComplete()) {
        saslToken = evaluateChallenge(saslToken);
        if (saslToken != null) {
          if (LOG.isDebugEnabled()) {
            LOG.debug("Will send token of size " + saslToken.length + " from initSASLContext.");
          }
          outStream.writeInt(saslToken.length);
          outStream.write(saslToken, 0, saslToken.length);
          outStream.flush();
        }
        if (!isComplete()) {
          readStatus(inStream);
          saslToken = new byte[inStream.readInt()];
          if (LOG.isDebugEnabled()) {
            LOG.debug("Will read input token of size " + saslToken.length
              + " for processing by initSASLContext");
          }
          inStream.readFully(saslToken);
        }
      }

      if (LOG.isDebugEnabled()) {
        LOG.debug("SASL client context established. Negotiated QoP: "
          + saslClient.getNegotiatedProperty(Sasl.QOP));
      }

      verifyNegotiatedQop();

      // initial the inputStream, outputStream for both Sasl encryption
      // and Crypto AES encryption if necessary
      // if Crypto AES encryption enabled, the saslInputStream/saslOutputStream is
      // only responsible for connection header negotiation,
      // cryptoInputStream/cryptoOutputStream is responsible for rpc encryption with Crypto AES
      saslInputStream = new SaslInputStream(inS, saslClient);
      saslOutputStream = new SaslOutputStream(outS, saslClient);
      if (initStreamForCrypto) {
        cryptoInputStream = new WrappedInputStream(inS);
        cryptoOutputStream = new WrappedOutputStream(outS);
      }

      return true;
    } catch (IOException e) {
      try {
        saslClient.dispose();
      } catch (SaslException ignored) {
        // ignore further exceptions during cleanup
      }
      throw e;
    }
  }
Do client side SASL authentication with server via the given InputStream and OutputStream
@param inS  InputStream to use
@param outS OutputStream to use
@return true if connection is set up, or false if needs to switch to simple Auth.
hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java