lexeme[lit("'") >> *(char_ - '\'') >> '\''];
unquoted_path %= +char_("a-zA-Z0-9_.-/");
- // match := [path=<path>] [uid=<uid>]
- uid %= (spaces >> lit("uid") >> lit('=') >> int_);
+ // match := [path=<path>] [uid=<uid> [gids=<gid>[,<gid>...]]
path %= (spaces >> lit("path") >> lit('=') >> (quoted_path | unquoted_path));
+ uid %= (spaces >> lit("uid") >> lit('=') >> int_);
+ intlist %= (int_ % lit(','));
+ gidlist %= -(spaces >> lit("gids") >> lit('=') >> intlist);
match = -(
- (uid)[_val = phoenix::construct<MDSCapMatch>(_1)] |
- (path >> uid)[_val = phoenix::construct<MDSCapMatch>(_1, _2)] |
+ (uid >> gidlist)[_val = phoenix::construct<MDSCapMatch>(_1, _2)] |
+ (path >> uid >> gidlist)[_val = phoenix::construct<MDSCapMatch>(_1, _2, _3)] |
(path)[_val = phoenix::construct<MDSCapMatch>(_1)]);
// capspec = * | r[w]
qi::rule<Iterator, MDSCapSpec()> capspec;
qi::rule<Iterator, string()> path;
qi::rule<Iterator, int()> uid;
+ qi::rule<Iterator, std::vector<int>() > intlist;
+ qi::rule<Iterator, std::vector<int>() > gidlist;
qi::rule<Iterator, MDSCapMatch()> match;
qi::rule<Iterator, MDSCapGrant()> grant;
qi::rule<Iterator, std::vector<MDSCapGrant>()> grants;
if (match.path != MDSCapMatch::MDS_AUTH_PATH_ROOT) {
out << "path=\"" << match.path << "\"";
}
- if (match.path != MDSCapMatch::MDS_AUTH_PATH_ROOT && match.uid != MDSCapMatch::MDS_AUTH_UID_ANY) {
+ if (match.path != MDSCapMatch::MDS_AUTH_PATH_ROOT &&
+ 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<int>::const_iterator p = match.gids.begin();
+ p != match.gids.end();
+ ++p) {
+ if (p != match.gids.begin())
+ out << ',';
+ out << *p;
+ }
+ }
}
return out;
#include <string>
#include <sstream>
-
+// what we can do
struct MDSCapSpec {
bool read;
bool write;
}
};
+// conditions before we are allowed to do it
struct MDSCapMatch {
static const int MDS_AUTH_UID_ANY = -1;
static const std::string MDS_AUTH_PATH_ROOT;
- int uid; // Require UID to be equal to this, if !=MDS_AUTH_UID_ANY
+ int uid; // Require UID to be equal to this, if !=MDS_AUTH_UID_ANY
+ std::vector<int> gids; // Use these GIDs
std::string path; // Require path to be child of this (may be "/" for any)
MDSCapMatch() : uid(MDS_AUTH_UID_ANY), path(MDS_AUTH_PATH_ROOT) {}
- MDSCapMatch(int uid_) : uid(uid_), path(MDS_AUTH_PATH_ROOT) {}
+ MDSCapMatch(int uid_, std::vector<int>& gids_)
+ : uid(uid_), gids(gids_), path(MDS_AUTH_PATH_ROOT) {}
MDSCapMatch(std::string path_) : uid(MDS_AUTH_UID_ANY), path(path_) {}
- MDSCapMatch(std::string path_, int uid_) : uid(uid_), path(path_) {}
+ MDSCapMatch(std::string path_, int uid_, std::vector<int>& gids_)
+ : uid(uid_), gids(gids_), path(path_) {}
bool is_match_all() const
{
using std::cout;
const char *parse_good[] = {
+ "allow rw uid=1 gids=1",
"allow * path=\"/foo\"",
"allow * path=/foo",
"allow * path=\"/foo bar/baz\"",
"allow *",
"allow r",
"allow rw",
+ "allow rw uid=1 gids=1,2,3",
+ "allow rw path=/foo uid=1 gids=1,2,3",
0
};
"allow namespace=foo",
"allow rwx auid 123 namespace asdf",
"allow wwx pool ''",
+ "allow rw gids=1",
+ "allow rw gids=1,2,3",
+ "allow rw uid=123 gids=asdf",
+ "allow rw uid=123 gids=1,2,asdf",
0
};
"MDSAuthCaps[allow rw]"},
{"allow * uid=1",
"MDSAuthCaps[allow * uid=1]"},
+ {"allow * uid=1 gids=1",
+ "MDSAuthCaps[allow * uid=1 gids=1]"},
+ {"allow * uid=1 gids=1,2,3",
+ "MDSAuthCaps[allow * uid=1 gids=1,2,3]"},
{"allow * path=/foo",
"MDSAuthCaps[allow * path=\"/foo\"]"},
{"allow * path=\"/foo\"",
"MDSAuthCaps[allow * path=\"/foo\"]"},
{"allow * path=\"/foo\" uid=1",
"MDSAuthCaps[allow * path=\"/foo\" uid=1]"},
+ {"allow * path=\"/foo\" uid=1 gids=1,2,3",
+ "MDSAuthCaps[allow * path=\"/foo\" uid=1 gids=1,2,3]"},
};
size_t num_tests = sizeof(test_values) / sizeof(*test_values);
for (size_t i = 0; i < num_tests; ++i) {