Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preventing imeta mod bypass (4-3-stable) #74

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions packaging/test_rule_engine_plugin_metadata_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,32 @@ def test_plugin_cannot_be_bypassed_with_addw__issue_40(self):
# Clean up.
self.rods.assert_icommand(['imeta', 'rm', '-C', root_coll, self.metadata_guard_attribute_name(), json_config])

def test_plugin_cannot_be_bypassed_via_imeta_mod__issue_58(self):
config = IrodsConfig()

# Set JSON configuration for the root collection.
root_coll = os.path.join('/', self.admin.zone_name)
json_config = json.dumps({
'prefixes': ['irods::'],
'admin_only': True
})
self.rods.assert_icommand(['imeta', 'set', '-C', root_coll, self.metadata_guard_attribute_name(), json_config])

try:
with lib.file_backed_up(config.server_config_path):
self.enable_rule_engine_plugin(config)

self.user.assert_icommand(['imeta', 'add', '-C', self.user.session_collection, 'unprotected::issue58', 'v'])
self.user.assert_icommand(['imeta', 'mod', '-C', self.user.session_collection, 'unprotected::issue58', 'v', 'n:irods::issue58'], 'STDERR', ['CAT_INSUFFICIENT_PRIVILEGE_LEVEL'])

# Same as above, but with units
self.user.assert_icommand(['imeta', 'add', '-C', self.user.session_collection, 'unprotected::withunits', 'v', 'u'])
self.user.assert_icommand(['imeta', 'mod', '-C', self.user.session_collection, 'unprotected::withunits', 'v', 'u', 'n:irods::withunits'], 'STDERR', ['CAT_INSUFFICIENT_PRIVILEGE_LEVEL'])
self.user.assert_icommand(['imeta', 'mod', '-C', self.user.session_collection, 'unprotected::withunits', 'v', 'n:irods::withunits', 'u'], 'STDERR', ['CAT_INSUFFICIENT_PRIVILEGE_LEVEL'])
finally:
# Clean up.
self.rods.assert_icommand(['imeta', 'rm', '-C', root_coll, self.metadata_guard_attribute_name(), json_config])

#
# Utility Functions
#
Expand Down
17 changes: 16 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,25 @@ namespace
// {"type": "user", "name": "jane#otherZone"}
// ]
// }

// Per the API, any of arg5 to arg8 is eligible to be the new attribute
// (depending on which one starts with "n:")
// However, only one will be considered (multiples will throw CAT_INVALID_ARGUMENT)
// Therefore, find the first one that starts with "n:"
const auto candidates = {input->arg5, input->arg6, input->arg7, input->arg8};
const auto mod_attr_ptr = std::find_if(std::begin(candidates), std::end(candidates), [](char* arg) {
return arg && boost::starts_with(arg, "n:");
});
const char* mod_attr_name = nullptr;
if (mod_attr_ptr != std::end(candidates)) {
mod_attr_name = (*mod_attr_ptr) + 2;
}
for (auto&& prefix : config->at("prefixes")) {
// If the metadata attribute starts with the prefix, then verify that the user
// can modify the metadata attribute.
if (boost::starts_with(input->arg3, prefix.get_ref<const std::string&>())) {
if (boost::starts_with(input->arg3, prefix.get_ref<const std::string&>()) ||
(mod_attr_name && boost::starts_with(mod_attr_name, prefix.get_ref<const std::string&>())))
{
// The "admin_only" flag supersedes the "editors" configuration option.
const auto& admin_iter = config->find("admin_only");
if (admin_iter != config->cend() && admin_iter->get<bool>()) {
Expand Down
Loading