From 231647d1568cad2ace5fa5cfd509a661d3e4301b Mon Sep 17 00:00:00 2001 From: dangell7 Date: Thu, 19 Jan 2023 09:38:39 -0500 Subject: [PATCH] update rpc auth + verify --- src/ripple/net/impl/RPCCall.cpp | 69 +++++++++++++++++++++--- src/ripple/rpc/handlers/PayChanClaim.cpp | 52 ++++++++++++------ 2 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index eb4906f3a..6b6dabe7d 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -149,6 +149,37 @@ private: } } + // Build an object or string + // { "currency" : "XYZ", "issuer" : "rXYX", "value": 1000 } + // "1000" + static Json::Value + jvParseAmount(std::string const& strAmount) + { + Json::Reader reader; + Json::Value jv; + Json::Value jv1{Json::objectValue}; + if (to_uint64(strAmount)) + return strAmount; + + bool valid_parse = reader.parse(strAmount, jv); + if (valid_parse) + { + if (jv.isObject()) + { + if (jv.isMember(jss::params)) + { + auto const& params = jv[jss::params]; + for (auto i = params.begin(); i != params.end(); ++i) + jv1[i.key().asString()] = *i; + } + jv1[jss::issuer] = jv[jss::issuer]; + jv1[jss::currency] = jv[jss::currency]; + jv1[jss::value] = jv[jss::value]; + } + } + return jv1; + } + static bool validPublicKey( std::string const& strPk, @@ -825,14 +856,24 @@ private: index++; } - if (!jvParams[index].isString() || - !to_uint64(jvParams[index].asString())) - return rpcError(rpcCHANNEL_AMT_MALFORMED); - jvRequest[jss::amount] = jvParams[index]; + { + // validate amount string | json + if (!jvParams[index].isString()) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + Json::Value amountJson = jvParseAmount(jvParams[index].asString()); + if (!amountJson) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + STAmount amount; + if (!amountFromJsonNoThrow(amount, amountJson)) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + jvRequest[jss::amount] = amountJson; + } // If additional parameters are appended, be sure to increment index // here - return jvRequest; } @@ -856,9 +897,21 @@ private: } jvRequest[jss::channel_id] = jvParams[1u].asString(); - if (!jvParams[2u].isString() || !to_uint64(jvParams[2u].asString())) - return rpcError(rpcCHANNEL_AMT_MALFORMED); - jvRequest[jss::amount] = jvParams[2u]; + { + // validate amount string | json + if (!jvParams[2u].isString()) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + Json::Value amountJson = jvParseAmount(jvParams[2u].asString()); + if (!amountJson) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + STAmount amount; + if (!amountFromJsonNoThrow(amount, amountJson)) + return rpcError(rpcCHANNEL_AMT_MALFORMED); + + jvRequest[jss::amount] = amountJson; + } jvRequest[jss::signature] = jvParams[3u].asString(); diff --git a/src/ripple/rpc/handlers/PayChanClaim.cpp b/src/ripple/rpc/handlers/PayChanClaim.cpp index c5b1202fa..730236805 100644 --- a/src/ripple/rpc/handlers/PayChanClaim.cpp +++ b/src/ripple/rpc/handlers/PayChanClaim.cpp @@ -63,17 +63,26 @@ doChannelAuthorize(RPC::JsonContext& context) if (!channelId.parseHex(params[jss::channel_id].asString())) return rpcError(rpcCHANNEL_MALFORMED); - std::optional const optDrops = params[jss::amount].isString() - ? to_uint64(params[jss::amount].asString()) - : std::nullopt; - - if (!optDrops) + STAmount amount; + bool isAmount = amountFromJsonNoThrow(amount, params[jss::amount]); + if (!isAmount) return rpcError(rpcCHANNEL_AMT_MALFORMED); - std::uint64_t const drops = *optDrops; - Serializer msg; - serializePayChanAuthorization(msg, channelId, XRPAmount(drops)); + if (isXRP(amount)) + { + serializePayChanAuthorization(msg, channelId, amount.xrp()); + } + else + { + serializePayChanAuthorization( + msg, + channelId, + amount.iou(), + amount.getCurrency(), + amount.getIssuer() + ); + } try { @@ -124,22 +133,31 @@ doChannelVerify(RPC::JsonContext& context) if (!channelId.parseHex(params[jss::channel_id].asString())) return rpcError(rpcCHANNEL_MALFORMED); - std::optional const optDrops = params[jss::amount].isString() - ? to_uint64(params[jss::amount].asString()) - : std::nullopt; - - if (!optDrops) + STAmount amount; + bool isAmount = amountFromJsonNoThrow(amount, params[jss::amount]); + if (!isAmount) return rpcError(rpcCHANNEL_AMT_MALFORMED); - std::uint64_t const drops = *optDrops; + Serializer msg; + if (isXRP(amount)) + { + serializePayChanAuthorization(msg, channelId, amount.xrp()); + } + else + { + serializePayChanAuthorization( + msg, + channelId, + amount.iou(), + amount.getCurrency(), + amount.getIssuer() + ); + } auto sig = strUnHex(params[jss::signature].asString()); if (!sig || !sig->size()) return rpcError(rpcINVALID_PARAMS); - Serializer msg; - serializePayChanAuthorization(msg, channelId, XRPAmount(drops)); - Json::Value result; result[jss::signature_verified] = verify(*pk, msg.slice(), makeSlice(*sig), /*canonical*/ true);