bool allowed( const char * rq , vector<string>& headers, const SockAddr &from ) { if ( from.isLocalHost() ) return true; if ( ! _webUsers->haveAdminUsers() ) return true; string auth = getHeader( rq , "Authorization" ); if ( auth.size() > 0 && auth.find( "Digest " ) == 0 ) { auth = auth.substr( 7 ) + ", "; map<string,string> parms; pcrecpp::StringPiece input( auth ); string name, val; pcrecpp::RE re("(\\w+)=\"?(.*?)\"?, "); while ( re.Consume( &input, &name, &val) ) { parms[name] = val; } BSONObj user = _webUsers->getAdminUser( parms["username"] ); if ( ! user.isEmpty() ) { string ha1 = user["pwd"].str(); string ha2 = md5simpledigest( (string)"GET" + ":" + parms["uri"] ); stringstream r; r << ha1 << ':' << parms["nonce"]; if ( parms["nc"].size() && parms["cnonce"].size() && parms["qop"].size() ) { r << ':'; r << parms["nc"]; r << ':'; r << parms["cnonce"]; r << ':'; r << parms["qop"]; } r << ':'; r << ha2; string r1 = md5simpledigest( r.str() ); if ( r1 == parms["response"] ) return true; } } stringstream authHeader; authHeader << "WWW-Authenticate: " << "Digest realm=\"mongo\", " << "nonce=\"abc\", " << "algorithm=MD5, qop=\"auth\" " ; headers.push_back( authHeader.str() ); return 0; }
bool allowed( const char * rq , vector<string>& headers, const SockAddr &from ) { if ( from.isLocalHost() || !_webUsers->haveAdminUsers() ) { // TODO(spencer): should the above check use "&&" not "||"? Currently this is much // more permissive than the server's localhost auth bypass. cc().getAuthorizationSession()->grantInternalAuthorization(); return true; } string auth = getHeader( rq , "Authorization" ); if ( auth.size() > 0 && auth.find( "Digest " ) == 0 ) { auth = auth.substr( 7 ) + ", "; map<string,string> parms; pcrecpp::StringPiece input( auth ); string name, val; pcrecpp::RE re("(\\w+)=\"?(.*?)\"?,\\s*"); while ( re.Consume( &input, &name, &val) ) { parms[name] = val; } // Only users in the admin DB are visible by the webserver UserName userName(parms["username"], "admin"); User* user; AuthorizationManager& authzManager = cc().getAuthorizationSession()->getAuthorizationManager(); Status status = authzManager.acquireUser(userName, &user); if (!status.isOK()) { if (status.code() != ErrorCodes::UserNotFound) { uasserted(17051, status.reason()); } } else { uassert(17090, "External users don't have a password", !user->getCredentials().isExternal); string ha1 = user->getCredentials().password; authzManager.releaseUser(user); string ha2 = md5simpledigest( (string)"GET" + ":" + parms["uri"] ); stringstream r; r << ha1 << ':' << parms["nonce"]; if ( parms["nc"].size() && parms["cnonce"].size() && parms["qop"].size() ) { r << ':'; r << parms["nc"]; r << ':'; r << parms["cnonce"]; r << ':'; r << parms["qop"]; } r << ':'; r << ha2; string r1 = md5simpledigest( r.str() ); if ( r1 == parms["response"] ) { _authorizePrincipal(userName); return true; } } } stringstream authHeader; authHeader << "WWW-Authenticate: " << "Digest realm=\"mongo\", " << "nonce=\"abc\", " << "algorithm=MD5, qop=\"auth\" " ; headers.push_back( authHeader.str() ); return 0; }