KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx, const KillAllSessionsUser& kasu) { KillAllSessionsByPattern kasbp = makeKillAllSessionsByPattern(opCtx); auto authMgr = AuthorizationManager::get(opCtx->getServiceContext()); User* user; UserName un(kasu.getUser(), kasu.getDb()); uassertStatusOK(authMgr->acquireUser(opCtx, un, &user)); kasbp.setUid(user->getDigest()); authMgr->releaseUser(user); return kasbp; }
StatusWith<UserHandle> AuthorizationManagerImpl::acquireUserForSessionRefresh( OperationContext* opCtx, const UserName& userName, const User::UserId& uid) { auto swUserHandle = acquireUser(opCtx, userName); if (!swUserHandle.isOK()) { return swUserHandle.getStatus(); } auto ret = std::move(swUserHandle.getValue()); if (uid != ret->getID()) { return {ErrorCodes::UserNotFound, str::stream() << "User id from privilege document '" << userName.toString() << "' does not match user id in session."}; } return ret; }
StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_firstStep( OperationContext* opCtx, StringData inputData) { const auto badCount = [](int got) { return Status(ErrorCodes::BadValue, str::stream() << "Incorrect number of arguments for first SCRAM client message, got " << got << " expected at least 3"); }; /** * gs2-cbind-flag := ("p=" cb-name) / 'y' / 'n' * gs2-header := gs2-cbind-flag ',' [ authzid ] ',' * reserved-mext := "m=" 1*(value-char) * client-first-message-bare := [reserved-mext ','] username ',' nonce [',' extensions] * client-first-message := gs2-header client-first-message-bare */ const auto gs2_cbind_comma = inputData.find(','); if (gs2_cbind_comma == std::string::npos) { return badCount(1); } const auto gs2_cbind_flag = inputData.substr(0, gs2_cbind_comma); if (gs2_cbind_flag.startsWith("p=")) { return Status(ErrorCodes::BadValue, "Server does not support channel binding"); } if ((gs2_cbind_flag != "y") && (gs2_cbind_flag != "n")) { return Status(ErrorCodes::BadValue, str::stream() << "Incorrect SCRAM client message prefix: " << gs2_cbind_flag); } const auto gs2_header_comma = inputData.find(',', gs2_cbind_comma + 1); if (gs2_header_comma == std::string::npos) { return badCount(2); } auto authzId = inputData.substr(gs2_cbind_comma + 1, gs2_header_comma - (gs2_cbind_comma + 1)); if (authzId.size()) { if (authzId.startsWith("a=")) { authzId = authzId.substr(2); } else { return Status(ErrorCodes::BadValue, str::stream() << "Incorrect SCRAM authzid: " << authzId); } } const auto client_first_message_bare = inputData.substr(gs2_header_comma + 1); if (client_first_message_bare.startsWith("m=")) { return Status(ErrorCodes::BadValue, "SCRAM mandatory extensions are not supported"); } /* StringSplitter::split() will ignore consecutive delimiters. * e.g. "foo,,bar" => {"foo","bar"} * This makes our implementation of SCRAM *slightly* more generous * in what it will accept than the standard calls for. * * This does not impact _authMessage, as it's composed from the raw * string input, rather than the output of the split operation. */ const auto input = StringSplitter::split(client_first_message_bare.toString(), ","); if (input.size() < 2) { // gs2-header is not included in this count, so add it back in. return badCount(input.size() + 2); } if (!str::startsWith(input[0], "n=") || input[0].size() < 3) { return Status(ErrorCodes::BadValue, str::stream() << "Invalid SCRAM user name: " << input[0]); } ServerMechanismBase::_principalName = input[0].substr(2); decodeSCRAMUsername(ServerMechanismBase::_principalName); if (!authzId.empty() && ServerMechanismBase::_principalName != authzId) { return Status(ErrorCodes::BadValue, str::stream() << "SCRAM user name " << ServerMechanismBase::_principalName << " does not match authzid " << authzId); } if (!str::startsWith(input[1], "r=") || input[1].size() < 6) { return Status(ErrorCodes::BadValue, str::stream() << "Invalid SCRAM client nonce: " << input[1]); } const auto clientNonce = input[1].substr(2); // SERVER-16534, SCRAM-SHA-1 must be enabled for authenticating the internal user, so that // cluster members may communicate with each other. Hence ignore disabled auth mechanism // for the internal user. UserName user(ServerMechanismBase::ServerMechanismBase::_principalName, ServerMechanismBase::getAuthenticationDatabase()); if (!sequenceContains(saslGlobalParams.authenticationMechanisms, "SCRAM-SHA-1") && user != internalSecurity.user->getName()) { return Status(ErrorCodes::BadValue, "SCRAM-SHA-1 authentication is disabled"); } // The authentication database is also the source database for the user. User* userObj; auto authManager = AuthorizationManager::get(opCtx->getServiceContext()); Status status = authManager->acquireUser(opCtx, user, &userObj); if (!status.isOK()) { return status; } User::CredentialData credentials = userObj->getCredentials(); UserName userName = userObj->getName(); authManager->releaseUser(userObj); _scramCredentials = credentials.scram<HashBlock>(); if (!_scramCredentials.isValid()) { // Check for authentication attempts of the __system user on // systems started without a keyfile. if (userName == internalSecurity.user->getName()) { return Status(ErrorCodes::AuthenticationFailed, "It is not possible to authenticate as the __system user " "on servers started without a --keyFile parameter"); } else { return Status(ErrorCodes::AuthenticationFailed, "Unable to perform SCRAM authentication for a user with missing " "or invalid SCRAM credentials"); } } _secrets = scram::Secrets<HashBlock>("", base64::decode(_scramCredentials.storedKey), base64::decode(_scramCredentials.serverKey)); // Generate server-first-message // Create text-based nonce as base64 encoding of a binary blob of length multiple of 3 const int nonceLenQWords = 3; uint64_t binaryNonce[nonceLenQWords]; std::unique_ptr<SecureRandom> sr(SecureRandom::create()); binaryNonce[0] = sr->nextInt64(); binaryNonce[1] = sr->nextInt64(); binaryNonce[2] = sr->nextInt64(); _nonce = clientNonce + base64::encode(reinterpret_cast<char*>(binaryNonce), sizeof(binaryNonce)); StringBuilder sb; sb << "r=" << _nonce << ",s=" << _scramCredentials.salt << ",i=" << _scramCredentials.iterationCount; std::string outputData = sb.str(); // add client-first-message-bare and server-first-message to _authMessage _authMessage = client_first_message_bare.toString() + "," + outputData; return std::make_tuple(false, std::move(outputData)); }