]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2014 Red Hat | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
7c673cae FG |
14 | #ifndef MDS_AUTH_CAPS_H |
15 | #define MDS_AUTH_CAPS_H | |
16 | ||
f67539c2 | 17 | #include <ostream> |
94b18763 | 18 | #include <string> |
11fdf7f2 | 19 | #include <string_view> |
94b18763 FG |
20 | #include <vector> |
21 | ||
9f95a23c | 22 | #include "include/common_fwd.h" |
7c673cae FG |
23 | #include "include/types.h" |
24 | #include "common/debug.h" | |
25 | ||
f67539c2 TL |
26 | #include "mdstypes.h" |
27 | ||
7c673cae FG |
28 | // unix-style capabilities |
29 | enum { | |
11fdf7f2 TL |
30 | MAY_READ = (1 << 0), |
31 | MAY_WRITE = (1 << 1), | |
32 | MAY_EXECUTE = (1 << 2), | |
33 | MAY_CHOWN = (1 << 4), | |
34 | MAY_CHGRP = (1 << 5), | |
35 | MAY_SET_VXATTR = (1 << 6), | |
36 | MAY_SNAPSHOT = (1 << 7), | |
b3b6e05e | 37 | MAY_FULL = (1 << 8), |
7c673cae FG |
38 | }; |
39 | ||
7c673cae FG |
40 | // what we can do |
41 | struct MDSCapSpec { | |
11fdf7f2 TL |
42 | static const unsigned ALL = (1 << 0); |
43 | static const unsigned READ = (1 << 1); | |
44 | static const unsigned WRITE = (1 << 2); | |
45 | // if the capability permits setting vxattrs (layout, quota, etc) | |
46 | static const unsigned SET_VXATTR = (1 << 3); | |
47 | // if the capability permits mksnap/rmsnap | |
48 | static const unsigned SNAPSHOT = (1 << 4); | |
b3b6e05e TL |
49 | // if the capability permits to bypass osd full check |
50 | static const unsigned FULL = (1 << 5); | |
11fdf7f2 TL |
51 | |
52 | static const unsigned RW = (READ|WRITE); | |
b3b6e05e | 53 | static const unsigned RWF = (READ|WRITE|FULL); |
11fdf7f2 TL |
54 | static const unsigned RWP = (READ|WRITE|SET_VXATTR); |
55 | static const unsigned RWS = (READ|WRITE|SNAPSHOT); | |
b3b6e05e TL |
56 | static const unsigned RWFP = (READ|WRITE|FULL|SET_VXATTR); |
57 | static const unsigned RWFS = (READ|WRITE|FULL|SNAPSHOT); | |
11fdf7f2 | 58 | static const unsigned RWPS = (READ|WRITE|SET_VXATTR|SNAPSHOT); |
b3b6e05e | 59 | static const unsigned RWFPS = (READ|WRITE|FULL|SET_VXATTR|SNAPSHOT); |
11fdf7f2 TL |
60 | |
61 | MDSCapSpec() = default; | |
62 | MDSCapSpec(unsigned _caps) : caps(_caps) { | |
63 | if (caps & ALL) | |
b3b6e05e | 64 | caps |= RWFPS; |
11fdf7f2 | 65 | } |
7c673cae FG |
66 | |
67 | bool allow_all() const { | |
11fdf7f2 TL |
68 | return (caps & ALL); |
69 | } | |
70 | bool allow_read() const { | |
71 | return (caps & READ); | |
72 | } | |
73 | bool allow_write() const { | |
74 | return (caps & WRITE); | |
7c673cae FG |
75 | } |
76 | ||
77 | bool allows(bool r, bool w) const { | |
11fdf7f2 | 78 | if (allow_all()) |
7c673cae | 79 | return true; |
11fdf7f2 | 80 | if (r && !allow_read()) |
7c673cae | 81 | return false; |
11fdf7f2 | 82 | if (w && !allow_write()) |
7c673cae FG |
83 | return false; |
84 | return true; | |
85 | } | |
86 | ||
11fdf7f2 TL |
87 | bool allow_snapshot() const { |
88 | return (caps & SNAPSHOT); | |
89 | } | |
90 | bool allow_set_vxattr() const { | |
91 | return (caps & SET_VXATTR); | |
7c673cae | 92 | } |
b3b6e05e TL |
93 | bool allow_full() const { |
94 | return (caps & FULL); | |
95 | } | |
11fdf7f2 TL |
96 | private: |
97 | unsigned caps = 0; | |
7c673cae FG |
98 | }; |
99 | ||
100 | // conditions before we are allowed to do it | |
101 | struct MDSCapMatch { | |
102 | static const int64_t MDS_AUTH_UID_ANY = -1; | |
103 | ||
f67539c2 TL |
104 | MDSCapMatch() : uid(MDS_AUTH_UID_ANY), fs_name(std::string()) {} |
105 | ||
106 | MDSCapMatch(int64_t uid_, std::vector<gid_t>& gids_) : | |
107 | uid(uid_), gids(gids_), fs_name(std::string()) {} | |
108 | ||
11fdf7f2 | 109 | explicit MDSCapMatch(const std::string &path_) |
f67539c2 TL |
110 | : uid(MDS_AUTH_UID_ANY), path(path_), fs_name(std::string()) { |
111 | normalize_path(); | |
112 | } | |
113 | ||
114 | explicit MDSCapMatch(std::string path, std::string fs_name) : | |
115 | uid(MDS_AUTH_UID_ANY), path(std::move(path)), fs_name(std::move(fs_name)) | |
116 | { | |
7c673cae FG |
117 | normalize_path(); |
118 | } | |
f67539c2 TL |
119 | |
120 | explicit MDSCapMatch(std::string path, std::string fs_name, bool root_squash_) : | |
121 | uid(MDS_AUTH_UID_ANY), path(std::move(path)), fs_name(std::move(fs_name)), root_squash(root_squash_) | |
122 | { | |
123 | normalize_path(); | |
124 | } | |
125 | ||
11fdf7f2 | 126 | MDSCapMatch(const std::string& path_, int64_t uid_, std::vector<gid_t>& gids_) |
f67539c2 | 127 | : uid(uid_), gids(gids_), path(path_), fs_name(std::string()) { |
7c673cae FG |
128 | normalize_path(); |
129 | } | |
130 | ||
131 | void normalize_path(); | |
132 | ||
133 | bool is_match_all() const | |
134 | { | |
135 | return uid == MDS_AUTH_UID_ANY && path == ""; | |
136 | } | |
137 | ||
138 | // check whether this grant matches against a given file and caller uid:gid | |
11fdf7f2 | 139 | bool match(std::string_view target_path, |
7c673cae FG |
140 | const int caller_uid, |
141 | const int caller_gid, | |
f67539c2 | 142 | const std::vector<uint64_t> *caller_gid_list) const; |
7c673cae FG |
143 | |
144 | /** | |
145 | * Check whether this path *might* be accessible (actual permission | |
146 | * depends on the stronger check in match()). | |
147 | * | |
148 | * @param target_path filesystem path without leading '/' | |
149 | */ | |
11fdf7f2 | 150 | bool match_path(std::string_view target_path) const; |
9f95a23c TL |
151 | |
152 | int64_t uid; // Require UID to be equal to this, if !=MDS_AUTH_UID_ANY | |
153 | std::vector<gid_t> gids; // Use these GIDs | |
154 | std::string path; // Require path to be child of this (may be "" or "/" for any) | |
f67539c2 TL |
155 | std::string fs_name; |
156 | bool root_squash=false; | |
7c673cae FG |
157 | }; |
158 | ||
159 | struct MDSCapGrant { | |
11fdf7f2 TL |
160 | MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_, |
161 | boost::optional<std::string> n) | |
162 | : spec(spec_), match(match_) { | |
163 | if (n) { | |
164 | network = *n; | |
165 | parse_network(); | |
166 | } | |
167 | } | |
7c673cae | 168 | MDSCapGrant() {} |
11fdf7f2 TL |
169 | |
170 | void parse_network(); | |
9f95a23c TL |
171 | |
172 | MDSCapSpec spec; | |
173 | MDSCapMatch match; | |
174 | ||
175 | std::string network; | |
176 | ||
177 | entity_addr_t network_parsed; | |
178 | unsigned network_prefix = 0; | |
179 | bool network_valid = true; | |
7c673cae FG |
180 | }; |
181 | ||
182 | class MDSAuthCaps | |
183 | { | |
7c673cae | 184 | public: |
11fdf7f2 TL |
185 | MDSAuthCaps() = default; |
186 | explicit MDSAuthCaps(CephContext *cct_) : cct(cct_) {} | |
7c673cae FG |
187 | |
188 | // this ctor is used by spirit/phoenix; doesn't need cct. | |
11fdf7f2 TL |
189 | explicit MDSAuthCaps(const std::vector<MDSCapGrant>& grants_) : grants(grants_) {} |
190 | ||
191 | void clear() { | |
192 | grants.clear(); | |
193 | } | |
7c673cae FG |
194 | |
195 | void set_allow_all(); | |
11fdf7f2 | 196 | bool parse(CephContext *cct, std::string_view str, std::ostream *err); |
7c673cae FG |
197 | |
198 | bool allow_all() const; | |
11fdf7f2 | 199 | bool is_capable(std::string_view inode_path, |
7c673cae | 200 | uid_t inode_uid, gid_t inode_gid, unsigned inode_mode, |
f67539c2 | 201 | uid_t uid, gid_t gid, const std::vector<uint64_t> *caller_gid_list, |
11fdf7f2 TL |
202 | unsigned mask, uid_t new_uid, gid_t new_gid, |
203 | const entity_addr_t& addr) const; | |
204 | bool path_capable(std::string_view inode_path) const; | |
7c673cae | 205 | |
f67539c2 TL |
206 | bool fs_name_capable(std::string_view fs_name, unsigned mask) const { |
207 | if (allow_all()) { | |
208 | return true; | |
209 | } | |
210 | ||
211 | for (const MDSCapGrant &g : grants) { | |
212 | if (g.match.fs_name == fs_name || g.match.fs_name.empty() || | |
213 | g.match.fs_name == "*") { | |
214 | if (mask & MAY_READ && g.spec.allow_read()) { | |
215 | return true; | |
216 | } | |
217 | ||
218 | if (mask & MAY_WRITE && g.spec.allow_write()) { | |
219 | return true; | |
220 | } | |
221 | } | |
222 | } | |
223 | ||
224 | return false; | |
225 | } | |
226 | ||
7c673cae | 227 | friend std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap); |
9f95a23c TL |
228 | private: |
229 | CephContext *cct = nullptr; | |
230 | std::vector<MDSCapGrant> grants; | |
7c673cae FG |
231 | }; |
232 | ||
7c673cae FG |
233 | std::ostream &operator<<(std::ostream &out, const MDSCapMatch &match); |
234 | std::ostream &operator<<(std::ostream &out, const MDSCapSpec &spec); | |
235 | std::ostream &operator<<(std::ostream &out, const MDSCapGrant &grant); | |
236 | std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap); | |
237 | ||
238 | #endif // MDS_AUTH_CAPS_H |