mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
clean up nonce implementation
This commit is contained in:
parent
69186d293c
commit
4d5715086f
12
bson/oid.cpp
12
bson/oid.cpp
@ -34,7 +34,7 @@ namespace mongo {
|
||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__sunos__)
|
||||
pid = (unsigned short) getpid();
|
||||
#else
|
||||
pid = (unsigned short) security.getNonce();
|
||||
pid = (unsigned short) Security::getNonce();
|
||||
#endif
|
||||
return pid;
|
||||
}
|
||||
@ -53,13 +53,13 @@ namespace mongo {
|
||||
// this is not called often, so the following is not expensive, and gives us some
|
||||
// testing that nonce generation is working right and that our OIDs are (perhaps) ok.
|
||||
{
|
||||
nonce a = security.getNonce();
|
||||
nonce b = security.getNonce();
|
||||
nonce c = security.getNonce();
|
||||
nonce64 a = Security::getNonceDuringInit();
|
||||
nonce64 b = Security::getNonceDuringInit();
|
||||
nonce64 c = Security::getNonceDuringInit();
|
||||
assert( !(a==b && b==c) );
|
||||
}
|
||||
|
||||
unsigned long long n = security.getNonce();
|
||||
unsigned long long n = Security::getNonceDuringInit();
|
||||
OID::MachineAndPid x = ourMachine = (OID::MachineAndPid&) n;
|
||||
foldInPid(x);
|
||||
return x;
|
||||
@ -96,7 +96,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void OID::init() {
|
||||
static AtomicUInt inc = (unsigned) security.getNonce();
|
||||
static AtomicUInt inc = (unsigned) Security::getNonce();
|
||||
|
||||
{
|
||||
unsigned t = (unsigned) time(0);
|
||||
|
@ -41,6 +41,8 @@ namespace mongo {
|
||||
|
||||
class AlignedBuilder;
|
||||
|
||||
unsigned goodRandomNumberSlow();
|
||||
|
||||
namespace dur {
|
||||
// Rotate after reaching this data size in a journal (j._<n>) file
|
||||
// We use a smaller size for 32 bit as the journal is mmapped during recovery (only)
|
||||
@ -118,15 +120,13 @@ namespace mongo {
|
||||
strncpy(dbpath, fname.c_str(), sizeof(dbpath)-1);
|
||||
{
|
||||
fileId = t&0xffffffff;
|
||||
fileId |= ((unsigned long long)getRandomNumber()) << 32;
|
||||
fileId |= ((unsigned long long)goodRandomNumberSlow()) << 32;
|
||||
}
|
||||
memset(reserved3, 0, sizeof(reserved3));
|
||||
txt2[0] = txt2[1] = '\n';
|
||||
n1 = n2 = n3 = n4 = '\n';
|
||||
}
|
||||
|
||||
// class Journal
|
||||
|
||||
Journal j;
|
||||
|
||||
const unsigned long long LsnShutdownSentinel = ~((unsigned long long)0);
|
||||
|
50
db/nonce.cpp
50
db/nonce.cpp
@ -23,7 +23,9 @@ extern int do_md5_test(void);
|
||||
|
||||
namespace mongo {
|
||||
|
||||
BOOST_STATIC_ASSERT( sizeof(nonce) == 8 );
|
||||
BOOST_STATIC_ASSERT( sizeof(nonce64) == 8 );
|
||||
|
||||
static Security security; // needs to be static so _initialized is preset to false (see initsafe below)
|
||||
|
||||
Security::Security() {
|
||||
static int n;
|
||||
@ -31,7 +33,7 @@ namespace mongo {
|
||||
init();
|
||||
}
|
||||
|
||||
void Security::init() {
|
||||
NOINLINE_DECL void Security::init() {
|
||||
if( _initialized ) return;
|
||||
_initialized = true;
|
||||
|
||||
@ -39,7 +41,7 @@ namespace mongo {
|
||||
_devrandom = new ifstream("/dev/urandom", ios::binary|ios::in);
|
||||
massert( 10353 , "can't open dev/urandom", _devrandom->is_open() );
|
||||
#elif defined(_WIN32)
|
||||
srand(curTimeMicros());
|
||||
srand(curTimeMicros()); // perhaps not relevant for rand_s but we might want elsewhere anyway
|
||||
#else
|
||||
srandomdev();
|
||||
#endif
|
||||
@ -50,21 +52,12 @@ namespace mongo {
|
||||
#endif
|
||||
}
|
||||
|
||||
nonce Security::getNonce() {
|
||||
static mongo::mutex m("getNonce");
|
||||
scoped_lock lk(m);
|
||||
|
||||
if ( ! _initialized )
|
||||
init();
|
||||
|
||||
/* question/todo: /dev/random works on OS X. is it better
|
||||
to use that than random() / srandom()?
|
||||
*/
|
||||
|
||||
nonce n;
|
||||
nonce64 Security::__getNonce() {
|
||||
dassert( _initialized );
|
||||
nonce64 n;
|
||||
#if defined(__linux__) || defined(__sunos__) || defined(__APPLE__)
|
||||
_devrandom->read((char*)&n, sizeof(n));
|
||||
massert( 10355 , "devrandom failed", !_devrandom->fail());
|
||||
massert(10355 , "devrandom failed", !_devrandom->fail());
|
||||
#elif defined(_WIN32)
|
||||
unsigned a=0, b=0;
|
||||
assert( rand_s(&a) == 0 );
|
||||
@ -75,9 +68,28 @@ namespace mongo {
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
unsigned getRandomNumber() { return (unsigned) security.getNonce(); }
|
||||
|
||||
bool Security::_initialized;
|
||||
Security security;
|
||||
SimpleMutex nonceMutex("nonce");
|
||||
nonce64 Security::_getNonce() {
|
||||
// not good this is a static as gcc will mutex protect it which costs time
|
||||
SimpleMutex::scoped_lock lk(nonceMutex);
|
||||
if( !_initialized )
|
||||
init();
|
||||
return __getNonce();
|
||||
}
|
||||
|
||||
nonce64 Security::getNonceDuringInit() {
|
||||
// the mutex might not be inited yet. init phase should be one thread anyway (hopefully we don't spawn threads therein)
|
||||
if( !security._initialized )
|
||||
security.init();
|
||||
return security.__getNonce();
|
||||
}
|
||||
|
||||
nonce64 Security::getNonce() {
|
||||
return security._getNonce();
|
||||
}
|
||||
|
||||
// name warns us this might be a little slow (see code above)
|
||||
unsigned goodRandomNumberSlow() { return (unsigned) Security::getNonce(); }
|
||||
|
||||
} // namespace mongo
|
||||
|
20
db/nonce.h
20
db/nonce.h
@ -1,4 +1,4 @@
|
||||
// nonce.h
|
||||
// @file nonce.h
|
||||
|
||||
/* Copyright 2009 10gen Inc.
|
||||
*
|
||||
@ -19,24 +19,18 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
typedef unsigned long long nonce;
|
||||
typedef unsigned long long nonce64;
|
||||
|
||||
struct Security {
|
||||
Security();
|
||||
|
||||
nonce getNonce();
|
||||
|
||||
/** safe during global var initialization */
|
||||
nonce getNonceInitSafe() {
|
||||
init();
|
||||
return getNonce();
|
||||
}
|
||||
static nonce64 getNonce();
|
||||
static nonce64 getNonceDuringInit(); // use this version during global var constructors
|
||||
private:
|
||||
nonce64 _getNonce();
|
||||
nonce64 __getNonce();
|
||||
ifstream *_devrandom;
|
||||
static bool _initialized;
|
||||
bool _initialized;
|
||||
void init(); // can call more than once
|
||||
};
|
||||
|
||||
extern Security security;
|
||||
|
||||
} // namespace mongo
|
||||
|
@ -39,12 +39,12 @@ namespace mongo {
|
||||
|
||||
getnonce sends nonce to client
|
||||
|
||||
client then sends { authenticate:1, nonce:<nonce_str>, user:<username>, key:<key> }
|
||||
client then sends { authenticate:1, nonce64:<nonce_str>, user:<username>, key:<key> }
|
||||
|
||||
where <key> is md5(<nonce_str><username><pwd_digest_str>) as a string
|
||||
*/
|
||||
|
||||
boost::thread_specific_ptr<nonce> lastNonce;
|
||||
boost::thread_specific_ptr<nonce64> lastNonce;
|
||||
|
||||
class CmdGetNonce : public Command {
|
||||
public:
|
||||
@ -57,7 +57,7 @@ namespace mongo {
|
||||
virtual LockType locktype() const { return NONE; }
|
||||
CmdGetNonce() : Command("getnonce") {}
|
||||
bool run(const string&, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
||||
nonce *n = new nonce(security.getNonce());
|
||||
nonce64 *n = new nonce64(Security::getNonce());
|
||||
stringstream ss;
|
||||
ss << hex << *n;
|
||||
result.append("nonce", ss.str() );
|
||||
@ -116,7 +116,7 @@ namespace mongo {
|
||||
|
||||
{
|
||||
bool reject = false;
|
||||
nonce *ln = lastNonce.release();
|
||||
nonce64 *ln = lastNonce.release();
|
||||
if ( ln == 0 ) {
|
||||
reject = true;
|
||||
log(1) << "auth: no lastNonce" << endl;
|
||||
|
@ -184,7 +184,7 @@ namespace mongo {
|
||||
|
||||
long long CursorCache::genId() {
|
||||
while ( true ) {
|
||||
long long x = security.getNonce();
|
||||
long long x = Security::getNonce();
|
||||
if ( x == 0 )
|
||||
continue;
|
||||
if ( x < 0 )
|
||||
|
@ -1744,8 +1744,8 @@ const StringData _jscode_raw_db =
|
||||
"this.getCollection( \"system.users\" ).remove( { user : username } );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"DB.prototype.__pwHash = function( nonce, username, pass ) {\n"
|
||||
"return hex_md5( nonce + username + hex_md5( username + \":mongo:\" + pass ) );\n"
|
||||
"DB.prototype.__pwHash = function( nonce64, username, pass ) {\n"
|
||||
"return hex_md5( nonce64 + username + hex_md5( username + \":mongo:\" + pass ) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"DB.prototype.auth = function( username , pass ){\n"
|
||||
@ -1755,8 +1755,8 @@ const StringData _jscode_raw_db =
|
||||
"{\n"
|
||||
"authenticate : 1 ,\n"
|
||||
"user : username ,\n"
|
||||
"nonce : n.nonce ,\n"
|
||||
"key : this.__pwHash( n.nonce, username, pass )\n"
|
||||
"nonce64 : n.nonce64 ,\n"
|
||||
"key : this.__pwHash( n.nonce64, username, pass )\n"
|
||||
"}\n"
|
||||
");\n"
|
||||
"\n"
|
||||
@ -1925,7 +1925,7 @@ const StringData _jscode_raw_db =
|
||||
"fromhost = fromhost || \"\";\n"
|
||||
"if ( username && password ) {\n"
|
||||
"var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } );\n"
|
||||
"return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, username, password ) } );\n"
|
||||
"return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce64:n.nonce64, key:this.__pwHash( n.nonce64, username, password ) } );\n"
|
||||
"} else {\n"
|
||||
"return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } );\n"
|
||||
"}\n"
|
||||
|
Loading…
Reference in New Issue
Block a user