bool DbWebServer::_allowed(OperationContext* txn, const char* rq, vector<string>& headers, const SockAddr& from) { AuthorizationSession* authSess = AuthorizationSession::get(txn->getClient()); if (!authSess->getAuthorizationManager().isAuthEnabled()) { return true; } if (from.isLocalHost() && !_webUsers->haveAdminUsers(txn)) { authSess->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 = authSess->getAuthorizationManager(); Status status = authzManager.acquireUser(txn, 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); if (ha1.empty()) { return false; } const 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; const string r1 = md5simpledigest(r.str()); if (r1 == parms["response"]) { Status status = authSess->addAndAuthorizeUser(txn, userName); uassertStatusOK(status); return true; } } } stringstream authHeader; authHeader << "WWW-Authenticate: " << "Digest realm=\"mongo\", " << "nonce=\"abc\", " << "algorithm=MD5, qop=\"auth\" "; headers.push_back(authHeader.str()); return 0; }
bool RestAdminAccess::haveAdminUsers(OperationContext* txn) const { AuthorizationSession* authzSession = cc().getAuthorizationSession(); return authzSession->getAuthorizationManager().hasAnyPrivilegeDocuments(txn); }
std::vector<BSONObj> MongoProcessCommon::getCurrentOps( const boost::intrusive_ptr<ExpressionContext>& expCtx, CurrentOpConnectionsMode connMode, CurrentOpSessionsMode sessionMode, CurrentOpUserMode userMode, CurrentOpTruncateMode truncateMode, CurrentOpCursorMode cursorMode) const { OperationContext* opCtx = expCtx->opCtx; AuthorizationSession* ctxAuth = AuthorizationSession::get(opCtx->getClient()); std::vector<BSONObj> ops; for (ServiceContext::LockedClientsCursor cursor(opCtx->getClient()->getServiceContext()); Client* client = cursor.next();) { invariant(client); stdx::lock_guard<Client> lk(*client); // If auth is disabled, ignore the allUsers parameter. if (ctxAuth->getAuthorizationManager().isAuthEnabled() && userMode == CurrentOpUserMode::kExcludeOthers && !ctxAuth->isCoauthorizedWithClient(client)) { continue; } // Ignore inactive connections unless 'idleConnections' is true. if (!client->getOperationContext() && connMode == CurrentOpConnectionsMode::kExcludeIdle) { continue; } // Delegate to the mongoD- or mongoS-specific implementation of _reportCurrentOpForClient. ops.emplace_back(_reportCurrentOpForClient(opCtx, client, truncateMode)); } // If 'cursorMode' is set to include idle cursors, retrieve them and add them to ops. if (cursorMode == CurrentOpCursorMode::kIncludeCursors) { for (auto&& cursor : getIdleCursors(expCtx, userMode)) { BSONObjBuilder cursorObj; auto ns = cursor.getNs(); auto lsid = cursor.getLsid(); cursorObj.append("type", "idleCursor"); cursorObj.append("host", getHostNameCached()); cursorObj.append("ns", ns->toString()); // If in legacy read mode, lsid is not present. if (lsid) { cursorObj.append("lsid", lsid->toBSON()); } cursor.setNs(boost::none); cursor.setLsid(boost::none); // On mongos, planSummary is not present. auto planSummaryData = cursor.getPlanSummary(); if (planSummaryData) { auto planSummaryText = planSummaryData->toString(); // Plan summary has to appear in the top level object, not the cursor object. // We remove it, create the op, then put it back. cursor.setPlanSummary(boost::none); cursorObj.append("planSummary", planSummaryText); cursorObj.append("cursor", cursor.toBSON()); cursor.setPlanSummary(StringData(planSummaryText)); } else { cursorObj.append("cursor", cursor.toBSON()); } ops.emplace_back(cursorObj.obj()); cursor.setNs(ns); cursor.setLsid(lsid); } } // If we need to report on idle Sessions, defer to the mongoD or mongoS implementations. if (sessionMode == CurrentOpSessionsMode::kIncludeIdle) { _reportCurrentOpsForIdleSessions(opCtx, userMode, &ops); } return ops; }