*/
#define CEPH_OSD_PROTOCOL 8 /* cluster internal */
#define CEPH_MDS_PROTOCOL 14 /* cluster internal */
-#define CEPH_MON_PROTOCOL 7 /* cluster internal */
+#define CEPH_MON_PROTOCOL 8 /* cluster internal */
#define CEPH_OSDC_PROTOCOL 24 /* server/client */
#define CEPH_MDSC_PROTOCOL 32 /* server/client */
#define CEPH_MONC_PROTOCOL 15 /* server/client */
bool op_deny = false;
bool any_cmd = false;
bool got_eq = false;
+ bool got_command = false;
+ list<string> command;
list<int> services_list;
list<int> uid_list;
bool last_is_comma = false;
op_deny = false;
any_cmd = false;
got_eq = false;
+ got_command = false;
+ command.clear();
last_is_comma = false;
cap_val = 0;
init = false;
if (token.compare("*") == 0) { //allow all operations
ASSERT_STATE(op_allow);
allow_all = true;
+ } else if (token.compare("command") == 0) {
+ ASSERT_STATE(op_allow);
+ got_command = true;
} else if (token.compare("=") == 0) {
ASSERT_STATE(any_cmd);
got_eq = true;
} else if (is_rwx(token, cap_val)) {
ASSERT_STATE(op_allow || op_deny);
} else if (token.compare(";") != 0) {
- ASSERT_STATE(got_eq);
- if (token.compare(",") == 0) {
- ASSERT_STATE(!last_is_comma);
- } else {
- last_is_comma = false;
- int service = get_service_id(token);
- if (service != -EINVAL) {
- if (service >= 0) {
- services_list.push_back(service);
- } else {
- generic_dout(0) << "error parsing caps at pos=" << pos << ", unknown service_name: " << token << dendl;
+ if (got_command) {
+ command.push_back(token);
+ } else {
+ ASSERT_STATE(got_eq);
+ if (token.compare(",") == 0) {
+ ASSERT_STATE(!last_is_comma);
+ } else {
+ last_is_comma = false;
+ int service = get_service_id(token);
+ if (service != -EINVAL) {
+ if (service >= 0) {
+ services_list.push_back(service);
+ } else {
+ generic_dout(0) << "error parsing caps at pos=" << pos << ", unknown service_name: " << token << dendl;
+ }
+ } else { //must be a uid
+ uid_list.push_back(strtoul(token.c_str(), NULL, 10));
}
- } else { //must be a uid
- uid_list.push_back(strtoul(token.c_str(), NULL, 10));
}
}
}
if (token.compare(";") == 0 || pos >= s.size()) {
- if (got_eq) {
+ if (got_command) {
+ generic_dout(0) << "parsed command " << command << dendl;
+ cmd_allow.push_back(command);
+ }
+ else if (got_eq) {
ASSERT_STATE((services_list.size() > 0) ||
(uid_list.size() > 0));
int get_service_id(string& token);
bool allow_all;
uint64_t auid;
+
+ // command whitelist
+ list<list<string> > cmd_allow;
+
public:
- MonCaps() : text(), default_action(0),
- allow_all(false), auid(CEPH_AUTH_UID_DEFAULT) {}
+ MonCaps()
+ : text(), default_action(0),
+ allow_all(false), auid(CEPH_AUTH_UID_DEFAULT)
+ {}
const string& get_str() const { return text; }
bool parse(bufferlist::iterator& iter);
rwx_t get_caps(int service) const;
void set_auid(uint64_t uid) { auid = uid; }
void encode(bufferlist& bl) const {
+ __u8 v = 2;
+ ::encode(v, bl);
::encode(text, bl);
::encode(default_action, bl);
::encode(services_map, bl);
::encode(pool_auid_map, bl);
::encode(allow_all, bl);
::encode(auid, bl);
+ ::encode(cmd_allow, bl);
}
void decode(bufferlist::iterator& bl) {
+ __u8 v;
+ ::decode(v, bl);
::decode(text, bl);
::decode(default_action, bl);
::decode(services_map, bl);
::decode(pool_auid_map, bl);
::decode(allow_all, bl);
::decode(auid, bl);
+ ::decode(cmd_allow, bl);
}
};
-
WRITE_CLASS_ENCODER(MonCaps);
inline ostream& operator<<(ostream& out, const MonCaps& m) {
resend_routed_requests();
}
+bool Monitor::_allowed_command(MonSession *s, const vector<string>& cmd)
+{
+ if (s->caps.check_privileges(PAXOS_MONMAP, MON_CAP_ALL))
+ return true;
+
+ for (list<list<string> >::iterator p = s->caps.cmd_allow.begin();
+ p != s->caps.cmd_allow.end();
+ ++p) {
+ list<string>::iterator q;
+ int i = 0;
+ for (q = p->begin(); q != p->end(); ++q, ++i) {
+ if (*q != cmd[i])
+ break;
+ }
+ if (q == p->end())
+ return true; // match
+ }
+
+ return false;
+}
+
void Monitor::handle_command(MMonCommand *m)
{
if (ceph_fsid_compare(&m->fsid, &monmap->fsid)) {
}
MonSession *session = m->get_session();
- if (!session ||
- !session->caps.check_privileges(PAXOS_MONMAP, MON_CAP_ALL)) {
+ if (!session || !_allowed_command(session, m->cmd)) {
string rs = "Access denied";
reply_command(m, -EACCES, rs, 0);
return;
void handle_get_version(MMonGetVersion *m);
void handle_subscribe(MMonSubscribe *m);
void handle_mon_get_map(MMonGetMap *m);
+ bool _allowed_command(MonSession *s, const vector<std::string>& cmd);
void handle_command(class MMonCommand *m);
void handle_observe(MMonObserve *m);
void handle_route(MRoute *m);