Skip to content

Commit

Permalink
Add referrer checks for access status
Browse files Browse the repository at this point in the history
  • Loading branch information
balsoft committed Feb 10, 2024
1 parent c5f8a40 commit effa88f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 4 deletions.
28 changes: 25 additions & 3 deletions src/libstore/local-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -858,11 +858,11 @@ StorePathSet LocalStore::queryAllValidPaths()
}


void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers)
void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers, bool accessCheck)
{
auto useQueryReferrers(state.stmts->QueryReferrers.use()(printStorePath(path)));

if (!canAccess(path)) throw AccessDenied("Access Denied");
if (accessCheck && !canAccess(path)) throw AccessDenied("Access Denied");

while (useQueryReferrers.next())
referrers.insert(parseStorePath(useQueryReferrers.getStr(0)));
Expand Down Expand Up @@ -1086,7 +1086,7 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc

auto info = promise.get_future().get();

if (info){
if (info) {
for (auto reference : info->references) {
if (reference == storePath) continue;
auto otherStatus = getCurrentAccessStatus(printStorePath(reference));
Expand All @@ -1103,6 +1103,28 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc
}
}
}

StorePathSet referrers;
retrySQLite<void>([&]() {
auto state(_state.lock());
queryReferrers(*state, storePath, referrers, false);
});

for (auto referrer : referrers) {
if (referrer == storePath) continue;
auto otherStatus = getCurrentAccessStatus(printStorePath(referrer));
if (!status.isProtected) continue;
if (!otherStatus.isProtected)
throw AccessDenied("can not make %s protected because it is referenced by a non-protected path %s", path, printStorePath(referrer));
std::vector<AccessControlEntity> difference;
std::set_difference(otherStatus.entities.begin(), otherStatus.entities.end(), status.entities.begin(), status.entities.end(),std::inserter(difference, difference.begin()));

if (! difference.empty()) {
std::string entities;
for (auto entity : difference) entities += ACL::printTag(entity) + ", ";
throw AccessDenied("can not deny %s access to %s because it is referenced by a path %s to which they do not have access", entities.substr(0, entities.size()-2), path, printStorePath(referrer));
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libstore/local-store.hh
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ private:

// Internal versions that are not wrapped in retry_sqlite.
bool isValidPath_(State & state, const StorePath & path);
void queryReferrers(State & state, const StorePath & path, StorePathSet & referrers);
void queryReferrers(State & state, const StorePath & path, StorePathSet & referrers, bool accessCheck = true);

/**
* Add signatures to a ValidPathInfo or Realisation using the secret keys
Expand Down

0 comments on commit effa88f

Please sign in to comment.