Skip to content

Commit

Permalink
make security work with repl pairs
Browse files Browse the repository at this point in the history
replicate system.users collection
  • Loading branch information
dwight authored and dwight committed Jan 25, 2009
1 parent 8413895 commit 76b6aac
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 19 deletions.
50 changes: 33 additions & 17 deletions client/dbclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ namespace mongo {
}

bool DBClientWithCommands::auth(const char *dbname, const char *username, const char *password_text, string& errmsg, bool digestPassword) {
//cout << "TEMP AUTH " << toString() << dbname << ' ' << username << ' ' << password_text << ' ' << digestPassword << endl;

string password = password_text;
if( digestPassword )
password = createPasswordDigest( password_text );
Expand Down Expand Up @@ -98,9 +100,7 @@ namespace mongo {
md5_finish(&st, d);
}
b << "key" << digestToString( d );
//b.appendBinData("key", 16, MD5Type, (const char *) d);
authCmd = b.done();
//cout << "TEMP: authCmd: " << authCmd.toString() << endl;
}

if( runCommand(dbname, authCmd, info) )
Expand Down Expand Up @@ -237,19 +237,19 @@ namespace mongo {
/* --- dbclientconnection --- */

bool DBClientConnection::auth(const char *dbname, const char *username, const char *password_text, string& errmsg, bool digestPassword) {
if( !autoReconnect )
return DBClientBase::auth(dbname, username, password_text, errmsg, digestPassword);

string password = password_text;
if( digestPassword )
password = createPasswordDigest( password_text );

if( !DBClientBase::auth(dbname, username, password.c_str(), errmsg, false) )
return false;
if( autoReconnect ) {
/* note we remember the auth info before we attempt to auth -- if the connection is broken, we will
then have it for the next autoreconnect attempt.
*/
pair<string,string> p = pair<string,string>(username, password);
authCache[dbname] = p;
}

pair<string,string> p = pair<string,string>(username, password);
authCache[dbname] = p;
return true;
return DBClientBase::auth(dbname, username, password.c_str(), errmsg, false);
}

BSONObj DBClientBase::findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn, int queryOptions) {
Expand Down Expand Up @@ -317,13 +317,12 @@ namespace mongo {
}

log() << "reconnect " << serverAddress << " ok" << endl;
//cout << "TEMP: authcache size: " << authCache.size() << endl;
for( map< string, pair<string,string> >::iterator i = authCache.begin(); i != authCache.end(); i++ ) {
const char *dbname = i->first.c_str();
const char *username = i->second.first.c_str();
const char *password = i->second.second.c_str();
if( !DBClientBase::auth(dbname, username, password, errmsg, false) )
log() << "reconnect: auth failed db:" << dbname << " user:" << username << '\n';
log() << "reconnect: auth failed db:" << dbname << " user:" << username << ' ' << errmsg << '\n';
}
}

Expand Down Expand Up @@ -708,12 +707,29 @@ namespace mongo {
try {
checkMaster();
}
catch (UserAssertionException&) {
catch (AssertionException&) {
return false;
}
return true;
}

bool DBClientPaired::auth(const char *dbname, const char *username, const char *pwd, string& errmsg) {
DBClientConnection& m = checkMaster();
if( !m.auth(dbname, username, pwd, errmsg) )
return false;
/* we try to authentiate with the other half of the pair -- even if down, that way the authInfo is cached. */
string e;
try {
if( &m == &left )
right.auth(dbname, username, pwd, e);
else
left.auth(dbname, username, pwd, e);
}
catch( AssertionException&) {
}
return true;
}

auto_ptr<DBClientCursor> DBClientPaired::query(const char *a, BSONObj b, int c, int d,
BSONObj *e, int f)
{
Expand All @@ -725,12 +741,12 @@ namespace mongo {
}

void testPaired() {
// DBClientPaired p;
// log() << "connect returns " << p.connect("localhost:27017", "localhost:27018") << endl;
DBClientPaired p;
log() << "connect returns " << p.connect("localhost:27017", "localhost:27018") << endl;

DBClientConnection p(true);
//DBClientConnection p(true);
string errmsg;
log() << "connect " << p.connect("localhost", errmsg) << endl;
// log() << "connect " << p.connect("localhost", errmsg) << endl;
log() << "auth " << p.auth("dwight", "u", "p", errmsg) << endl;

while( 1 ) {
Expand Down
2 changes: 2 additions & 0 deletions client/dbclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ namespace mongo {
*/
bool connect(const char *serverHostname1, const char *serverHostname2);

bool auth(const char *dbname, const char *username, const char *pwd, string& errmsg);

/* throws userassertion "no master found" */
virtual
auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
Expand Down
9 changes: 8 additions & 1 deletion db/cloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,14 @@ namespace mongo {
assert( !e.eoo() );
assert( e.type() == String );
const char *from_name = e.valuestr();
if ( strstr(from_name, ".system.") || strchr(from_name, '$') ) {

if( strstr(from_name, ".system.") ) {
/* system.users is cloned -- but nothing else from system. */
if( strstr(from_name, ".system.users") == 0 )
continue;
}
else if( strchr(from_name, '$') ) {
log() << "clone: '$' char in namespaces outside of system???\n";
continue;
}
BSONObj options = collection.getObjectField("options");
Expand Down
2 changes: 1 addition & 1 deletion db/repl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ namespace mongo {
massert("bad user object? [1]", !u.empty());
massert("bad user object? [2]", !p.empty());
string err;
if( !conn->auth("admin", u.c_str(), p.c_str(), err, false) ) {
if( !conn->auth("local", u.c_str(), p.c_str(), err, false) ) {
log() << "replauthenticate: can't authenticate to master server, user:" << u << endl;
return false;
}
Expand Down
1 change: 1 addition & 0 deletions db/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace mongo {
if( m[dbname].level == 2 ) return true;
if( noauth ) return true;
if( m["admin"].level == 2 ) return true;
if( m["local"].level == 2 ) return true;
if( isLocalHost ) {
DBContext c("admin.system.users");
BSONObj result;
Expand Down

0 comments on commit 76b6aac

Please sign in to comment.