Exemple #1
0
    Status HostAndPort::initialize(const StringData& s) {
        const size_t colonPos = s.rfind(':');
        const StringData hostPart = s.substr(0, colonPos);
        if (hostPart.empty()) {
            return Status(ErrorCodes::FailedToParse, str::stream() <<
                          "Empty host component parsing HostAndPort from \"" <<
                          escape(s.toString()) << "\"");
        }

        int port;
        if (colonPos != std::string::npos) {
            const StringData portPart = s.substr(colonPos + 1);
            Status status = parseNumberFromStringWithBase(portPart, 10, &port);
            if (!status.isOK()) {
                return status;
            }
            if (port <= 0) {
                return Status(ErrorCodes::FailedToParse, str::stream() << "Port number " << port <<
                              " out of range parsing HostAndPort from \"" << escape(s.toString()) <<
                              "\"");
            }
        }
        else {
            port = -1;
        }
        _host = hostPart.toString();
        _port = port;
        return Status::OK();
    }
    Status HostAndPort::initialize(const StringData& s) {
        size_t colonPos = s.rfind(':');
        StringData hostPart = s.substr(0, colonPos);

        // handle ipv6 hostPart (which we require to be wrapped in []s)
        const size_t openBracketPos = s.find('[');
        const size_t closeBracketPos = s.find(']');
        if (openBracketPos != std::string::npos) {
            if (openBracketPos != 0) {
                return Status(ErrorCodes::FailedToParse,
                              str::stream() << "'[' present, but not first character in "
                                            << s.toString());
            }
            if (closeBracketPos == std::string::npos) {
                return Status(ErrorCodes::FailedToParse,
                              str::stream() << "ipv6 address is missing closing ']' in hostname in "
                                            << s.toString());
            }

            hostPart = s.substr(openBracketPos+1, closeBracketPos-openBracketPos-1);
            // prevent accidental assignment of port to the value of the final portion of hostPart
            if (colonPos < closeBracketPos) {
                colonPos = std::string::npos;
            }
            else if (colonPos != closeBracketPos+1) {
                return Status(ErrorCodes::FailedToParse,
                              str::stream() << "Extraneous characters between ']' and pre-port ':'"
                                            << " in " << s.toString());
            }
        }
        else if (closeBracketPos != std::string::npos) {
            return Status(ErrorCodes::FailedToParse,
                          str::stream() << "']' present without '[' in " << s.toString());
        }

        if (hostPart.empty()) {
            return Status(ErrorCodes::FailedToParse, str::stream() <<
                          "Empty host component parsing HostAndPort from \"" <<
                          escape(s.toString()) << "\"");
        }

        int port;
        if (colonPos != std::string::npos) {
            const StringData portPart = s.substr(colonPos + 1);
            Status status = parseNumberFromStringWithBase(portPart, 10, &port);
            if (!status.isOK()) {
                return status;
            }
            if (port <= 0) {
                return Status(ErrorCodes::FailedToParse, str::stream() << "Port number " << port <<
                              " out of range parsing HostAndPort from \"" << escape(s.toString()) <<
                              "\"");
            }
        }
        else {
            port = -1;
        }
        _host = hostPart.toString();
        _port = port;
        return Status::OK();
    }
Exemple #3
0
StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_secondStep(
    OperationContext* opCtx, StringData inputData) {
    const auto badCount = [](int got) {
        return Status(ErrorCodes::BadValue,
                      str::stream()
                          << "Incorrect number of arguments for second SCRAM client message, got "
                          << got
                          << " expected at least 3");
    };

    /**
     * client-final-message-without-proof := cbind ',' nonce ',' [ ',' extensions ]
     * client-final-message := client-final-message-without-proof ',' proof
     */
    const auto last_comma = inputData.rfind(',');
    if (last_comma == std::string::npos) {
        return badCount(1);
    }

    // add client-final-message-without-proof to authMessage
    const auto client_final_message_without_proof = inputData.substr(0, last_comma);
    _authMessage += "," + client_final_message_without_proof.toString();

    const auto last_field = inputData.substr(last_comma + 1);
    if ((last_field.size() < 3) || !last_field.startsWith("p=")) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << "Incorrect SCRAM ClientProof: " << last_field);
    }
    const auto proof = last_field.substr(2);

    const auto input = StringSplitter::split(client_final_message_without_proof.toString(), ",");
    if (input.size() < 2) {
        // Add count for proof back on.
        return badCount(input.size() + 1);
    }

    if (!str::startsWith(input[0], "c=") || input[0].size() < 3) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << "Incorrect SCRAM channel binding: " << input[0]);
    }
    const auto cbind = input[0].substr(2);

    if (!str::startsWith(input[1], "r=") || input[1].size() < 6) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << "Incorrect SCRAM client|server nonce: " << input[1]);
    }
    const auto nonce = input[1].substr(2);

    // Concatenated nonce sent by client should equal the one in server-first-message
    if (nonce != _nonce) {
        return Status(ErrorCodes::BadValue,
                      str::stream()
                          << "Unmatched SCRAM nonce received from client in second step, expected "
                          << _nonce
                          << " but received "
                          << nonce);
    }

    // Do server side computations, compare storedKeys and generate client-final-message
    // AuthMessage     := client-first-message-bare + "," +
    //                    server-first-message + "," +
    //                    client-final-message-without-proof
    // ClientSignature := HMAC(StoredKey, AuthMessage)
    // ClientKey := ClientSignature XOR ClientProof
    // ServerSignature := HMAC(ServerKey, AuthMessage)

    if (!_secrets.verifyClientProof(_authMessage, base64::decode(proof.toString()))) {
        return Status(ErrorCodes::AuthenticationFailed,
                      "SCRAM authentication failed, storedKey mismatch");
    }

    StringBuilder sb;
    // ServerSignature := HMAC(ServerKey, AuthMessage)
    sb << "v=" << _secrets.generateServerSignature(_authMessage);

    return std::make_tuple(false, sb.str());
}