summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoao Eduardo Luis <joao.luis@inktank.com>2013-07-26 19:56:44 +0100
committerJoao Eduardo Luis <joao.luis@inktank.com>2013-08-06 13:59:15 -0700
commitf087d84ba0f70c29166abb59ba1495e3bd4e44d9 (patch)
treed5532c15896a284a3b198fea133b5dd09c8a5a2b
parentef036bd4bc0e79bff8a5805800fbdeb0cc2db6ae (diff)
downloadceph-f087d84ba0f70c29166abb59ba1495e3bd4e44d9.tar.gz
mon: Monitor: check caps considering command's requirements
Fixes: #5648 Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
-rw-r--r--src/mon/Monitor.cc50
-rw-r--r--src/mon/Monitor.h2
2 files changed, 52 insertions, 0 deletions
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index 118cf6f4a1e..20a799f3e52 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -1893,6 +1893,51 @@ struct MonCommand {
#include <mon/MonCommands.h>
};
+bool Monitor::_allowed_command(MonSession *s, string &module, string &prefix,
+ map<string,cmd_vartype>& cmdmap) {
+
+ map<string,string> strmap;
+ for (map<string,cmd_vartype>::const_iterator p = cmdmap.begin();
+ p != cmdmap.end(); ++p) {
+ if (p->first == "prefix")
+ continue;
+ if (p->first == "caps") {
+ vector<string> cv;
+ if (cmd_getval(g_ceph_context, cmdmap, "caps", cv) &&
+ cv.size() % 2 == 0) {
+ for (unsigned i = 0; i < cv.size(); i += 2) {
+ string k = string("caps_") + cv[i];
+ strmap[k] = cv[i + 1];
+ }
+ continue;
+ }
+ }
+ strmap[p->first] = cmd_vartype_stringify(p->second);
+ }
+
+ MonCommand *this_cmd = NULL;
+ for (MonCommand *cp = mon_commands;
+ cp < &mon_commands[ARRAY_SIZE(mon_commands)]; cp++) {
+ dout(0) << __func__ << " CAPSBAR >> matching against " << cp->cmdstring << dendl;
+ if (cp->cmdstring.find(prefix) != string::npos) {
+ this_cmd = cp;
+ break;
+ }
+ }
+ assert(this_cmd != NULL);
+ bool cmd_r = (this_cmd->req_perms.find('r') != string::npos);
+ bool cmd_w = (this_cmd->req_perms.find('w') != string::npos);
+ bool cmd_x = (this_cmd->req_perms.find('x') != string::npos);
+
+ bool capable = s->caps.is_capable(g_ceph_context, s->inst.name,
+ module, prefix, strmap,
+ cmd_r, cmd_w, cmd_x);
+
+ dout(10) << __func__ << " " << (capable ? "" : "not ") << "capable" << dendl;
+ return capable;
+}
+
+
void Monitor::handle_command(MMonCommand *m)
{
if (m->fsid != monmap->fsid) {
@@ -1979,6 +2024,11 @@ void Monitor::handle_command(MMonCommand *m)
access_r = (session->is_capable("mon", MON_CAP_R) || access_cmd);
access_all = (session->caps.is_allow_all() || access_cmd);
+ if (!_allowed_command(session, module, prefix, cmdmap)) {
+ dout(1) << __func__ << " access denied" << dendl;
+ reply_command(m, -EACCES, "access denied", 0);
+ }
+
if (module == "mds") {
mdsmon()->dispatch(m);
return;
diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h
index cb1f4138a25..c76b8a47d4f 100644
--- a/src/mon/Monitor.h
+++ b/src/mon/Monitor.h
@@ -584,6 +584,8 @@ public:
void handle_subscribe(MMonSubscribe *m);
void handle_mon_get_map(MMonGetMap *m);
bool _allowed_command(MonSession *s, map<std::string, cmd_vartype>& cmd);
+ bool _allowed_command(MonSession *s, string &module, string& prefix,
+ map<string,cmd_vartype>& cmdmap);
void _mon_status(Formatter *f, ostream& ss);
void _quorum_status(Formatter *f, ostream& ss);
void _add_bootstrap_peer_hint(string cmd, cmdmap_t& cmdmap, ostream& ss);