X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmds%2FMDSAuthCaps.cc;fp=src%2Fceph%2Fsrc%2Fmds%2FMDSAuthCaps.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=e22e449cd42218a5a1e8946064f5b0cd30abc19f;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/mds/MDSAuthCaps.cc b/src/ceph/src/mds/MDSAuthCaps.cc deleted file mode 100644 index e22e449..0000000 --- a/src/ceph/src/mds/MDSAuthCaps.cc +++ /dev/null @@ -1,391 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2014 Red Hat - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - - -#include -#include - -#include -#include -#include - -#include "common/debug.h" -#include "MDSAuthCaps.h" - -#define dout_subsys ceph_subsys_mds - -#undef dout_prefix -#define dout_prefix *_dout << "MDSAuthCap " - -using std::ostream; -using std::string; -namespace qi = boost::spirit::qi; -namespace ascii = boost::spirit::ascii; -namespace phoenix = boost::phoenix; - -template -struct MDSCapParser : qi::grammar -{ - MDSCapParser() : MDSCapParser::base_type(mdscaps) - { - using qi::char_; - using qi::int_; - using qi::uint_; - using qi::lexeme; - using qi::alnum; - using qi::_val; - using qi::_1; - using qi::_2; - using qi::_3; - using qi::eps; - using qi::lit; - - spaces = +(lit(' ') | lit('\n') | lit('\t')); - - quoted_path %= - lexeme[lit("\"") >> *(char_ - '"') >> '"'] | - lexeme[lit("'") >> *(char_ - '\'') >> '\'']; - unquoted_path %= +char_("a-zA-Z0-9_./-"); - - // match := [path=] [uid= [gids=[,...]] - path %= (spaces >> lit("path") >> lit('=') >> (quoted_path | unquoted_path)); - uid %= (spaces >> lit("uid") >> lit('=') >> uint_); - uintlist %= (uint_ % lit(',')); - gidlist %= -(spaces >> lit("gids") >> lit('=') >> uintlist); - match = -( - (uid >> gidlist)[_val = phoenix::construct(_1, _2)] | - (path >> uid >> gidlist)[_val = phoenix::construct(_1, _2, _3)] | - (path)[_val = phoenix::construct(_1)]); - - // capspec = * | r[w] - capspec = spaces >> ( - lit("*")[_val = MDSCapSpec(true, true, true, true)] - | - (lit("rwp"))[_val = MDSCapSpec(true, true, false, true)] - | - (lit("rw"))[_val = MDSCapSpec(true, true, false, false)] - | - (lit("r"))[_val = MDSCapSpec(true, false, false, false)] - ); - - grant = lit("allow") >> (capspec >> match)[_val = phoenix::construct(_1, _2)]; - grants %= (grant % (*lit(' ') >> (lit(';') | lit(',')) >> *lit(' '))); - mdscaps = grants [_val = phoenix::construct(_1)]; - } - qi::rule spaces; - qi::rule quoted_path, unquoted_path; - qi::rule capspec; - qi::rule path; - qi::rule uid; - qi::rule() > uintlist; - qi::rule() > gidlist; - qi::rule match; - qi::rule grant; - qi::rule()> grants; - qi::rule mdscaps; -}; - -void MDSCapMatch::normalize_path() -{ - // drop any leading / - while (path.length() && path[0] == '/') { - path = path.substr(1); - } - - // drop dup // - // drop . - // drop .. -} - -bool MDSCapMatch::match(const std::string &target_path, - const int caller_uid, - const int caller_gid, - const vector *caller_gid_list) const -{ - if (uid != MDS_AUTH_UID_ANY) { - if (uid != caller_uid) - return false; - bool gid_matched = false; - if (std::find(gids.begin(), gids.end(), caller_gid) != gids.end()) - gid_matched = true; - if (caller_gid_list) { - for (auto i = caller_gid_list->begin(); i != caller_gid_list->end(); ++i) { - if (std::find(gids.begin(), gids.end(), *i) != gids.end()) { - gid_matched = true; - break; - } - } - } - if (!gid_matched) - return false; - } - - if (!match_path(target_path)) { - return false; - } - - return true; -} - -bool MDSCapMatch::match_path(const std::string &target_path) const -{ - if (path.length()) { - if (target_path.find(path) != 0) - return false; - // if path doesn't already have a trailing /, make sure the target - // does so that path=/foo doesn't match target_path=/food - if (target_path.length() > path.length() && - path[path.length()-1] != '/' && - target_path[path.length()] != '/') - return false; - } - - return true; -} - -/** - * Is the client *potentially* able to access this path? Actual - * permission will depend on uids/modes in the full is_capable. - */ -bool MDSAuthCaps::path_capable(const std::string &inode_path) const -{ - for (const auto &i : grants) { - if (i.match.match_path(inode_path)) { - return true; - } - } - - return false; -} - -/** - * For a given filesystem path, query whether this capability carries` - * authorization to read or write. - * - * This is true if any of the 'grant' clauses in the capability match the - * requested path + op. - */ -bool MDSAuthCaps::is_capable(const std::string &inode_path, - uid_t inode_uid, gid_t inode_gid, - unsigned inode_mode, - uid_t caller_uid, gid_t caller_gid, - const vector *caller_gid_list, - unsigned mask, - uid_t new_uid, gid_t new_gid) const -{ - if (cct) - ldout(cct, 10) << __func__ << " inode(path /" << inode_path - << " owner " << inode_uid << ":" << inode_gid - << " mode 0" << std::oct << inode_mode << std::dec - << ") by caller " << caller_uid << ":" << caller_gid -// << "[" << caller_gid_list << "]"; - << " mask " << mask - << " new " << new_uid << ":" << new_gid - << " cap: " << *this << dendl; - - for (std::vector::const_iterator i = grants.begin(); - i != grants.end(); - ++i) { - - if (i->match.match(inode_path, caller_uid, caller_gid, caller_gid_list) && - i->spec.allows(mask & (MAY_READ|MAY_EXECUTE), mask & MAY_WRITE)) { - // we have a match; narrow down GIDs to those specifically allowed here - vector gids; - if (std::find(i->match.gids.begin(), i->match.gids.end(), caller_gid) != - i->match.gids.end()) { - gids.push_back(caller_gid); - } - if (caller_gid_list) { - std::set_intersection(i->match.gids.begin(), i->match.gids.end(), - caller_gid_list->begin(), caller_gid_list->end(), - std::back_inserter(gids)); - std::sort(gids.begin(), gids.end()); - } - - - // Spec is non-allowing if caller asked for set pool but spec forbids it - if (mask & MAY_SET_VXATTR) { - if (!i->spec.allows_set_vxattr()) { - continue; - } - } - - // check unix permissions? - if (i->match.uid == MDSCapMatch::MDS_AUTH_UID_ANY) { - return true; - } - - // chown/chgrp - if (mask & MAY_CHOWN) { - if (new_uid != caller_uid || // you can't chown to someone else - inode_uid != caller_uid) { // you can't chown from someone else - continue; - } - } - if (mask & MAY_CHGRP) { - // you can only chgrp *to* one of your groups... if you own the file. - if (inode_uid != caller_uid || - std::find(gids.begin(), gids.end(), new_gid) == - gids.end()) { - continue; - } - } - - if (inode_uid == caller_uid) { - if ((!(mask & MAY_READ) || (inode_mode & S_IRUSR)) && - (!(mask & MAY_WRITE) || (inode_mode & S_IWUSR)) && - (!(mask & MAY_EXECUTE) || (inode_mode & S_IXUSR))) { - return true; - } - } else if (std::find(gids.begin(), gids.end(), - inode_gid) != gids.end()) { - if ((!(mask & MAY_READ) || (inode_mode & S_IRGRP)) && - (!(mask & MAY_WRITE) || (inode_mode & S_IWGRP)) && - (!(mask & MAY_EXECUTE) || (inode_mode & S_IXGRP))) { - return true; - } - } else { - if ((!(mask & MAY_READ) || (inode_mode & S_IROTH)) && - (!(mask & MAY_WRITE) || (inode_mode & S_IWOTH)) && - (!(mask & MAY_EXECUTE) || (inode_mode & S_IXOTH))) { - return true; - } - } - } - } - - return false; -} - -void MDSAuthCaps::set_allow_all() -{ - grants.clear(); - grants.push_back(MDSCapGrant( - MDSCapSpec(true, true, true, true), - MDSCapMatch())); -} - -bool MDSAuthCaps::parse(CephContext *c, const std::string& str, ostream *err) -{ - // Special case for legacy caps - if (str == "allow") { - grants.clear(); - grants.push_back(MDSCapGrant(MDSCapSpec(true, true, false, true), MDSCapMatch())); - return true; - } - - MDSCapParser g; - std::string::const_iterator iter = str.begin(); - std::string::const_iterator end = str.end(); - - bool r = qi::phrase_parse(iter, end, g, ascii::space, *this); - cct = c; // set after parser self-assignment - if (r && iter == end) { - for (auto& grant : grants) { - std::sort(grant.match.gids.begin(), grant.match.gids.end()); - } - return true; - } else { - // Make sure no grants are kept after parsing failed! - grants.clear(); - - if (err) - *err << "MDSAuthCaps parse failed, stopped at '" << std::string(iter, end) - << "' of '" << str << "'\n"; - return false; - } -} - - -bool MDSAuthCaps::allow_all() const -{ - for (std::vector::const_iterator i = grants.begin(); i != grants.end(); ++i) { - if (i->match.is_match_all() && i->spec.allow_all()) { - return true; - } - } - - return false; -} - - -ostream &operator<<(ostream &out, const MDSCapMatch &match) -{ - if (match.path.length()) { - out << "path=\"/" << match.path << "\""; - if (match.uid != MDSCapMatch::MDS_AUTH_UID_ANY) { - out << " "; - } - } - if (match.uid != MDSCapMatch::MDS_AUTH_UID_ANY) { - out << "uid=" << match.uid; - if (!match.gids.empty()) { - out << " gids="; - for (std::vector::const_iterator p = match.gids.begin(); - p != match.gids.end(); - ++p) { - if (p != match.gids.begin()) - out << ','; - out << *p; - } - } - } - - return out; -} - - -ostream &operator<<(ostream &out, const MDSCapSpec &spec) -{ - if (spec.any) { - out << "*"; - } else { - if (spec.read) { - out << "r"; - } - if (spec.write) { - out << "w"; - } - } - - return out; -} - - -ostream &operator<<(ostream &out, const MDSCapGrant &grant) -{ - out << "allow "; - out << grant.spec; - if (!grant.match.is_match_all()) { - out << " " << grant.match; - } - - return out; -} - - -ostream &operator<<(ostream &out, const MDSAuthCaps &cap) -{ - out << "MDSAuthCaps["; - for (size_t i = 0; i < cap.grants.size(); ++i) { - out << cap.grants[i]; - if (i < cap.grants.size() - 1) { - out << ", "; - } - } - out << "]"; - - return out; -} -