]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: Monitor: check caps considering command's requirements
authorJoao Eduardo Luis <joao.luis@inktank.com>
Fri, 26 Jul 2013 18:56:44 +0000 (19:56 +0100)
committerJoao Eduardo Luis <joao.luis@inktank.com>
Tue, 6 Aug 2013 20:59:15 +0000 (13:59 -0700)
Fixes: #5648
Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
src/mon/Monitor.cc
src/mon/Monitor.h

index 118cf6f4a1ee59cbe265665e3a9cb82d50a66e37..20a799f3e52fad9ac049986e8dd5bc49bb702e30 100644 (file)
@@ -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;
index cb1f4138a252401647ea10b98a7d0f204c75fd44..c76b8a47d4fab7a464734fc550d511dbb5e1d7a5 100644 (file)
@@ -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);