mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
DomainID authorization check moved to doApply
This commit is contained in:
@@ -720,6 +720,7 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
.id = keylet.key,
|
.id = keylet.key,
|
||||||
.amount = asset(50)});
|
.amount = asset(50)});
|
||||||
env(tx, ter{tecNO_AUTH});
|
env(tx, ter{tecNO_AUTH});
|
||||||
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -733,6 +734,7 @@ class Vault_test : public beast::unit_test::suite
|
|||||||
.id = keylet.key,
|
.id = keylet.key,
|
||||||
.amount = asset(50)});
|
.amount = asset(50)});
|
||||||
env(tx);
|
env(tx);
|
||||||
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,19 +71,27 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
|
|||||||
if (isFrozen(ctx.view, account, share))
|
if (isFrozen(ctx.view, account, share))
|
||||||
return tecFROZEN;
|
return tecFROZEN;
|
||||||
|
|
||||||
if (vault->getFlags() == tfVaultPrivate && account != vault->at(sfOwner))
|
if ((vault->getFlags() & tfVaultPrivate) && account != vault->at(sfOwner))
|
||||||
{
|
{
|
||||||
auto const err = requireAuth(
|
// The authorization check below is based on DomainID stored in
|
||||||
ctx.view, MPTIssue(vault->at(sfMPTokenIssuanceID)), account);
|
// MPTokenIssuance. Had the vault shares been a regular MPToken, we
|
||||||
return err;
|
// would allow authorization granted by the issuer explicitly, but Vault
|
||||||
|
// does not have an MPT issuer (instead it uses pseudo-account, which is
|
||||||
// The above will perform authorization check based on DomainID stored
|
// blackholed and cannot create any transactions).
|
||||||
// in MPTokenIssuance. Had this been a regular MPToken, it would also
|
|
||||||
// allow use of authorization granted by the issuer explicitly, but
|
|
||||||
// Vault does not have an MPT issuer (instead it uses pseudo-account).
|
|
||||||
//
|
//
|
||||||
// If we passed the above check then we also need to do similar check
|
// We also need to do similar check inside doApply(), in order to remove
|
||||||
// inside doApply(), in order to check for expired credentials.
|
// expired credentials and/or adjust authorization flag on tokens owned
|
||||||
|
// by DomainID (i.e. with lsfMPTDomainCheck flag). This is why we
|
||||||
|
// suppress authorization errors if domainId is set.
|
||||||
|
uint256 domainId = beast::zero;
|
||||||
|
auto const err = requireAuth(
|
||||||
|
ctx.view,
|
||||||
|
MPTIssue(vault->at(sfMPTokenIssuanceID)),
|
||||||
|
account,
|
||||||
|
&domainId);
|
||||||
|
|
||||||
|
if (domainId == beast::zero)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
@@ -120,7 +128,7 @@ VaultDeposit::doApply()
|
|||||||
|
|
||||||
MPTIssue const mptIssue(mptIssuanceID);
|
MPTIssue const mptIssue(mptIssuanceID);
|
||||||
// Note, vault owner is always authorized
|
// Note, vault owner is always authorized
|
||||||
if (account_ != vault->at(sfOwner) && (vault->getFlags() & tfVaultPrivate))
|
if ((vault->getFlags() & tfVaultPrivate) && account_ != vault->at(sfOwner))
|
||||||
{
|
{
|
||||||
if (auto const err = enforceMPTokenAuthorization(
|
if (auto const err = enforceMPTokenAuthorization(
|
||||||
ctx_.view(), mptIssue, account_, mPriorBalance, j_);
|
ctx_.view(), mptIssue, account_, mPriorBalance, j_);
|
||||||
|
|||||||
@@ -654,7 +654,8 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account);
|
|||||||
requireAuth(
|
requireAuth(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
MPTIssue const& mptIssue,
|
MPTIssue const& mptIssue,
|
||||||
AccountID const& account);
|
AccountID const& account,
|
||||||
|
uint256* domainId = nullptr);
|
||||||
|
|
||||||
/** Check if the account lacks required authorization.
|
/** Check if the account lacks required authorization.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2183,7 +2183,8 @@ TER
|
|||||||
requireAuth(
|
requireAuth(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
MPTIssue const& mptIssue,
|
MPTIssue const& mptIssue,
|
||||||
AccountID const& account)
|
AccountID const& account,
|
||||||
|
uint256* domainId)
|
||||||
{
|
{
|
||||||
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
|
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
|
||||||
auto const sleIssuance = view.read(mptID);
|
auto const sleIssuance = view.read(mptID);
|
||||||
@@ -2220,7 +2221,12 @@ requireAuth(
|
|||||||
if (auto const err =
|
if (auto const err =
|
||||||
credentials::validDomain(view, *maybeDomainID, account);
|
credentials::validDomain(view, *maybeDomainID, account);
|
||||||
!isTesSuccess(err))
|
!isTesSuccess(err))
|
||||||
|
{
|
||||||
|
if (err != tecINVALID_DOMAIN && domainId != nullptr)
|
||||||
|
(*domainId) = *maybeDomainID;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// We are authorized by permissioned domain.
|
// We are authorized by permissioned domain.
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
@@ -2237,16 +2243,17 @@ enforceMPTokenAuthorization(
|
|||||||
auto const mptIssuanceID = mptIssue.getMptID();
|
auto const mptIssuanceID = mptIssue.getMptID();
|
||||||
auto const sleIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
|
auto const sleIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
|
||||||
if (!sleIssuance)
|
if (!sleIssuance)
|
||||||
return tefINTERNAL; // Should have called requireAuth earlier
|
return tefINTERNAL;
|
||||||
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth,
|
sleIssuance->getFlags() & lsfMPTRequireAuth,
|
||||||
"ripple::verifyAuth : MPTokenIssuance requires authorization");
|
"ripple::verifyAuth : MPTokenIssuance requires authorization");
|
||||||
|
|
||||||
if (account == sleIssuance->at(sfIssuer))
|
if (account == sleIssuance->at(sfIssuer))
|
||||||
return tesSUCCESS; // Won't create MPToken for the token issuer
|
return tesSUCCESS; // Won't create MPToken for the token issuer
|
||||||
|
|
||||||
auto sleToken = view.read(keylet::mptoken(mptIssuanceID, account));
|
auto const keylet = keylet::mptoken(mptIssuanceID, account);
|
||||||
|
auto sleToken = view.read(keylet);
|
||||||
bool const domainOwned =
|
bool const domainOwned =
|
||||||
(sleToken && (sleToken->getFlags() & lsfMPTDomainCheck));
|
(sleToken && (sleToken->getFlags() & lsfMPTDomainCheck));
|
||||||
|
|
||||||
@@ -2282,16 +2289,15 @@ enforceMPTokenAuthorization(
|
|||||||
{
|
{
|
||||||
// We found an MPToken with lsfMPTDomainCheck flag, but the account is
|
// We found an MPToken with lsfMPTDomainCheck flag, but the account is
|
||||||
// no longer authorized.
|
// no longer authorized.
|
||||||
if (sleToken->getFieldU32(sfFlags) & lsfMPTAuthorized)
|
if (sleToken->getFlags() & lsfMPTAuthorized)
|
||||||
{
|
{
|
||||||
// Must reset lsfMPTAuthorized, no current credentials
|
// Must reset lsfMPTAuthorized, no current credentials
|
||||||
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
|
auto sleMpt = view.peek(keylet);
|
||||||
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null bad MPToken");
|
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null bad MPToken");
|
||||||
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
|
sleMpt->clearFlag(lsfMPTAuthorized);
|
||||||
sleMpt->setFieldU32(sfFlags, flags & ~lsfMPTAuthorized);
|
|
||||||
view.update(sleMpt);
|
view.update(sleMpt);
|
||||||
|
|
||||||
sleToken = nullptr; // return tecNO_AUTH at the end of function
|
sleToken = sleMpt; // without lsfMPTAuthorized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!authorizedByDomain)
|
else if (!authorizedByDomain)
|
||||||
@@ -2310,10 +2316,9 @@ enforceMPTokenAuthorization(
|
|||||||
if ((sleToken->getFlags() & lsfMPTAuthorized) == 0)
|
if ((sleToken->getFlags() & lsfMPTAuthorized) == 0)
|
||||||
{
|
{
|
||||||
// Must set lsfMPTAuthorized, we found new credentials
|
// Must set lsfMPTAuthorized, we found new credentials
|
||||||
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
|
auto sleMpt = view.peek(keylet);
|
||||||
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null good MPToken");
|
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null good MPToken");
|
||||||
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
|
sleMpt->setFlag(lsfMPTAuthorized);
|
||||||
sleMpt->setFieldU32(sfFlags, flags | lsfMPTAuthorized);
|
|
||||||
view.update(sleMpt);
|
view.update(sleMpt);
|
||||||
|
|
||||||
sleToken = sleMpt; // with lsfMPTAuthorized
|
sleToken = sleMpt; // with lsfMPTAuthorized
|
||||||
@@ -2334,11 +2339,9 @@ enforceMPTokenAuthorization(
|
|||||||
!isTesSuccess(err))
|
!isTesSuccess(err))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
|
auto sleMpt = view.peek(keylet);
|
||||||
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null new MPToken");
|
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null new MPToken");
|
||||||
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
|
sleMpt->setFlag(lsfMPTDomainCheck | lsfMPTAuthorized);
|
||||||
sleMpt->setFieldU32(
|
|
||||||
sfFlags, flags | lsfMPTDomainCheck | lsfMPTAuthorized);
|
|
||||||
view.update(sleMpt);
|
view.update(sleMpt);
|
||||||
|
|
||||||
sleToken = sleMpt; // with lsfMPTAuthorized
|
sleToken = sleMpt; // with lsfMPTAuthorized
|
||||||
|
|||||||
Reference in New Issue
Block a user