~mathiaz/+junk/ceph-new-pkg-review

« back to all changes in this revision

Viewing changes to src/osd/OSDCaps.cc

  • Committer: Mathias Gug
  • Date: 2010-07-29 03:10:42 UTC
  • Revision ID: mathias.gug@canonical.com-20100729031042-n9n8kky962qb4onb
Import ceph_0.21-0ubuntu1 from https://launchpad.net/~clint-fewbar/+archive/ceph/+packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "OSDCaps.h"
 
3
 
 
4
#include "config.h"
 
5
 
 
6
 
 
7
 
 
8
void PoolsMap::dump()
 
9
{
 
10
  map<string, OSDCap>::iterator it;
 
11
  for (it = pools_map.begin(); it != pools_map.end(); ++it) {
 
12
    generic_dout(0) << it->first << " -> (" << (int)it->second.allow << "." << (int)it->second.deny << ")" << dendl;
 
13
  }
 
14
}
 
15
 
 
16
void PoolsMap::apply_caps(string& name, int& cap)
 
17
{
 
18
  map<string, OSDCap>::iterator iter;
 
19
 
 
20
  if ((iter = pools_map.find(name)) != pools_map.end()) {
 
21
    OSDCap& c = iter->second;
 
22
    cap |= c.allow;
 
23
    cap &= ~c.deny;
 
24
  }
 
25
}
 
26
 
 
27
void AuidMap::apply_caps(uint64_t uid, int& cap)
 
28
{
 
29
  map<uint64_t, OSDCap>::iterator iter;
 
30
 
 
31
  if ((iter = auid_map.find(uid)) != auid_map.end()) {
 
32
    OSDCap& auid_cap = iter->second;
 
33
    cap |= auid_cap.allow;
 
34
    cap &= ~auid_cap.deny;
 
35
  }
 
36
}
 
37
 
 
38
bool OSDCaps::get_next_token(string s, size_t& pos, string& token)
 
39
{
 
40
  int start = s.find_first_not_of(" \t", pos);
 
41
  int end;
 
42
 
 
43
  if (s[start] == '=' || s[start] == ',' || s[start] == ';') {
 
44
    end = start + 1;
 
45
  } else {
 
46
    end = s.find_first_of(";,= \t", start+1);
 
47
  }
 
48
 
 
49
  if (start < 0) {
 
50
    return false; 
 
51
  }
 
52
 
 
53
  if (end < 0) {
 
54
    end=s.size();
 
55
  }
 
56
 
 
57
  token = s.substr(start, end - start);
 
58
 
 
59
  pos = end;
 
60
 
 
61
  return true;
 
62
}
 
63
 
 
64
bool OSDCaps::is_rwx(string& token, rwx_t& cap_val)
 
65
{
 
66
  const char *t = token.c_str();
 
67
  int val = 0;
 
68
 
 
69
  while (*t) {
 
70
    switch (*t) {
 
71
    case 'r':
 
72
      val |= OSD_POOL_CAP_R;
 
73
      break;
 
74
    case 'w':
 
75
      val |= OSD_POOL_CAP_W;
 
76
      break;
 
77
    case 'x':
 
78
      val |= OSD_POOL_CAP_X;
 
79
      break;
 
80
    default:
 
81
      return false;
 
82
    }
 
83
    t++;
 
84
  }
 
85
 
 
86
  cap_val = val;
 
87
  return true;
 
88
}
 
89
 
 
90
bool OSDCaps::parse(bufferlist::iterator& iter)
 
91
{
 
92
  string s;
 
93
 
 
94
  try {
 
95
    ::decode(s, iter);
 
96
 
 
97
    generic_dout(0) << "decoded caps: " << s << dendl;
 
98
 
 
99
    size_t pos = 0;
 
100
    string token;
 
101
    bool init = true;
 
102
 
 
103
    bool op_allow = false;
 
104
    bool op_deny = false;
 
105
    bool cmd_pool = false;
 
106
    bool cmd_uid = false;
 
107
    bool any_cmd = false;
 
108
    bool got_eq = false;
 
109
    list<string> name_list;
 
110
    bool last_is_comma = false;
 
111
    rwx_t cap_val = 0;
 
112
 
 
113
    while (pos < s.size()) {
 
114
      if (init) {
 
115
        op_allow = false;
 
116
        op_deny = false;
 
117
        cmd_pool = false;
 
118
        cmd_uid = false;
 
119
        any_cmd = false;
 
120
        got_eq = false;
 
121
        last_is_comma = false;
 
122
        cap_val = 0;
 
123
        init = false;
 
124
        name_list.clear();
 
125
      }
 
126
 
 
127
#define ASSERT_STATE(x) \
 
128
do { \
 
129
  if (!(x)) { \
 
130
       *_dout << "error parsing caps at pos=" << pos << " (" #x ")" << std::endl; \
 
131
  } \
 
132
} while (0)
 
133
 
 
134
      if (get_next_token(s, pos, token)) {
 
135
        if (token.compare("*") == 0) { //allow all operations 
 
136
          ASSERT_STATE(op_allow);
 
137
          allow_all = true;
 
138
        } else if (token.compare("=") == 0) {
 
139
          ASSERT_STATE(any_cmd);
 
140
          got_eq = true;
 
141
        } else if (token.compare("allow") == 0) {
 
142
          ASSERT_STATE((!op_allow) && (!op_deny));
 
143
          op_allow = true;
 
144
        } else if (token.compare("deny") == 0) {
 
145
          ASSERT_STATE((!op_allow) && (!op_deny));
 
146
          op_deny = true;
 
147
        } else if ((token.compare("pools") == 0) ||
 
148
                   (token.compare("pool") == 0)) {
 
149
          ASSERT_STATE(!cmd_uid && (op_allow || op_deny));
 
150
          cmd_pool = true;
 
151
          any_cmd = true;
 
152
        } else if (token.compare("uid") == 0) {
 
153
          ASSERT_STATE(!cmd_pool && (op_allow || op_deny));
 
154
          any_cmd = true;
 
155
          cmd_uid = true;
 
156
        } else if (is_rwx(token, cap_val)) {
 
157
          ASSERT_STATE(op_allow || op_deny);
 
158
        } else if (token.compare(";") != 0) {
 
159
          ASSERT_STATE(got_eq);
 
160
          if (token.compare(",") == 0) {
 
161
            ASSERT_STATE(!last_is_comma);
 
162
            last_is_comma = true;
 
163
          } else {
 
164
            last_is_comma = false;
 
165
            name_list.push_back(token);
 
166
          }
 
167
        }
 
168
 
 
169
        if (token.compare(";") == 0 || pos >= s.size()) {
 
170
          if (got_eq) {
 
171
            ASSERT_STATE(name_list.size() > 0);
 
172
            list<string>::iterator iter;
 
173
            CapMap *working_map = &pools_map;
 
174
            if (cmd_uid) working_map = &auid_map;
 
175
            for (iter = name_list.begin(); iter != name_list.end(); ++iter) {
 
176
              OSDCap& cap = working_map->get_cap(*iter);
 
177
              if (op_allow) {
 
178
                cap.allow |= cap_val;
 
179
              } else {
 
180
                cap.deny |= cap_val;
 
181
              }
 
182
            }
 
183
          } else {
 
184
            if (op_allow) {
 
185
              default_allow |= cap_val;
 
186
            } else {
 
187
              default_deny |= cap_val;
 
188
            }
 
189
          }
 
190
          init = true;
 
191
        }
 
192
        
 
193
      }
 
194
    }
 
195
  } catch (buffer::error *err) {
 
196
    return false;
 
197
  }
 
198
 
 
199
  generic_dout(0) << "default allow=" << (int)default_allow << " default_deny=" << (int) default_deny << dendl;
 
200
  pools_map.dump();
 
201
  return true;
 
202
}
 
203
 
 
204
/**
 
205
 * Get the caps given this OSDCaps object for a given pool id
 
206
 * and uid (the pool's owner).
 
207
 *
 
208
 * Basic strategy: chain of permissions: default allow -> auid
 
209
 * -> pool -> default_deny.
 
210
 *
 
211
 * Starting with default allowed caps. Next check if you have caps on
 
212
 * the auid and apply, then apply any caps granted on the pool
 
213
 * (this lets users give out caps to their auid but keep one pool
 
214
 * private, for instance).
 
215
 * If these two steps haven't given you explicit caps
 
216
 * on the pool, check if you're the pool owner and grant full.
 
217
 */
 
218
int OSDCaps::get_pool_cap(string& pool_name, uint64_t uid)
 
219
{
 
220
  if (allow_all)
 
221
    return OSD_POOL_CAP_ALL;
 
222
 
 
223
  int explicit_cap = default_allow; //explicitly granted caps
 
224
  
 
225
  //if the owner is granted permissions on the pool owner's auid, grant them
 
226
  auid_map.apply_caps(uid, explicit_cap);
 
227
 
 
228
  //check for explicitly granted caps and apply if needed
 
229
  pools_map.apply_caps(pool_name, explicit_cap);
 
230
 
 
231
  //owner gets full perms by default:
 
232
  if (uid != CEPH_AUTH_UID_DEFAULT
 
233
      && uid == auid
 
234
      && explicit_cap == 0) {
 
235
    explicit_cap = OSD_POOL_CAP_ALL;
 
236
  }
 
237
 
 
238
  explicit_cap &= ~default_deny;
 
239
 
 
240
  return explicit_cap;
 
241
}
 
242