[JAVA-269] NullPointerException when authentication used with replica sets not logged correctly Created: 10/Feb/11  Updated: 17/Mar/11  Resolved: 11/Feb/11

Status: Closed
Project: Java Driver
Component/s: Cluster Management
Affects Version/s: 2.4, 2.5
Fix Version/s: 2.5

Type: Bug Priority: Major - P3
Reporter: Mike Copley Assignee: Antoine Girbal
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

OS X 10.6.6, Java driver. 3-node replica set with user authentication (--auth) (and replica authentication --keyFile)



 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)



 Comments   
Comment by auto [ 11/Feb/11 ]

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

Comment by Antoine Girbal [ 11/Feb/11 ]

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.

Comment by Antoine Girbal [ 11/Feb/11 ]

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.
Generated at Thu Feb 08 08:51:53 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.