コード例 #1
0
ファイル: kill_sessions.cpp プロジェクト: louiswilliams/mongo
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;
}
コード例 #2
0
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));
}