diff options
author | Sage Weil <sage@redhat.com> | 2018-08-03 22:20:16 +0200 |
---|---|---|
committer | Sage Weil <sage@redhat.com> | 2018-08-13 00:01:05 +0200 |
commit | 6651b498639a45289ca98aaea6d08c7ea2279ce0 (patch) | |
tree | eea45726201de195aa9906db65847036507a69ed /src | |
parent | mds/MDSAuthCaps: pass addr to is_capable (diff) | |
download | ceph-6651b498639a45289ca98aaea6d08c7ea2279ce0.tar.xz ceph-6651b498639a45289ca98aaea6d08c7ea2279ce0.zip |
mds/MDSAuthCaps: parse and enforce network restriction
Signed-off-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/mds/MDSAuthCaps.cc | 32 | ||||
-rw-r--r-- | src/mds/MDSAuthCaps.h | 18 | ||||
-rw-r--r-- | src/mds/MDSRank.cc | 2 | ||||
-rw-r--r-- | src/test/mds/TestMDSAuthCaps.cc | 16 |
4 files changed, 60 insertions, 8 deletions
diff --git a/src/mds/MDSAuthCaps.cc b/src/mds/MDSAuthCaps.cc index 61835928e56..ffa06f60e97 100644 --- a/src/mds/MDSAuthCaps.cc +++ b/src/mds/MDSAuthCaps.cc @@ -23,6 +23,7 @@ #include "common/debug.h" #include "MDSAuthCaps.h" +#include "include/ipaddr.h" #define dout_subsys ceph_subsys_mds @@ -58,6 +59,7 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()> lexeme[lit("\"") >> *(char_ - '"') >> '"'] | lexeme[lit("'") >> *(char_ - '\'') >> '\'']; unquoted_path %= +char_("a-zA-Z0-9_./-"); + network_str %= +char_("/.:a-fA-F0-9]["); // match := [path=<path>] [uid=<uid> [gids=<gid>[,<gid>...]] path %= (spaces >> lit("path") >> lit('=') >> (quoted_path | unquoted_path)); @@ -86,12 +88,14 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()> (lit("r"))[_val = MDSCapSpec(MDSCapSpec::READ)] ); - grant = lit("allow") >> (capspec >> match)[_val = phoenix::construct<MDSCapGrant>(_1, _2)]; + grant = lit("allow") >> (capspec >> match >> + -(spaces >> lit("network") >> spaces >> network_str)) + [_val = phoenix::construct<MDSCapGrant>(_1, _2, _3)]; grants %= (grant % (*lit(' ') >> (lit(';') | lit(',')) >> *lit(' '))); mdscaps = grants [_val = phoenix::construct<MDSAuthCaps>(_1)]; } qi::rule<Iterator> spaces; - qi::rule<Iterator, string()> quoted_path, unquoted_path; + qi::rule<Iterator, string()> quoted_path, unquoted_path, network_str; qi::rule<Iterator, MDSCapSpec()> capspec; qi::rule<Iterator, string()> path; qi::rule<Iterator, uint32_t()> uid; @@ -163,6 +167,12 @@ bool MDSCapMatch::match_path(std::string_view target_path) const return true; } +void MDSCapGrant::parse_network() +{ + network_valid = ::parse_network(network.c_str(), &network_parsed, + &network_prefix); +} + /** * Is the client *potentially* able to access this path? Actual * permission will depend on uids/modes in the full is_capable. @@ -207,6 +217,13 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path, for (std::vector<MDSCapGrant>::const_iterator i = grants.begin(); i != grants.end(); ++i) { + if (i->network.size() && + (!i->network_valid || + !network_contains(i->network_parsed, + i->network_prefix, + addr))) { + continue; + } if (i->match.match(inode_path, caller_uid, caller_gid, caller_gid_list) && i->spec.allows(mask & (MAY_READ|MAY_EXECUTE), mask & MAY_WRITE)) { @@ -287,7 +304,8 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path, void MDSAuthCaps::set_allow_all() { grants.clear(); - grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::ALL), MDSCapMatch())); + grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::ALL), MDSCapMatch(), + {})); } bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err) @@ -295,7 +313,8 @@ bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err) // Special case for legacy caps if (str == "allow") { grants.clear(); - grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::RWPS), MDSCapMatch())); + grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::RWPS), MDSCapMatch(), + {})); return true; } @@ -308,6 +327,7 @@ bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err) if (r && iter == end) { for (auto& grant : grants) { std::sort(grant.match.gids.begin(), grant.match.gids.end()); + grant.parse_network(); } return true; } else { @@ -390,7 +410,9 @@ ostream &operator<<(ostream &out, const MDSCapGrant &grant) if (!grant.match.is_match_all()) { out << " " << grant.match; } - + if (grant.network.size()) { + out << " network " << grant.network; + } return out; } diff --git a/src/mds/MDSAuthCaps.h b/src/mds/MDSAuthCaps.h index 6297a456be6..c21df082137 100644 --- a/src/mds/MDSAuthCaps.h +++ b/src/mds/MDSAuthCaps.h @@ -132,9 +132,23 @@ struct MDSCapGrant { MDSCapSpec spec; MDSCapMatch match; - MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_) - : spec(spec_), match(match_) {} + std::string network; + + entity_addr_t network_parsed; + unsigned network_prefix = 0; + bool network_valid = true; + + MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_, + boost::optional<std::string> n) + : spec(spec_), match(match_) { + if (n) { + network = *n; + parse_network(); + } + } MDSCapGrant() {} + + void parse_network(); }; class MDSAuthCaps diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 1accfeb8508..fb65a117130 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -914,7 +914,7 @@ Session *MDSRank::get_session(Message *m) imported_session->info.auth_name = session->info.auth_name; //assert(session->info.auth_name == imported_session->info.auth_name); assert(session->info.inst == imported_session->info.inst); - imported_session->connection = session->connection; + imported_session->set_connection(session->connection); // send out any queued messages while (!session->preopen_out_queue.empty()) { imported_session->connection->send_message(session->preopen_out_queue.front()); diff --git a/src/test/mds/TestMDSAuthCaps.cc b/src/test/mds/TestMDSAuthCaps.cc index 7b88a7d8787..deaddf51c08 100644 --- a/src/test/mds/TestMDSAuthCaps.cc +++ b/src/test/mds/TestMDSAuthCaps.cc @@ -44,6 +44,8 @@ const char *parse_good[] = { "allow r ; allow * uid=1", "allow r ; allow * uid=1", "allow r uid=1 gids=1,2,3, allow * uid=2", + "allow r network 1.2.3.4/8", + "allow rw path=/foo uid=1 gids=1,2,3 network 2.3.4.5/16", 0 }; @@ -271,3 +273,17 @@ TEST(MDSAuthCaps, OutputParsed) { ASSERT_EQ(test_values[i].output, stringify(cap)); } } + +TEST(MDSAuthCaps, network) { + entity_addr_t a, b, c; + a.parse("10.1.2.3"); + b.parse("192.168.2.3"); + c.parse("192.167.2.3"); + + MDSAuthCaps cap; + ASSERT_TRUE(cap.parse(g_ceph_context, "allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", NULL)); + + ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, a)); + ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, b)); + ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, c)); +} |