]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: add osd caps parser
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 20 Oct 2009 23:43:03 +0000 (16:43 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 20 Oct 2009 23:43:03 +0000 (16:43 -0700)
src/osd/OSD.cc
src/osd/OSD.h
src/vstart.sh

index 6524629c1fd4854d4e47435f6d64d71cdae0820a..2e9344ecda0df100fae9a9ccf42bb8b0834b453d 100644 (file)
@@ -1538,6 +1538,21 @@ bool OSD::ms_verify_authorizer(Connection *con, int peer_type,
   int ret = verify_authorizer(g_keyring, iter, auth_ticket_info, authorizer_reply);
   dout(0) << "OSD::verify_authorizer returns " << ret << dendl;
 
+  Mutex::Locker l(session_lock);
+
+  Session *s = _get_session(con);
+
+  if (s) {
+    if (auth_ticket_info.ticket.caps.length() > 0) {
+      bufferlist::iterator iter = auth_ticket_info.ticket.caps.begin();
+      s->caps.parse(iter);
+    }
+
+    s->put();
+  } else {
+    derr(0) << "got a NULL session" << dendl;
+  }
+
   isvalid = (ret >= 0);
  
   return true;
@@ -4145,18 +4160,26 @@ void OSD::init_op_flags(MOSDOp *op)
   }
 }
 
+OSD::Session *OSD::_get_session(Connection *c)
+{
+  Session *s = (Session *)c->get_priv();
+  if (!s) {
+    s = new Session;
+    c->set_priv(s->get());
+    dout(10) << " new session " << s << dendl;
+  }
+
+  return s;
+}
+
+
 
 void OSD::handle_auth(MAuth *m)
 {
   dout(10) << "handle_auth " << *m << dendl;
   Mutex::Locker l(session_lock);
 
-  Session *s = (Session *)m->get_connection()->get_priv();
-  if (!s) {
-    s = new Session;
-    m->get_connection()->set_priv(s->get());
-    dout(10) << " new session " << s << dendl;
-  }
+  Session *s = _get_session(m->get_connection());
 
   /*
   bufferlist::iterator p = m->auth_payload.begin();
@@ -4172,3 +4195,158 @@ void OSD::handle_auth(MAuth *m)
   s->put();
   delete m;
 }
+
+bool OSD::OSDCaps::get_next_token(string s, size_t& pos, string& token)
+{
+  int start = s.find_first_not_of(" \t", pos);
+  int end;
+
+  if (s[start] == '=' || s[start] == ',' || s[start] == ';') {
+    end = pos + 1;
+  } else {
+    end = s.find_first_of(";,= \t", start+1);
+  }
+
+  if (start < 0) {
+    return false; 
+  }
+
+  if (end < 0) {
+    end=s.size();
+  }
+
+  token = s.substr(start, end - start);
+
+  pos = end;
+
+  return true;
+}
+
+bool OSD::OSDCaps::parse(bufferlist::iterator& iter)
+{
+  string s;
+
+  try {
+    ::decode(s, iter);
+
+    *_dout << "decoded caps: " << s << std::endl;
+
+    size_t pos = 0;
+    string token;
+    bool init = true;
+
+    bool op_allow = false;
+    bool op_deny = false;
+    bool cmd_pool = false;
+    bool any_cmd = false;
+    bool got_eq = false;
+    list<int> num_list;
+    bool last_is_comma = false;
+    int cap_val = 0;
+
+    while (pos < s.size()) {
+      if (init) {
+        op_allow = false;
+        op_deny = false;
+        cmd_pool = false;
+        any_cmd = false;
+        got_eq = false;
+        last_is_comma = false;
+        cap_val = 0;
+        init = false;
+        num_list.clear();
+      }
+
+#define ASSERT_STATE(x) \
+do { \
+  if (!(x)) { \
+       *_dout << "error parsing caps at pos=" << pos << " (" #x ")" << std::endl; \
+  } \
+} while (0)
+
+      if (get_next_token(s, pos, token)) {
+        if (token.compare("=") == 0) {
+          ASSERT_STATE(any_cmd);
+          got_eq = true;
+        } else if (token.compare("allow") == 0) {
+          ASSERT_STATE((!op_allow) && (!op_deny));
+          op_allow = true;
+        } else if (token.compare("deny") == 0) {
+          ASSERT_STATE((!op_allow) && (!op_deny));
+          op_deny = true;
+        } else if (token.compare("pools") == 0) {
+          ASSERT_STATE(op_allow || op_deny);
+          cmd_pool = true;
+          any_cmd = true;
+        } else if (token.compare("r") == 0) {
+          ASSERT_STATE(op_allow || op_deny);
+          cap_val = OSD_POOL_CAP_R;
+        } else if (token.compare("w") == 0) {
+          ASSERT_STATE(op_allow || op_deny);
+          cap_val = OSD_POOL_CAP_W;
+        } else if (token.compare("rw") == 0) {
+          ASSERT_STATE(op_allow || op_deny);
+          cap_val = OSD_POOL_CAP_RW;
+        } else if (token.compare(";") != 0) {
+          ASSERT_STATE(got_eq);
+          if (token.compare(",") == 0) {
+            ASSERT_STATE(!last_is_comma);
+          } else {
+            last_is_comma = false;
+            int num = strtol(token.c_str(), NULL, 10);
+            num_list.push_back(num);
+          }
+        }
+
+        if (token.compare(";") == 0 || pos >= s.size()) {
+          if (got_eq) {
+            ASSERT_STATE(num_list.size() > 0);
+            list<int>::iterator iter;
+            for (iter = num_list.begin(); iter != num_list.end(); ++iter) {
+              OSDPoolCap& cap = pools_map[*iter];
+              if (op_allow) {
+                cap.allow |= cap_val;
+              } else {
+                cap.deny |= cap_val;
+              }
+            }
+          } else {
+            if (op_allow) {
+              default_action |= cap_val;
+            } else {
+              default_action &= ~cap_val;
+            }
+          }
+          init = true;
+        }
+        
+      }
+    }
+  } catch (buffer::error *err) {
+    return false;
+  }
+
+  *_dout << "default=" << default_action << std::endl;
+  map<int, OSDPoolCap>::iterator it;
+  for (it = pools_map.begin(); it != pools_map.end(); ++it) {
+    *_dout << it->first << " -> (" << it->second.allow << "." << it->second.deny << ")" << std::endl;
+  }
+
+
+  return true;
+}
+
+int OSD::OSDCaps::get_pool_cap(int pool_id)
+{
+  int cap = default_action;
+
+  map<int, OSDPoolCap>::iterator iter = pools_map.find(pool_id);
+  if (iter != pools_map.end()) {
+    OSDPoolCap& c = iter->second;
+    cap |= c.allow;
+    cap &= ~c.deny;
+  }
+
+  return cap;
+}
+
index 3e58af2001092d6ae71776f874b059ef25bec206..5b51d78ad5e69ccc7ee5e1db6de0fa063a73696a 100644 (file)
@@ -41,6 +41,11 @@ using namespace std;
 using namespace __gnu_cxx;
 
 
+
+#define OSD_POOL_CAP_R 0x1
+#define OSD_POOL_CAP_W 0x2
+#define OSD_POOL_CAP_RW (OSD_POOL_CAP_R | OSD_POOL_CAP_W)
+
 enum {
   l_osd_first = 10000,
   l_osd_opq,
@@ -178,12 +183,30 @@ private:
 
   // -- sessions --
 public:
+  struct OSDPoolCap {
+    int allow;
+    int deny;
+    OSDPoolCap() : allow(0), deny(0) {}
+  };
+
+  class OSDCaps {
+    map<int, OSDPoolCap> pools_map;
+    int default_action;
+    bool get_next_token(string s, size_t& pos, string& token);
+  public:
+    OSDCaps() : default_action(0) {}
+    bool parse(bufferlist::iterator& iter);
+    int get_pool_cap(int pool_id);
+  };
   struct Session : public RefCountedObject {
     AuthTicket ticket;
+    OSDCaps caps;
   };
 
 private:
   Mutex session_lock;
+
+  Session *_get_session(Connection *c);
   
   void handle_auth(MAuth *m);
 
index eaa38e33f4741cf72bb1889714b0d104068c577f..163b93efa8380e1c78df7a18dbed4ee8a543c7c8 100755 (executable)
@@ -226,7 +226,7 @@ EOF
 cat <<EOF > $admin_caps
 ; generated by vstart.sh on `date`
        mon = "allow"
-       osd = "allow"
+       osd = "allow rw"
        mds = "allow"
 EOF
                $SUDO $CEPH_BIN/authtool --gen-key --name=mon. $monkeys_fn
@@ -283,7 +283,7 @@ EOF
            cat <<EOF > $osd_caps
 ; generated by vstart.sh on `date`
        mon = "allow"
-       osd = "allow"
+       osd = "allow rw"
 EOF
             $SUDO $CEPH_BIN/authtool --gen-key --name=osd.$osd --caps=$osd_caps $key_fn
             $SUDO $CEPH_ADM -i $key_fn auth add osd.$osd
@@ -307,7 +307,7 @@ EOF
        cat <<EOF > $mds_caps
 ; generated by vstart.sh on `date`
        mon = "allow"
-       osd = "allow"
+       osd = "allow rw"
        mds = "allow"
 EOF
             $SUDO $CEPH_BIN/authtool --gen-key --name=mds.$name --caps=$mds_caps $key_fn