public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer)
      throws SQLException {
    toServer.clear();

    if (this.password == null || this.password.length() == 0 || fromServer == null) {
      // no password or changeUser()
      Buffer bresp = new Buffer(new byte[] {0});
      toServer.add(bresp);

    } else if (((MySQLConnection) connection).getIO().isSSLEstablished()) {
      // allow plain text over SSL
      Buffer bresp = new Buffer(StringUtils.getBytes(this.password));
      bresp.setPosition(bresp.getBufLength());
      int oldBufLength = bresp.getBufLength();
      bresp.writeByte((byte) 0);
      bresp.setBufLength(oldBufLength + 1);
      bresp.setPosition(0);
      toServer.add(bresp);

    } else if (this.connection.getServerRSAPublicKeyFile() != null) {
      // encrypt with given key, don't use "Public Key Retrieval"
      this.seed = fromServer.readString();
      Buffer bresp =
          new Buffer(
              encryptPassword(this.password, this.seed, this.connection, this.publicKeyString));
      toServer.add(bresp);

    } else {
      if (!this.connection.getAllowPublicKeyRetrieval()) {
        throw SQLError.createSQLException(
            Messages.getString("Sha256PasswordPlugin.2"),
            SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE,
            connection.getExceptionInterceptor());
      }

      // We must request the public key from the server to encrypt the password
      if (this.publicKeyRequested) {
        // read key response
        Buffer bresp =
            new Buffer(
                encryptPassword(
                    this.password, this.seed, this.connection, fromServer.readString()));
        toServer.add(bresp);
        this.publicKeyRequested = false;
      } else {
        // build and send Public Key Retrieval packet
        this.seed = fromServer.readString();
        Buffer bresp = new Buffer(new byte[] {1});
        toServer.add(bresp);
        this.publicKeyRequested = true;
      }
    }
    return true;
  }