]>
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), | |
7c673cae FG |
37 | }; |
38 | ||
7c673cae FG |
39 | // what we can do |
40 | struct MDSCapSpec { | |
11fdf7f2 TL |
41 | static const unsigned ALL = (1 << 0); |
42 | static const unsigned READ = (1 << 1); | |
43 | static const unsigned WRITE = (1 << 2); | |
44 | // if the capability permits setting vxattrs (layout, quota, etc) | |
45 | static const unsigned SET_VXATTR = (1 << 3); | |
46 | // if the capability permits mksnap/rmsnap | |
47 | static const unsigned SNAPSHOT = (1 << 4); | |
48 | ||
49 | static const unsigned RW = (READ|WRITE); | |
50 | static const unsigned RWP = (READ|WRITE|SET_VXATTR); | |
51 | static const unsigned RWS = (READ|WRITE|SNAPSHOT); | |
52 | static const unsigned RWPS = (READ|WRITE|SET_VXATTR|SNAPSHOT); | |
53 | ||
54 | MDSCapSpec() = default; | |
55 | MDSCapSpec(unsigned _caps) : caps(_caps) { | |
56 | if (caps & ALL) | |
57 | caps |= RWPS; | |
58 | } | |
7c673cae FG |
59 | |
60 | bool allow_all() const { | |
11fdf7f2 TL |
61 | return (caps & ALL); |
62 | } | |
63 | bool allow_read() const { | |
64 | return (caps & READ); | |
65 | } | |
66 | bool allow_write() const { | |
67 | return (caps & WRITE); | |
7c673cae FG |
68 | } |
69 | ||
70 | bool allows(bool r, bool w) const { | |
11fdf7f2 | 71 | if (allow_all()) |
7c673cae | 72 | return true; |
11fdf7f2 | 73 | if (r && !allow_read()) |
7c673cae | 74 | return false; |
11fdf7f2 | 75 | if (w && !allow_write()) |
7c673cae FG |
76 | return false; |
77 | return true; | |
78 | } | |
79 | ||
11fdf7f2 TL |
80 | bool allow_snapshot() const { |
81 | return (caps & SNAPSHOT); | |
82 | } | |
83 | bool allow_set_vxattr() const { | |
84 | return (caps & SET_VXATTR); | |
7c673cae | 85 | } |
11fdf7f2 TL |
86 | private: |
87 | unsigned caps = 0; | |
7c673cae FG |
88 | }; |
89 | ||
90 | // conditions before we are allowed to do it | |
91 | struct MDSCapMatch { | |
92 | static const int64_t MDS_AUTH_UID_ANY = -1; | |
93 | ||
f67539c2 TL |
94 | MDSCapMatch() : uid(MDS_AUTH_UID_ANY), fs_name(std::string()) {} |
95 | ||
96 | MDSCapMatch(int64_t uid_, std::vector<gid_t>& gids_) : | |
97 | uid(uid_), gids(gids_), fs_name(std::string()) {} | |
98 | ||
11fdf7f2 | 99 | explicit MDSCapMatch(const std::string &path_) |
f67539c2 TL |
100 | : uid(MDS_AUTH_UID_ANY), path(path_), fs_name(std::string()) { |
101 | normalize_path(); | |
102 | } | |
103 | ||
104 | explicit MDSCapMatch(std::string path, std::string fs_name) : | |
105 | uid(MDS_AUTH_UID_ANY), path(std::move(path)), fs_name(std::move(fs_name)) | |
106 | { | |
7c673cae FG |
107 | normalize_path(); |
108 | } | |
f67539c2 TL |
109 | |
110 | explicit MDSCapMatch(std::string path, std::string fs_name, bool root_squash_) : | |
111 | uid(MDS_AUTH_UID_ANY), path(std::move(path)), fs_name(std::move(fs_name)), root_squash(root_squash_) | |
112 | { | |
113 | normalize_path(); | |
114 | } | |
115 | ||
11fdf7f2 | 116 | MDSCapMatch(const std::string& path_, int64_t uid_, std::vector<gid_t>& gids_) |
f67539c2 | 117 | : uid(uid_), gids(gids_), path(path_), fs_name(std::string()) { |
7c673cae FG |
118 | normalize_path(); |
119 | } | |
120 | ||
121 | void normalize_path(); | |
122 | ||
123 | bool is_match_all() const | |
124 | { | |
125 | return uid == MDS_AUTH_UID_ANY && path == ""; | |
126 | } | |
127 | ||
128 | // check whether this grant matches against a given file and caller uid:gid | |
11fdf7f2 | 129 | bool match(std::string_view target_path, |
7c673cae FG |
130 | const int caller_uid, |
131 | const int caller_gid, | |
f67539c2 | 132 | const std::vector<uint64_t> *caller_gid_list) const; |
7c673cae FG |
133 | |
134 | /** | |
135 | * Check whether this path *might* be accessible (actual permission | |
136 | * depends on the stronger check in match()). | |
137 | * | |
138 | * @param target_path filesystem path without leading '/' | |
139 | */ | |
11fdf7f2 | 140 | bool match_path(std::string_view target_path) const; |
9f95a23c TL |
141 | |
142 | int64_t uid; // Require UID to be equal to this, if !=MDS_AUTH_UID_ANY | |
143 | std::vector<gid_t> gids; // Use these GIDs | |
144 | std::string path; // Require path to be child of this (may be "" or "/" for any) | |
f67539c2 TL |
145 | std::string fs_name; |
146 | bool root_squash=false; | |
7c673cae FG |
147 | }; |
148 | ||
149 | struct MDSCapGrant { | |
11fdf7f2 TL |
150 | MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_, |
151 | boost::optional<std::string> n) | |
152 | : spec(spec_), match(match_) { | |
153 | if (n) { | |
154 | network = *n; | |
155 | parse_network(); | |
156 | } | |
157 | } | |
7c673cae | 158 | MDSCapGrant() {} |
11fdf7f2 TL |
159 | |
160 | void parse_network(); | |
9f95a23c TL |
161 | |
162 | MDSCapSpec spec; | |
163 | MDSCapMatch match; | |
164 | ||
165 | std::string network; | |
166 | ||
167 | entity_addr_t network_parsed; | |
168 | unsigned network_prefix = 0; | |
169 | bool network_valid = true; | |
7c673cae FG |
170 | }; |
171 | ||
172 | class MDSAuthCaps | |
173 | { | |
7c673cae | 174 | public: |
11fdf7f2 TL |
175 | MDSAuthCaps() = default; |
176 | explicit MDSAuthCaps(CephContext *cct_) : cct(cct_) {} | |
7c673cae FG |
177 | |
178 | // this ctor is used by spirit/phoenix; doesn't need cct. | |
11fdf7f2 TL |
179 | explicit MDSAuthCaps(const std::vector<MDSCapGrant>& grants_) : grants(grants_) {} |
180 | ||
181 | void clear() { | |
182 | grants.clear(); | |
183 | } | |
7c673cae FG |
184 | |
185 | void set_allow_all(); | |
11fdf7f2 | 186 | bool parse(CephContext *cct, std::string_view str, std::ostream *err); |
7c673cae FG |
187 | |
188 | bool allow_all() const; | |
11fdf7f2 | 189 | bool is_capable(std::string_view inode_path, |
7c673cae | 190 | uid_t inode_uid, gid_t inode_gid, unsigned inode_mode, |
f67539c2 | 191 | uid_t uid, gid_t gid, const std::vector<uint64_t> *caller_gid_list, |
11fdf7f2 TL |
192 | unsigned mask, uid_t new_uid, gid_t new_gid, |
193 | const entity_addr_t& addr) const; | |
194 | bool path_capable(std::string_view inode_path) const; | |
7c673cae | 195 | |
f67539c2 TL |
196 | bool fs_name_capable(std::string_view fs_name, unsigned mask) const { |
197 | if (allow_all()) { | |
198 | return true; | |
199 | } | |
200 | ||
201 | for (const MDSCapGrant &g : grants) { | |
202 | if (g.match.fs_name == fs_name || g.match.fs_name.empty() || | |
203 | g.match.fs_name == "*") { | |
204 | if (mask & MAY_READ && g.spec.allow_read()) { | |
205 | return true; | |
206 | } | |
207 | ||
208 | if (mask & MAY_WRITE && g.spec.allow_write()) { | |
209 | return true; | |
210 | } | |
211 | } | |
212 | } | |
213 | ||
214 | return false; | |
215 | } | |
216 | ||
7c673cae | 217 | friend std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap); |
9f95a23c TL |
218 | private: |
219 | CephContext *cct = nullptr; | |
220 | std::vector<MDSCapGrant> grants; | |
7c673cae FG |
221 | }; |
222 | ||
7c673cae FG |
223 | std::ostream &operator<<(std::ostream &out, const MDSCapMatch &match); |
224 | std::ostream &operator<<(std::ostream &out, const MDSCapSpec &spec); | |
225 | std::ostream &operator<<(std::ostream &out, const MDSCapGrant &grant); | |
226 | std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap); | |
227 | ||
228 | #endif // MDS_AUTH_CAPS_H |