diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index f81d9b0c7..acd8aaca4 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -363,6 +363,7 @@ int PathRequest::parseJson (Json::Value const& jvParams) Currency srcCurrencyID; if (! c.isObject() || ! c.isMember(jss::currency) || + ! c[jss::currency].isString() || ! to_currency(srcCurrencyID, c[jss::currency].asString())) { jvStatus = rpcError (rpcSRC_CUR_MALFORMED); diff --git a/src/ripple/json/impl/json_assert.h b/src/ripple/json/impl/json_assert.h index ab124d42e..fc8ab335a 100644 --- a/src/ripple/json/impl/json_assert.h +++ b/src/ripple/json/impl/json_assert.h @@ -20,8 +20,10 @@ #ifndef RIPPLE_JSON_JSON_ASSERT_H_INCLUDED #define RIPPLE_JSON_JSON_ASSERT_H_INCLUDED +#include "ripple/json/json_errors.h" + #define JSON_ASSERT_UNREACHABLE assert( false ) #define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw -#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) ripple::Throw ( message ); +#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) ripple::Throw ( message ); #endif diff --git a/src/ripple/json/json_errors.h b/src/ripple/json/json_errors.h new file mode 100644 index 000000000..558d99e3a --- /dev/null +++ b/src/ripple/json/json_errors.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_JSON_JSON_ERRORS_H_INCLUDED +#define RIPPLE_JSON_JSON_ERRORS_H_INCLUDED + +#include + +namespace Json +{ + +struct error : std::runtime_error +{ + using std::runtime_error::runtime_error; +}; + +} // namespace Json + + +#endif // JSON_FORWARDS_H_INCLUDED diff --git a/src/ripple/rpc/impl/ServerHandlerImp.cpp b/src/ripple/rpc/impl/ServerHandlerImp.cpp index a7bcaee46..52ec11bd7 100644 --- a/src/ripple/rpc/impl/ServerHandlerImp.cpp +++ b/src/ripple/rpc/impl/ServerHandlerImp.cpp @@ -416,56 +416,68 @@ ServerHandlerImp::processSession( // Requests without "command" are invalid. Json::Value jr(Json::objectValue); - if ((!jv.isMember(jss::command) && !jv.isMember(jss::method)) || - (jv.isMember(jss::command) && jv.isMember(jss::method) && - jv[jss::command].asString() != jv[jss::method].asString())) - { - jr[jss::type] = jss::response; - jr[jss::status] = jss::error; - jr[jss::error] = jss::missingCommand; - jr[jss::request] = jv; - if (jv.isMember (jss::id)) - jr[jss::id] = jv[jss::id]; - if (jv.isMember(jss::jsonrpc)) - jr[jss::jsonrpc] = jv[jss::jsonrpc]; - if (jv.isMember(jss::ripplerpc)) - jr[jss::ripplerpc] = jv[jss::ripplerpc]; - - is->getConsumer().charge(Resource::feeInvalidRPC); - return jr; - } - Resource::Charge loadType = Resource::feeReferenceRPC; - auto required = RPC::roleRequired(jv.isMember(jss::command) ? - jv[jss::command].asString() : - jv[jss::method].asString()); - auto role = requestRole( - required, - session->port(), - jv, - beast::IP::from_asio(session->remote_endpoint().address()), - is->user()); - if (Role::FORBID == role) + try { - loadType = Resource::feeInvalidRPC; - jr[jss::result] = rpcError (rpcFORBIDDEN); - } - else - { - RPC::Context context{ - app_.journal("RPCHandler"), + if ((!jv.isMember(jss::command) && !jv.isMember(jss::method)) || + (jv.isMember(jss::command) && !jv[jss::command].isString()) || + (jv.isMember(jss::method) && !jv[jss::method].isString()) || + (jv.isMember(jss::command) && jv.isMember(jss::method) && + jv[jss::command].asString() != jv[jss::method].asString())) + { + jr[jss::type] = jss::response; + jr[jss::status] = jss::error; + jr[jss::error] = jss::missingCommand; + jr[jss::request] = jv; + if (jv.isMember (jss::id)) + jr[jss::id] = jv[jss::id]; + if (jv.isMember(jss::jsonrpc)) + jr[jss::jsonrpc] = jv[jss::jsonrpc]; + if (jv.isMember(jss::ripplerpc)) + jr[jss::ripplerpc] = jv[jss::ripplerpc]; + + is->getConsumer().charge(Resource::feeInvalidRPC); + return jr; + } + + auto required = RPC::roleRequired(jv.isMember(jss::command) ? + jv[jss::command].asString() : + jv[jss::method].asString()); + auto role = requestRole( + required, + session->port(), jv, - app_, - loadType, - app_.getOPs(), - app_.getLedgerMaster(), - is->getConsumer(), - role, - coro, - is, - {is->user(), is->forwarded_for()} - }; - RPC::doCommand(context, jr[jss::result]); + beast::IP::from_asio(session->remote_endpoint().address()), + is->user()); + if (Role::FORBID == role) + { + loadType = Resource::feeInvalidRPC; + jr[jss::result] = rpcError (rpcFORBIDDEN); + } + else + { + RPC::Context context{ + app_.journal("RPCHandler"), + jv, + app_, + loadType, + app_.getOPs(), + app_.getLedgerMaster(), + is->getConsumer(), + role, + coro, + is, + {is->user(), is->forwarded_for()} + }; + RPC::doCommand(context, jr[jss::result]); + } + } + catch (std::exception const& ex) + { + jr[jss::result] = RPC::make_error(rpcINTERNAL); + JLOG(m_journal.error()) + << "Exception while processing WS: " << ex.what() << "\n" + << "Input JSON: " << Json::Compact{Json::Value{jv}}; } is->getConsumer().charge(loadType); @@ -482,7 +494,6 @@ ServerHandlerImp::processSession( jr = jr[jss::result]; jr[jss::status] = jss::error; jr[jss::request] = jv; - } else { @@ -490,6 +501,7 @@ ServerHandlerImp::processSession( // For testing resource limits on this connection. if (is->getConsumer().isUnlimited() && + jv[jss::command].isString() && jv[jss::command].asString() == "ping") jr[jss::unlimited] = true; }