示例#1
0
  public static void authenticate(
      PGStream pgStream,
      String host,
      String user,
      String password,
      String jaasApplicationName,
      String kerberosServerName,
      Logger logger)
      throws IOException, SQLException {
    if (logger.logDebug()) logger.debug(" <=BE AuthenticationReqGSS");

    Object result = null;

    if (jaasApplicationName == null) jaasApplicationName = "pgjdbc";
    if (kerberosServerName == null) kerberosServerName = "postgres";

    try {
      LoginContext lc =
          new LoginContext(jaasApplicationName, new GSSCallbackHandler(user, password));
      lc.login();

      Subject sub = lc.getSubject();
      PrivilegedAction action =
          new GssAction(pgStream, host, user, password, kerberosServerName, logger);
      result = Subject.doAs(sub, action);
    } catch (Exception e) {
      throw new PSQLException(GT.tr("GSS Authentication failed"), PSQLState.CONNECTION_FAILURE, e);
    }

    if (result instanceof IOException) throw (IOException) result;
    else if (result instanceof SQLException) throw (SQLException) result;
    else if (result != null)
      throw new PSQLException(
          GT.tr("GSS Authentication failed"), PSQLState.CONNECTION_FAILURE, (Exception) result);
  }
  /**
   * Preconditions: 1. xid is known to the RM or it's in prepared state
   *
   * <p>Implementation deficiency preconditions: 1. xid must be associated with this connection if
   * it's not in prepared state.
   *
   * <p>Postconditions: 1. Transaction is rolled back and disassociated from connection
   */
  public void rollback(Xid xid) throws XAException {
    if (logger.logDebug()) debug("rolling back xid = " + xid);

    // We don't explicitly check precondition 1.

    try {
      if (currentXid != null && xid.equals(currentXid)) {
        state = STATE_IDLE;
        currentXid = null;
        conn.rollback();
        conn.setAutoCommit(localAutoCommitMode);
      } else {
        String s = RecoveredXid.xidToString(xid);

        conn.setAutoCommit(true);
        Statement stmt = conn.createStatement();
        try {
          stmt.executeUpdate("ROLLBACK PREPARED '" + s + "'");
        } finally {
          stmt.close();
        }
      }
    } catch (SQLException ex) {
      throw new PGXAException(
          GT.tr("Error rolling back prepared transaction"), ex, XAException.XAER_RMERR);
    }
  }
  /**
   * Preconditions: 1. Flags is one of TMSUCCESS, TMFAIL, TMSUSPEND 2. xid != null 3. Connection is
   * associated with transaction xid
   *
   * <p>Implementation deficiency preconditions: 1. Flags is not TMSUSPEND
   *
   * <p>Postconditions: 1. connection is disassociated from the transaction.
   */
  public void end(Xid xid, int flags) throws XAException {
    if (logger.logDebug()) debug("ending transaction xid = " + xid);

    // Check preconditions

    if (flags != XAResource.TMSUSPEND
        && flags != XAResource.TMFAIL
        && flags != XAResource.TMSUCCESS)
      throw new PGXAException(GT.tr("Invalid flags"), XAException.XAER_INVAL);

    if (xid == null) throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);

    if (state != STATE_ACTIVE || !currentXid.equals(xid))
      throw new PGXAException(
          GT.tr("tried to call end without corresponding start call"), XAException.XAER_PROTO);

    // Check implementation deficiency preconditions
    if (flags == XAResource.TMSUSPEND)
      throw new PGXAException(GT.tr("suspend/resume not implemented"), XAException.XAER_RMERR);

    // We ignore TMFAIL. It's just a hint to the RM. We could roll back immediately
    // if TMFAIL was given.

    // All clear. We don't have any real work to do.
    state = STATE_ENDED;
  }
  public void commit(Xid xid, boolean onePhase) throws XAException {
    if (logger.logDebug())
      debug("committing xid = " + xid + (onePhase ? " (one phase) " : " (two phase)"));

    if (xid == null) throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);

    if (onePhase) commitOnePhase(xid);
    else commitPrepared(xid);
  }
  private void sendStartupPacket(PGStream pgStream, String[][] params, Logger logger)
      throws IOException {
    if (logger.logDebug()) {
      String details = "";
      for (int i = 0; i < params.length; ++i) {
        if (i != 0) details += ", ";
        details += params[i][0] + "=" + params[i][1];
      }
      logger.debug(" FE=> StartupPacket(" + details + ")");
    }

    /*
     * Precalculate message length and encode params.
     */
    int length = 4 + 4;
    byte[][] encodedParams = new byte[params.length * 2][];
    for (int i = 0; i < params.length; ++i) {
      encodedParams[i * 2] = params[i][0].getBytes("US-ASCII");
      encodedParams[i * 2 + 1] = params[i][1].getBytes("US-ASCII");
      length += encodedParams[i * 2].length + 1 + encodedParams[i * 2 + 1].length + 1;
    }

    length += 1; // Terminating \0

    /*
     * Send the startup message.
     */
    pgStream.SendInteger4(length);
    pgStream.SendInteger2(3); // protocol major
    pgStream.SendInteger2(0); // protocol minor
    for (int i = 0; i < encodedParams.length; ++i) {
      pgStream.Send(encodedParams[i]);
      pgStream.SendChar(0);
    }

    pgStream.SendChar(0);
    pgStream.flush();
  }
  private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger)
      throws IOException, SQLException {
    if (logger.logDebug()) logger.debug(" FE=> SSLRequest");

    // Send SSL request packet
    pgStream.SendInteger4(8);
    pgStream.SendInteger2(1234);
    pgStream.SendInteger2(5679);
    pgStream.flush();

    // Now get the response from the backend, one of N, E, S.
    int beresp = pgStream.ReceiveChar();
    switch (beresp) {
      case 'E':
        if (logger.logDebug()) logger.debug(" <=BE SSLError");

        // Server doesn't even know about the SSL handshake protocol
        if (requireSSL)
          throw new PSQLException(
              GT.tr("The server does not support SSL."), PSQLState.CONNECTION_FAILURE);

        // We have to reconnect to continue.
        pgStream.close();
        return new PGStream(pgStream.getHost(), pgStream.getPort());

      case 'N':
        if (logger.logDebug()) logger.debug(" <=BE SSLRefused");

        // Server does not support ssl
        if (requireSSL)
          throw new PSQLException(
              GT.tr("The server does not support SSL."), PSQLState.CONNECTION_FAILURE);

        return pgStream;

      case 'S':
        if (logger.logDebug()) logger.debug(" <=BE SSLOk");

        // Server supports ssl
        Driver.makeSSL(pgStream, info, logger);
        return pgStream;

      default:
        throw new PSQLException(
            GT.tr("An error occured while setting up the SSL connection."),
            PSQLState.CONNECTION_FAILURE);
    }
  }
  /**
   * Preconditions: 1. flags must be one of TMNOFLAGS, TMRESUME or TMJOIN 2. xid != null 3.
   * connection must not be associated with a transaction 4. the TM hasn't seen the xid before
   *
   * <p>Implementation deficiency preconditions: 1. TMRESUME not supported. 2. if flags is TMJOIN,
   * we must be in ended state, and xid must be the current transaction 3. unless flags is TMJOIN,
   * previous transaction using the connection must be committed or prepared or rolled back
   *
   * <p>Postconditions: 1. Connection is associated with the transaction
   */
  public void start(Xid xid, int flags) throws XAException {
    if (logger.logDebug()) debug("starting transaction xid = " + xid);

    // Check preconditions
    if (flags != XAResource.TMNOFLAGS && flags != XAResource.TMRESUME && flags != XAResource.TMJOIN)
      throw new PGXAException(GT.tr("Invalid flags"), XAException.XAER_INVAL);

    if (xid == null) throw new PGXAException(GT.tr("xid must not be null"), XAException.XAER_INVAL);

    if (state == STATE_ACTIVE)
      throw new PGXAException(
          GT.tr("Connection is busy with another transaction"), XAException.XAER_PROTO);

    // We can't check precondition 4 easily, so we don't. Duplicate xid will be catched in prepare
    // phase.

    // Check implementation deficiency preconditions
    if (flags == TMRESUME)
      throw new PGXAException(GT.tr("suspend/resume not implemented"), XAException.XAER_RMERR);

    // It's ok to join an ended transaction. WebLogic does that.
    if (flags == TMJOIN) {
      if (state != STATE_ENDED)
        throw new PGXAException(
            GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR);

      if (!xid.equals(currentXid))
        throw new PGXAException(
            GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR);
    } else if (state == STATE_ENDED)
      throw new PGXAException(
          GT.tr("Transaction interleaving not implemented"), XAException.XAER_RMERR);

    try {
      localAutoCommitMode = conn.getAutoCommit();
      conn.setAutoCommit(false);
    } catch (SQLException ex) {
      throw new PGXAException(GT.tr("Error disabling autocommit"), ex, XAException.XAER_RMERR);
    }

    // Preconditions are met, Associate connection with the transaction
    state = STATE_ACTIVE;
    currentXid = xid;
  }
  /** ** XAConnection interface *** */
  public Connection getConnection() throws SQLException {
    if (logger.logDebug()) debug("PGXAConnection.getConnection called");

    Connection conn = super.getConnection();

    // When we're outside an XA transaction, autocommit
    // is supposed to be true, per usual JDBC convention.
    // When an XA transaction is in progress, it should be
    // false.
    if (state == STATE_IDLE) conn.setAutoCommit(true);

    /*
     * Wrap the connection in a proxy to forbid application from
     * fiddling with transaction state directly during an XA transaction
     */
    ConnectionHandler handler = new ConnectionHandler(conn);
    return (Connection)
        Proxy.newProxyInstance(
            getClass().getClassLoader(),
            new Class[] {Connection.class, PGConnection.class},
            handler);
  }
  /**
   * Preconditions: 1. xid != null 2. xid is in ended state
   *
   * <p>Implementation deficiency preconditions: 1. xid was associated with this connection
   *
   * <p>Postconditions: 1. Transaction is prepared
   */
  public int prepare(Xid xid) throws XAException {
    if (logger.logDebug()) debug("preparing transaction xid = " + xid);

    // Check preconditions
    if (!currentXid.equals(xid)) {
      throw new PGXAException(
          GT.tr(
              "Not implemented: Prepare must be issued using the same connection that started the transaction"),
          XAException.XAER_RMERR);
    }
    if (state != STATE_ENDED)
      throw new PGXAException(GT.tr("Prepare called before end"), XAException.XAER_INVAL);

    state = STATE_IDLE;
    currentXid = null;

    if (!conn.haveMinimumServerVersion("8.1"))
      throw new PGXAException(
          GT.tr("Server versions prior to 8.1 do not support two-phase commit."),
          XAException.XAER_RMERR);

    try {
      String s = RecoveredXid.xidToString(xid);

      Statement stmt = conn.createStatement();
      try {
        stmt.executeUpdate("PREPARE TRANSACTION '" + s + "'");
      } finally {
        stmt.close();
      }
      conn.setAutoCommit(localAutoCommitMode);

      return XA_OK;
    } catch (SQLException ex) {
      throw new PGXAException(GT.tr("Error preparing transaction"), ex, XAException.XAER_RMERR);
    }
  }
  public ProtocolConnection openConnectionImpl(
      String host, int port, String user, String database, Properties info, Logger logger)
      throws SQLException {
    // Extract interesting values from the info properties:
    //  - the SSL setting
    boolean requireSSL = (info.getProperty("ssl") != null);
    boolean trySSL = requireSSL; // XXX temporary until we revisit the ssl property values

    // NOTE: To simplify this code, it is assumed that if we are
    // using the V3 protocol, then the database is at least 7.4.  That
    // eliminates the need to check database versions and maintain
    // backward-compatible code here.
    //
    // Change by Chris Smith <*****@*****.**>

    if (logger.logDebug())
      logger.debug("Trying to establish a protocol version 3 connection to " + host + ":" + port);

    if (!Driver.sslEnabled()) {
      if (requireSSL)
        throw new PSQLException(
            GT.tr("The driver does not support SSL."), PSQLState.CONNECTION_FAILURE);
      trySSL = false;
    }

    //
    // Establish a connection.
    //

    PGStream newStream = null;
    try {
      newStream = new PGStream(host, port);

      // Construct and send an ssl startup packet if requested.
      if (trySSL) newStream = enableSSL(newStream, requireSSL, info, logger);

      // Construct and send a startup packet.
      String[][] params = {
        {"user", user},
        {"database", database},
        {"client_encoding", "UNICODE"},
        {"DateStyle", "ISO"},
        {"extra_float_digits", "2"}
      };

      sendStartupPacket(newStream, params, logger);

      // Do authentication (until AuthenticationOk).
      doAuthentication(newStream, user, info.getProperty("password"), logger);

      // Do final startup.
      ProtocolConnectionImpl protoConnection =
          new ProtocolConnectionImpl(newStream, user, database, info, logger);
      readStartupMessages(newStream, protoConnection, logger);

      // And we're done.
      return protoConnection;
    } catch (UnsupportedProtocolException upe) {
      // Swallow this and return null so ConnectionFactory tries the next protocol.
      if (logger.logDebug()) logger.debug("Protocol not supported, abandoning connection.");
      try {
        newStream.close();
      } catch (IOException e) {
      }
      return null;
    } catch (ConnectException cex) {
      // Added by Peter Mount <*****@*****.**>
      // ConnectException is thrown when the connection cannot be made.
      // we trap this an return a more meaningful message for the end user
      throw new PSQLException(
          GT.tr(
              "Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections."),
          PSQLState.CONNECTION_REJECTED,
          cex);
    } catch (IOException ioe) {
      if (newStream != null) {
        try {
          newStream.close();
        } catch (IOException e) {
        }
      }
      throw new PSQLException(
          GT.tr("The connection attempt failed."), PSQLState.CONNECTION_UNABLE_TO_CONNECT, ioe);
    } catch (SQLException se) {
      if (newStream != null) {
        try {
          newStream.close();
        } catch (IOException e) {
        }
      }
      throw se;
    }
  }
  private void readStartupMessages(
      PGStream pgStream, ProtocolConnectionImpl protoConnection, Logger logger)
      throws IOException, SQLException {
    while (true) {
      int beresp = pgStream.ReceiveChar();
      switch (beresp) {
        case 'Z':
          // Ready For Query; we're done.
          if (pgStream.ReceiveInteger4() != 5)
            throw new IOException("unexpected length of ReadyForQuery packet");

          char tStatus = (char) pgStream.ReceiveChar();
          if (logger.logDebug()) logger.debug(" <=BE ReadyForQuery(" + tStatus + ")");

          // Update connection state.
          switch (tStatus) {
            case 'I':
              protoConnection.setTransactionState(ProtocolConnection.TRANSACTION_IDLE);
              break;
            case 'T':
              protoConnection.setTransactionState(ProtocolConnection.TRANSACTION_OPEN);
              break;
            case 'E':
              protoConnection.setTransactionState(ProtocolConnection.TRANSACTION_FAILED);
              break;
            default:
              // Huh?
              break;
          }

          return;

        case 'K':
          // BackendKeyData
          int l_msgLen = pgStream.ReceiveInteger4();
          if (l_msgLen != 12)
            throw new PSQLException(
                GT.tr("Protocol error.  Session setup failed."),
                PSQLState.CONNECTION_UNABLE_TO_CONNECT);

          int pid = pgStream.ReceiveInteger4();
          int ckey = pgStream.ReceiveInteger4();

          if (logger.logDebug())
            logger.debug(" <=BE BackendKeyData(pid=" + pid + ",ckey=" + ckey + ")");

          protoConnection.setBackendKeyData(pid, ckey);
          break;

        case 'E':
          // Error
          int l_elen = pgStream.ReceiveInteger4();
          ServerErrorMessage l_errorMsg =
              new ServerErrorMessage(pgStream.ReceiveString(l_elen - 4), logger.getLogLevel());

          if (logger.logDebug()) logger.debug(" <=BE ErrorMessage(" + l_errorMsg + ")");

          throw new PSQLException(l_errorMsg);

        case 'N':
          // Warning
          int l_nlen = pgStream.ReceiveInteger4();
          ServerErrorMessage l_warnMsg =
              new ServerErrorMessage(pgStream.ReceiveString(l_nlen - 4), logger.getLogLevel());

          if (logger.logDebug()) logger.debug(" <=BE NoticeResponse(" + l_warnMsg + ")");

          protoConnection.addWarning(new PSQLWarning(l_warnMsg));
          break;

        case 'S':
          // ParameterStatus
          int l_len = pgStream.ReceiveInteger4();
          String name = pgStream.ReceiveString();
          String value = pgStream.ReceiveString();

          if (logger.logDebug())
            logger.debug(" <=BE ParameterStatus(" + name + " = " + value + ")");

          if (name.equals("server_version")) protoConnection.setServerVersion(value);
          else if (name.equals("client_encoding")) {
            if (!value.equals("UNICODE"))
              throw new PSQLException(
                  GT.tr("Protocol error.  Session setup failed."),
                  PSQLState.CONNECTION_UNABLE_TO_CONNECT);
            pgStream.setEncoding(Encoding.getDatabaseEncoding("UNICODE"));
          } else if (name.equals("standard_conforming_strings")) {
            if (value.equals("on")) protoConnection.setStandardConformingStrings(true);
            else if (value.equals("off")) protoConnection.setStandardConformingStrings(false);
            else
              throw new PSQLException(
                  GT.tr("Protocol error.  Session setup failed."),
                  PSQLState.CONNECTION_UNABLE_TO_CONNECT);
          }

          break;

        default:
          if (logger.logDebug()) logger.debug("invalid message type=" + (char) beresp);
          throw new PSQLException(
              GT.tr("Protocol error.  Session setup failed."),
              PSQLState.CONNECTION_UNABLE_TO_CONNECT);
      }
    }
  }
  private void doAuthentication(PGStream pgStream, String user, String password, Logger logger)
      throws IOException, SQLException {
    // Now get the response from the backend, either an error message
    // or an authentication request

    while (true) {
      int beresp = pgStream.ReceiveChar();

      switch (beresp) {
        case 'E':
          // An error occured, so pass the error message to the
          // user.
          //
          // The most common one to be thrown here is:
          // "User authentication failed"
          //
          int l_elen = pgStream.ReceiveInteger4();
          if (l_elen > 30000) {
            // if the error length is > than 30000 we assume this is really a v2 protocol
            // server, so trigger fallback.
            throw new UnsupportedProtocolException();
          }

          ServerErrorMessage errorMsg =
              new ServerErrorMessage(pgStream.ReceiveString(l_elen - 4), logger.getLogLevel());
          if (logger.logDebug()) logger.debug(" <=BE ErrorMessage(" + errorMsg + ")");
          throw new PSQLException(errorMsg);

        case 'R':
          // Authentication request.
          // Get the message length
          int l_msgLen = pgStream.ReceiveInteger4();

          // Get the type of request
          int areq = pgStream.ReceiveInteger4();

          // Process the request.
          switch (areq) {
            case AUTH_REQ_CRYPT:
              {
                byte[] rst = new byte[2];
                rst[0] = (byte) pgStream.ReceiveChar();
                rst[1] = (byte) pgStream.ReceiveChar();
                String salt = new String(rst, 0, 2, "US-ASCII");

                if (logger.logDebug())
                  logger.debug(" <=BE AuthenticationReqCrypt(salt='" + salt + "')");

                if (password == null)
                  throw new PSQLException(
                      GT.tr(
                          "The server requested password-based authentication, but no password was provided."),
                      PSQLState.CONNECTION_REJECTED);

                String result = UnixCrypt.crypt(salt, password);
                byte[] encodedResult = result.getBytes("US-ASCII");

                if (logger.logDebug()) logger.debug(" FE=> Password(crypt='" + result + "')");

                pgStream.SendChar('p');
                pgStream.SendInteger4(4 + encodedResult.length + 1);
                pgStream.Send(encodedResult);
                pgStream.SendChar(0);
                pgStream.flush();

                break;
              }

            case AUTH_REQ_MD5:
              {
                byte[] md5Salt = pgStream.Receive(4);
                if (logger.logDebug()) {
                  logger.debug(
                      " <=BE AuthenticationReqMD5(salt=" + Utils.toHexString(md5Salt) + ")");
                }

                if (password == null)
                  throw new PSQLException(
                      GT.tr(
                          "The server requested password-based authentication, but no password was provided."),
                      PSQLState.CONNECTION_REJECTED);

                byte[] digest = MD5Digest.encode(user, password, md5Salt);

                if (logger.logDebug()) {
                  logger.debug(" FE=> Password(md5digest=" + new String(digest, "US-ASCII") + ")");
                }

                pgStream.SendChar('p');
                pgStream.SendInteger4(4 + digest.length + 1);
                pgStream.Send(digest);
                pgStream.SendChar(0);
                pgStream.flush();

                break;
              }

            case AUTH_REQ_PASSWORD:
              {
                if (logger.logDebug()) {
                  logger.debug(" <=BE AuthenticationReqPassword");
                  logger.debug(" FE=> Password(password=<not shown>)");
                }

                if (password == null)
                  throw new PSQLException(
                      GT.tr(
                          "The server requested password-based authentication, but no password was provided."),
                      PSQLState.CONNECTION_REJECTED);

                byte[] encodedPassword = password.getBytes("US-ASCII");

                pgStream.SendChar('p');
                pgStream.SendInteger4(4 + encodedPassword.length + 1);
                pgStream.Send(encodedPassword);
                pgStream.SendChar(0);
                pgStream.flush();

                break;
              }

            case AUTH_REQ_OK:
              if (logger.logDebug()) logger.debug(" <=BE AuthenticationOk");

              return; // We're done.

            default:
              if (logger.logDebug())
                logger.debug(" <=BE AuthenticationReq (unsupported type " + ((int) areq) + ")");

              throw new PSQLException(
                  GT.tr(
                      "The authentication type {0} is not supported. Check that you have configured the pg_hba.conf file to include the client''s IP address or subnet, and that it is using an authentication scheme supported by the driver.",
                      new Integer(areq)),
                  PSQLState.CONNECTION_REJECTED);
          }

          break;

        default:
          throw new PSQLException(
              GT.tr("Protocol error.  Session setup failed."),
              PSQLState.CONNECTION_UNABLE_TO_CONNECT);
      }
    }
  }
 private void debug(String s) {
   logger.debug("XAResource " + Integer.toHexString(this.hashCode()) + ": " + s);
 }
示例#14
0
  public Object run() {

    try {

      org.ietf.jgss.Oid desiredMechs[] = new org.ietf.jgss.Oid[1];
      desiredMechs[0] = new org.ietf.jgss.Oid("1.2.840.113554.1.2.2");

      GSSManager manager = GSSManager.getInstance();

      GSSName clientName = manager.createName(user, GSSName.NT_USER_NAME);
      GSSCredential clientCreds =
          manager.createCredential(clientName, 8 * 3600, desiredMechs, GSSCredential.INITIATE_ONLY);

      GSSName serverName =
          manager.createName(kerberosServerName + "@" + host, GSSName.NT_HOSTBASED_SERVICE);

      GSSContext secContext =
          manager.createContext(
              serverName, desiredMechs[0], clientCreds, GSSContext.DEFAULT_LIFETIME);
      secContext.requestMutualAuth(true);

      byte inToken[] = new byte[0];
      byte outToken[] = null;

      boolean established = false;
      while (!established) {
        outToken = secContext.initSecContext(inToken, 0, inToken.length);

        if (outToken != null) {
          if (logger.logDebug()) logger.debug(" FE=> Password(GSS Authentication Token)");

          pgStream.SendChar('p');
          pgStream.SendInteger4(4 + outToken.length);
          pgStream.Send(outToken);
          pgStream.flush();
        }

        if (!secContext.isEstablished()) {
          int response = pgStream.ReceiveChar();
          // Error
          if (response == 'E') {
            int l_elen = pgStream.ReceiveInteger4();
            ServerErrorMessage l_errorMsg =
                new ServerErrorMessage(pgStream.ReceiveString(l_elen - 4), logger.getLogLevel());

            if (logger.logDebug()) logger.debug(" <=BE ErrorMessage(" + l_errorMsg + ")");

            return new PSQLException(l_errorMsg);

          } else if (response == 'R') {

            if (logger.logDebug()) logger.debug(" <=BE AuthenticationGSSContinue");

            int len = pgStream.ReceiveInteger4();
            int type = pgStream.ReceiveInteger4();
            // should check type = 8
            inToken = pgStream.Receive(len - 8);
          } else {
            // Unknown/unexpected message type.
            return new PSQLException(
                GT.tr("Protocol error.  Session setup failed."),
                PSQLState.CONNECTION_UNABLE_TO_CONNECT);
          }
        } else {
          established = true;
        }
      }

    } catch (IOException e) {
      return e;
    } catch (GSSException gsse) {
      return new PSQLException(
          GT.tr("GSS Authentication failed"), PSQLState.CONNECTION_FAILURE, gsse);
    }

    return null;
  }