diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index d716ca21315..00000000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt -y update -RUN apt -y upgrade -RUN apt -y install build-essential g++ git libbz2-dev wget python-dev -RUN apt -y install cmake flex bison graphviz graphviz-dev libicu-dev -RUN apt -y install jarwrapper java-common - -RUN cd /tmp -ENV CM_INSTALLER=cmake-3.10.0-rc3-Linux-x86_64.sh -ENV CM_VER_DIR=/opt/local/cmake-3.10.0 -RUN cd /tmp && wget https://cmake.org/files/v3.10/$CM_INSTALLER && chmod a+x $CM_INSTALLER -RUN mkdir -p $CM_VER_DIR -RUN ln -s $CM_VER_DIR /opt/local/cmake -RUN /tmp/$CM_INSTALLER --prefix=$CM_VER_DIR --exclude-subdir -RUN rm -f /tmp/$CM_INSTALLER - -RUN cd /tmp && wget https://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.14.src.tar.gz -RUN cd /tmp && tar xvf doxygen-1.8.14.src.tar.gz -RUN mkdir -p /tmp/doxygen-1.8.14/build -RUN cd /tmp/doxygen-1.8.14/build && /opt/local/cmake/bin/cmake -G "Unix Makefiles" .. -RUN cd /tmp/doxygen-1.8.14/build && make -j2 -RUN cd /tmp/doxygen-1.8.14/build && make install -RUN rm -f /tmp/doxygen-1.8.14.src.tar.gz -RUN rm -rf /tmp/doxygen-1.8.14 - -RUN mkdir -p /opt/plantuml -RUN wget -O /opt/plantuml/plantuml.jar http://sourceforge.net/projects/plantuml/files/plantuml.jar/download -ENV DOXYGEN_PLANTUML_JAR_PATH=/opt/plantuml/plantuml.jar - -ENV DOXYGEN_OUTPUT_DIRECTORY=html -CMD cd /opt/rippled && doxygen docs/Doxyfile diff --git a/src/ripple/app/tx/impl/XChainBridge.cpp b/src/ripple/app/tx/impl/XChainBridge.cpp index c6ee250e819..59450113d2b 100644 --- a/src/ripple/app/tx/impl/XChainBridge.cpp +++ b/src/ripple/app/tx/impl/XChainBridge.cpp @@ -1211,6 +1211,9 @@ attestationPreflight(PreflightContext const& ctx) if (ctx.tx.getFlags() & tfUniversalMask) return temINVALID_FLAG; + if (!publicKeyType(ctx.tx[sfPublicKey])) + return temMALFORMED; + auto const att = toClaim(ctx.tx); if (!att) return temMALFORMED; diff --git a/src/ripple/net/RPCCall.h b/src/ripple/net/RPCCall.h index a97c6177109..600fad28e58 100644 --- a/src/ripple/net/RPCCall.h +++ b/src/ripple/net/RPCCall.h @@ -65,18 +65,22 @@ fromNetwork( std::unordered_map headers = {}); } // namespace RPCCall -/** Given a rippled command line, return the corresponding JSON. - */ Json::Value -cmdLineToJSONRPC(std::vector const& args, beast::Journal j); +rpcCmdToJson( + std::vector const& args, + Json::Value& retParams, + unsigned int apiVersion, + beast::Journal j); /** Internal invocation of RPC client. + * Used by both rippled command line as well as rippled unit tests */ std::pair rpcClient( std::vector const& args, Config const& config, Logs& logs, + unsigned int apiVersion, std::unordered_map const& headers = {}); } // namespace ripple diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index b52545960cc..f4428a3f000 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -1472,10 +1472,11 @@ struct RPCCallImp //------------------------------------------------------------------------------ // Used internally by rpcClient. -static Json::Value -rpcCmdLineToJson( +Json::Value +rpcCmdToJson( std::vector const& args, Json::Value& retParams, + unsigned int apiVersion, beast::Journal j) { Json::Value jvRequest(Json::objectValue); @@ -1493,11 +1494,11 @@ rpcCmdLineToJson( jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true); - auto insert_api_version = [](Json::Value& jr) { + auto insert_api_version = [apiVersion](Json::Value& jr) { if (jr.isObject() && !jr.isMember(jss::error) && !jr.isMember(jss::api_version)) { - jr[jss::api_version] = RPC::apiMaximumSupportedVersion; + jr[jss::api_version] = apiVersion; } }; @@ -1510,35 +1511,6 @@ rpcCmdLineToJson( return jvRequest; } -Json::Value -cmdLineToJSONRPC(std::vector const& args, beast::Journal j) -{ - Json::Value jv = Json::Value(Json::objectValue); - auto const paramsObj = rpcCmdLineToJson(args, jv, j); - - // Re-use jv to return our formatted result. - jv.clear(); - - // Allow parser to rewrite method. - jv[jss::method] = paramsObj.isMember(jss::method) - ? paramsObj[jss::method].asString() - : args[0]; - - // If paramsObj is not empty, put it in a [params] array. - if (paramsObj.begin() != paramsObj.end()) - { - auto& paramsArray = Json::setArray(jv, jss::params); - paramsArray.append(paramsObj); - } - if (paramsObj.isMember(jss::jsonrpc)) - jv[jss::jsonrpc] = paramsObj[jss::jsonrpc]; - if (paramsObj.isMember(jss::ripplerpc)) - jv[jss::ripplerpc] = paramsObj[jss::ripplerpc]; - if (paramsObj.isMember(jss::id)) - jv[jss::id] = paramsObj[jss::id]; - return jv; -} - //------------------------------------------------------------------------------ std::pair @@ -1546,6 +1518,7 @@ rpcClient( std::vector const& args, Config const& config, Logs& logs, + unsigned int apiVersion, std::unordered_map const& headers) { static_assert( @@ -1561,7 +1534,8 @@ rpcClient( try { Json::Value jvRpc = Json::Value(Json::objectValue); - jvRequest = rpcCmdLineToJson(args, jvRpc, logs.journal("RPCParser")); + jvRequest = + rpcCmdToJson(args, jvRpc, apiVersion, logs.journal("RPCParser")); if (jvRequest.isMember(jss::error)) { @@ -1698,7 +1672,8 @@ fromCommandLine( const std::vector& vCmd, Logs& logs) { - auto const result = rpcClient(vCmd, config, logs); + auto const result = + rpcClient(vCmd, config, logs, RPC::apiMaximumSupportedVersion); std::cout << result.second.toStyledString(); diff --git a/src/test/app/XChain_test.cpp b/src/test/app/XChain_test.cpp index 9b8aaf397dc..e6e193adf10 100644 --- a/src/test/app/XChain_test.cpp +++ b/src/test/app/XChain_test.cpp @@ -4209,6 +4209,73 @@ struct XChain_test : public beast::unit_test::suite, } } + void + testBadPublicKey() + { + using namespace jtx; + + testcase("Bad attestations"); + { + // Create a bridge and add an attestation with a bad public key + XEnv scEnv(*this, true); + std::uint32_t const claimID = 1; + std::optional dst{scBob}; + auto const amt = XRP(1000); + scEnv.tx(create_bridge(Account::master, jvb)) + .tx(jtx::signers(Account::master, quorum, signers)) + .close(); + scEnv.tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice)) + .close(); + auto jvAtt = claim_attestation( + scAttester, + jvb, + mcAlice, + amt, + payees[UT_XCHAIN_DEFAULT_QUORUM], + true, + claimID, + dst, + signers[UT_XCHAIN_DEFAULT_QUORUM]); + { + // Change to an invalid keytype + auto k = jvAtt["PublicKey"].asString(); + k.at(1) = '9'; + jvAtt["PublicKey"] = k; + } + scEnv.tx(jvAtt, ter(temMALFORMED)).close(); + } + { + // Create a bridge and add an create account attestation with a bad + // public key + XEnv scEnv(*this, true); + std::uint32_t const createCount = 1; + Account dst{scBob}; + auto const amt = XRP(1000); + auto const rewardAmt = XRP(1); + scEnv.tx(create_bridge(Account::master, jvb)) + .tx(jtx::signers(Account::master, quorum, signers)) + .close(); + auto jvAtt = create_account_attestation( + scAttester, + jvb, + mcAlice, + amt, + rewardAmt, + payees[UT_XCHAIN_DEFAULT_QUORUM], + true, + createCount, + dst, + signers[UT_XCHAIN_DEFAULT_QUORUM]); + { + // Change to an invalid keytype + auto k = jvAtt["PublicKey"].asString(); + k.at(1) = '9'; + jvAtt["PublicKey"] = k; + } + scEnv.tx(jvAtt, ter(temMALFORMED)).close(); + } + } + void run() override { @@ -4226,6 +4293,7 @@ struct XChain_test : public beast::unit_test::suite, testXChainCreateAccount(); testFeeDipsIntoReserve(); testXChainDeleteDoor(); + testBadPublicKey(); } }; diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index 5e1aaa166f0..3467a42cbbb 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -463,7 +463,13 @@ Env::do_rpc( std::vector const& args, std::unordered_map const& headers) { - return rpcClient(args, app().config(), app().logs(), headers).second; + return rpcClient( + args, + app().config(), + app().logs(), + RPC::apiMaximumSupportedVersion, + headers) + .second; } void diff --git a/src/test/jtx/impl/utility.cpp b/src/test/jtx/impl/utility.cpp index a2acdd87b4d..196fd9258d7 100644 --- a/src/test/jtx/impl/utility.cpp +++ b/src/test/jtx/impl/utility.cpp @@ -18,6 +18,8 @@ //============================================================================== #include +#include +#include #include #include #include @@ -73,6 +75,38 @@ fill_seq(Json::Value& jv, ReadView const& view) jv[jss::Sequence] = ar->getFieldU32(sfSequence); } +Json::Value +cmdToJSONRPC( + std::vector const& args, + beast::Journal j, + unsigned int apiVersion) +{ + Json::Value jv = Json::Value(Json::objectValue); + auto const paramsObj = rpcCmdToJson(args, jv, apiVersion, j); + + // Re-use jv to return our formatted result. + jv.clear(); + + // Allow parser to rewrite method. + jv[jss::method] = paramsObj.isMember(jss::method) + ? paramsObj[jss::method].asString() + : args[0]; + + // If paramsObj is not empty, put it in a [params] array. + if (paramsObj.begin() != paramsObj.end()) + { + auto& paramsArray = Json::setArray(jv, jss::params); + paramsArray.append(paramsObj); + } + if (paramsObj.isMember(jss::jsonrpc)) + jv[jss::jsonrpc] = paramsObj[jss::jsonrpc]; + if (paramsObj.isMember(jss::ripplerpc)) + jv[jss::ripplerpc] = paramsObj[jss::ripplerpc]; + if (paramsObj.isMember(jss::id)) + jv[jss::id] = paramsObj[jss::id]; + return jv; +} + } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/utility.h b/src/test/jtx/utility.h index cb013a68435..7bc9fbaa817 100644 --- a/src/test/jtx/utility.h +++ b/src/test/jtx/utility.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,13 @@ fill_fee(Json::Value& jv, ReadView const& view); void fill_seq(Json::Value& jv, ReadView const& view); +/** Given a rippled unit test rpc command, return the corresponding JSON. */ +Json::Value +cmdToJSONRPC( + std::vector const& args, + beast::Journal j, + unsigned int apiVersion = RPC::apiMaximumSupportedVersion); + } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 5385ba768e6..ce270184a26 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -6442,7 +6443,7 @@ class RPCCall_test : public beast::unit_test::suite Json::Value got; try { - got = cmdLineToJSONRPC(args, env.journal); + got = jtx::cmdToJSONRPC(args, env.journal); } catch (std::bad_cast const&) {