Java Driver
  1. Java Driver
  2. JAVA-269

NullPointerException when authentication used with replica sets not logged correctly

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major - P3 Major - P3
    • Resolution: Fixed
    • Affects Version/s: 2.4, 2.5
    • Fix Version/s: 2.5
    • Component/s: Cluster Management
    • Labels:
      None
    • Environment:
      OS X 10.6.6, Java driver. 3-node replica set with user authentication (--auth) (and replica authentication --keyFile)
    • Operating System:
      ALL
    • # Replies:
      3
    • Last comment by Customer:
      false

      Description

      If you try use the java driver to connect to a database that requires authentication, a NullPointerException is thrown and caught in Node.update(). This is because at the point the update is attempted, the java code has yet to call the DB.authenticate() method. Because the exception is already caught, it is not preventing anything from working. However the code should handle this better so as to not generate a NPE in the first place.

      String setName = config.get("_id").toString(); // <-- .toString() triggers NPE if DB.authenticate() hasn't yet been called.
      if ( _setName == null )

      { _setName = setName; _logger = Logger.getLogger( _rootLogger.getName() + "." + setName ); }

      Inspecting config shows it has $err defined (unauthenticated message) as well as code (10057). Suggest checking if null first, then checking if an error exists and if it's not authentication related, only then show the user. Another alternative would be to have DBPort check for the condition first and then throw a MongoInternalException.

      static final int UNAUTHENTICATED_ERROR_CODE = 10057;
      ...

      Object setNameObj = config.get("_id");
      if (setNameObj == null) {
      if (config.get("$err") != null && UNAUTHENTICATED_ERROR_CODE != (Integer)config.get("code"))

      { _logger.log( Level.SEVERE, "can't get set name from node: " +_addr + ". Error: " + config.get("$err")); }

      return;
      }
      String setName = setNameObj.toString();

      Stack Trace (based on git head, commit a052b4f35af4069121cbf47adc88d6199563c4d4):

      Feb 10, 2011 3:53:17 PM com.mongodb.ReplicaSetStatus$Node update
      SEVERE: unexpected error getting config from node: 10.211.55.23:23003
      java.lang.NullPointerException
      at com.mongodb.ReplicaSetStatus$Node.update(ReplicaSetStatus.java:174)
      at com.mongodb.ReplicaSetStatus.updateAll(ReplicaSetStatus.java:287)
      at com.mongodb.ReplicaSetStatus$Updater.run(ReplicaSetStatus.java:248)
      Feb 10, 2011 3:53:17 PM com.mongodb.ReplicaSetStatus$Node update
      SEVERE: unexpected error getting config from node: 10.211.55.23:23003
      java.lang.NullPointerException
      at com.mongodb.ReplicaSetStatus$Node.update(ReplicaSetStatus.java:174)
      at com.mongodb.ReplicaSetStatus.updateAll(ReplicaSetStatus.java:287)
      at com.mongodb.ReplicaSetStatus.ensureMaster(ReplicaSetStatus.java:280)
      at com.mongodb.DBTCPConnector.checkMaster(DBTCPConnector.java:364)
      at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:206)
      at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:271)
      at com.mongodb.DB.command(DB.java:154)
      at com.mongodb.DB.command(DB.java:139)
      at com.mongodb.DB._doauth(DB.java:469)
      at com.mongodb.DB.authenticate(DB.java:434)

        Activity

        Hide
        Antoine Girbal
        added a comment -

        the problem is slightly worse than that: even once authenticate is called by user, it will not stop the NPE.
        The updater thread uses a dedicated port for each mongod, and calls methods directly on the port.
        This means that checkAuth() is not called and most operations on it would fail.

        fortunately the isMaster command always succeeds
        foo:SECONDARY> use admin
        switched to db admin
        foo:SECONDARY> show collections
        Thu Feb 10 23:55:17 uncaught exception: error:

        { "$err" : "unauthorized db:admin lock type:-1 client:127.0.0.1", "code" : 10057 }

        foo:SECONDARY> db.runCommand("isMaster")

        { "setName" : "foo", "ismaster" : false, "secondary" : true, "hosts" : [ "localhost:27017", "localhost:27018" ], "passives" : [ "localhost:27019" ], "primary" : "localhost:27018", "maxBsonObjectSize" : 16777216, "ok" : 1 }

        But getting the replset config will fail:
        foo:SECONDARY> use local
        switched to db local
        foo:SECONDARY> db.system.replset.find()
        error:

        { "$err" : "unauthorized db:local lock type:-1 client:127.0.0.1", "code" : 10057 }

        Right now the driver only needs that operation to obtain the setName from master node.
        The setName is not actively used in driver, just to print out warning if it changes.

        Proposed fix:

        • add checkAuth to the direct port operations.
        • if we get error because not authenticated, print out warning that user should authenticate against admin or local.
        Show
        Antoine Girbal
        added a comment - the problem is slightly worse than that: even once authenticate is called by user, it will not stop the NPE. The updater thread uses a dedicated port for each mongod, and calls methods directly on the port. This means that checkAuth() is not called and most operations on it would fail. fortunately the isMaster command always succeeds foo:SECONDARY> use admin switched to db admin foo:SECONDARY> show collections Thu Feb 10 23:55:17 uncaught exception: error: { "$err" : "unauthorized db:admin lock type:-1 client:127.0.0.1", "code" : 10057 } foo:SECONDARY> db.runCommand("isMaster") { "setName" : "foo", "ismaster" : false, "secondary" : true, "hosts" : [ "localhost:27017", "localhost:27018" ], "passives" : [ "localhost:27019" ], "primary" : "localhost:27018", "maxBsonObjectSize" : 16777216, "ok" : 1 } But getting the replset config will fail: foo:SECONDARY> use local switched to db local foo:SECONDARY> db.system.replset.find() error: { "$err" : "unauthorized db:local lock type:-1 client:127.0.0.1", "code" : 10057 } Right now the driver only needs that operation to obtain the setName from master node. The setName is not actively used in driver, just to print out warning if it changes. Proposed fix: add checkAuth to the direct port operations. if we get error because not authenticated, print out warning that user should authenticate against admin or local.
        Hide
        Antoine Girbal
        added a comment - - edited

        final fix:
        add a checkAuth for DB local before trying to get replset config in updater.
        If the result is an error with a code that states needs auth, then driver logs a line telling user to auth against local or admin.

        Show
        Antoine Girbal
        added a comment - - edited final fix: add a checkAuth for DB local before trying to get replset config in updater. If the result is an error with a code that states needs auth, then driver logs a line telling user to auth against local or admin.
        Hide
        auto
        added a comment -

        Author:

        {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'}

        Message: JAVA-269: NullPointerException when authentication used with replica sets not logged correctly
        https://github.com/mongodb/mongo-java-driver/commit/eacd9a594bf2f5d4ffe5f237decca61b1721bc8f

        Show
        auto
        added a comment - Author: {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'} Message: JAVA-269 : NullPointerException when authentication used with replica sets not logged correctly https://github.com/mongodb/mongo-java-driver/commit/eacd9a594bf2f5d4ffe5f237decca61b1721bc8f

          People

          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since reply:
              3 years, 10 weeks, 1 day ago
              Date of 1st Reply: