Beispiel #1
0
bool
ConnectHandouts::try_insert (beast::IP::Endpoint const& endpoint)
{
    if (full ())
        return false;

    // Make sure the address isn't already in our list
    if (std::any_of (m_list.begin(), m_list.end(),
        [&endpoint](beast::IP::Endpoint const& other)
        {
            // Ignore port for security reasons
            return other.address() ==
                endpoint.address();
        }))
    {
        return false;
    }

    // Add to squelch list so we don't try it too often.
    // If its already there, then make try_insert fail.
    auto const result (m_squelches.insert (
        endpoint.address()));
    if (! result.second)
        return false;
    
    m_list.push_back (endpoint);

    return true;
}
Beispiel #2
0
Role
requestRole (Role const& required, HTTP::Port const& port,
             Json::Value const& params, beast::IP::Endpoint const& remoteIp)
{
    Role role (Role::GUEST);
    if (isAdmin(port, params, remoteIp.address ()))
        role = Role::ADMIN;
    if (required == Role::ADMIN && role != required)
        role = Role::FORBID;
    return role;
}
// VFALCO ARGH! returning a single std::string for the entire response?
std::string
ServerHandlerImp::processRequest (std::string const& request,
    beast::IP::Endpoint const& remoteIPAddress)
{
    Json::Value jvRequest;
    {
        Json::Reader reader;
        if ((request.size () > 1000000) ||
            ! reader.parse (request, jvRequest) ||
            jvRequest.isNull () ||
            ! jvRequest.isObject ())
        {
            return createResponse (400, "Unable to parse request");
        }
    }

    auto const role = getConfig ().getAdminRole (jvRequest, remoteIPAddress);

    Resource::Consumer usage;

    if (role == Config::ADMIN)
        usage = m_resourceManager.newAdminEndpoint (remoteIPAddress.to_string());
    else
        usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);

    if (usage.disconnect ())
        return createResponse (503, "Server is overloaded");

    // Parse id now so errors from here on will have the id
    //
    // VFALCO NOTE Except that "id" isn't included in the following errors.
    //
    Json::Value const id = jvRequest ["id"];

    Json::Value const method = jvRequest ["method"];

    if (method.isNull ())
        return createResponse (400, "Null method");

    if (! method.isString ())
        return createResponse (400, "method is not string");

    std::string strMethod = method.asString ();
    if (strMethod.empty())
        return createResponse (400, "method is empty");

    // Parse params
    Json::Value params = jvRequest ["params"];

    if (params.isNull ())
        params = Json::Value (Json::arrayValue);

    else if (!params.isArray ())
        return HTTPReply (400, "params unparseable");

    // VFALCO TODO Shouldn't we handle this earlier?
    //
    if (role == Config::FORBID)
    {
        // VFALCO TODO Needs implementing
        // FIXME Needs implementing
        // XXX This needs rate limiting to prevent brute forcing password.
        return HTTPReply (403, "Forbidden");
    }


    std::string response;
    RPCHandler rpcHandler (m_networkOPs);
    Resource::Charge loadType = Resource::feeReferenceRPC;

    m_journal.debug << "Query: " << strMethod << params;

    Json::Value const result (rpcHandler.doRpcCommand (
        strMethod, params, role, loadType));
    m_journal.debug << "Reply: " << result;

    usage.charge (loadType);

    response = JSONRPCReply (result, Json::Value (), id);

    return createResponse (200, response);
}
Beispiel #4
0
Config::Role Config::getAdminRole (Json::Value const& params, beast::IP::Endpoint const& remoteIp) const
{
    Config::Role role (Config::FORBID);

    bool const bPasswordSupplied =
        params.isMember ("admin_user") ||
        params.isMember ("admin_password");

    bool const bPasswordRequired =
        ! this->RPC_ADMIN_USER.empty () ||
        ! this->RPC_ADMIN_PASSWORD.empty ();

    bool bPasswordWrong;

    if (bPasswordSupplied)
    {
        if (bPasswordRequired)
        {
            // Required, and supplied, check match
            bPasswordWrong =
                (this->RPC_ADMIN_USER !=
                    (params.isMember ("admin_user") ? params["admin_user"].asString () : ""))
                ||
                (this->RPC_ADMIN_PASSWORD !=
                    (params.isMember ("admin_user") ? params["admin_password"].asString () : ""));
        }
        else
        {
            // Not required, but supplied
            bPasswordWrong = false;
        }
    }
    else
    {
        // Required but not supplied, 
        bPasswordWrong = bPasswordRequired;
    }

    // Meets IP restriction for admin.
    beast::IP::Endpoint const remote_addr (remoteIp.at_port (0));
    bool bAdminIP = false;

    for (auto const& allow_addr : RPC_ADMIN_ALLOW)
    {
        if (allow_addr == remote_addr)
        {
            bAdminIP = true;
            break;
        }
    }

    if (bPasswordWrong                          // Wrong
            || (bPasswordSupplied && !bAdminIP))    // Supplied and doesn't meet IP filter.
    {
        role   = Config::FORBID;
    }
    // If supplied, password is correct.
    else
    {
        // Allow admin, if from admin IP and no password is required or it was supplied and correct.
        role = bAdminIP && (!bPasswordRequired || bPasswordSupplied) ? Config::ADMIN : Config::GUEST;
    }

    return role;
}