]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/MDSAuthCaps.h
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / mds / MDSAuthCaps.h
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 */
14 #ifndef MDS_AUTH_CAPS_H
15 #define MDS_AUTH_CAPS_H
16
17 #include <ostream>
18 #include <string>
19 #include <string_view>
20 #include <vector>
21
22 #include "include/common_fwd.h"
23 #include "include/types.h"
24 #include "common/debug.h"
25
26 #include "mdstypes.h"
27
28 // unix-style capabilities
29 enum {
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),
37 MAY_FULL = (1 << 8),
38 };
39
40 // what we can do
41 struct MDSCapSpec {
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);
49 // if the capability permits to bypass osd full check
50 static const unsigned FULL = (1 << 5);
51
52 static const unsigned RW = (READ|WRITE);
53 static const unsigned RWF = (READ|WRITE|FULL);
54 static const unsigned RWP = (READ|WRITE|SET_VXATTR);
55 static const unsigned RWS = (READ|WRITE|SNAPSHOT);
56 static const unsigned RWFP = (READ|WRITE|FULL|SET_VXATTR);
57 static const unsigned RWFS = (READ|WRITE|FULL|SNAPSHOT);
58 static const unsigned RWPS = (READ|WRITE|SET_VXATTR|SNAPSHOT);
59 static const unsigned RWFPS = (READ|WRITE|FULL|SET_VXATTR|SNAPSHOT);
60
61 MDSCapSpec() = default;
62 MDSCapSpec(unsigned _caps) : caps(_caps) {
63 if (caps & ALL)
64 caps |= RWFPS;
65 }
66
67 bool allow_all() const {
68 return (caps & ALL);
69 }
70 bool allow_read() const {
71 return (caps & READ);
72 }
73 bool allow_write() const {
74 return (caps & WRITE);
75 }
76
77 bool allows(bool r, bool w) const {
78 if (allow_all())
79 return true;
80 if (r && !allow_read())
81 return false;
82 if (w && !allow_write())
83 return false;
84 return true;
85 }
86
87 bool allow_snapshot() const {
88 return (caps & SNAPSHOT);
89 }
90 bool allow_set_vxattr() const {
91 return (caps & SET_VXATTR);
92 }
93 bool allow_full() const {
94 return (caps & FULL);
95 }
96 private:
97 unsigned caps = 0;
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
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
109 explicit MDSCapMatch(const std::string &path_)
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 {
117 normalize_path();
118 }
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
126 MDSCapMatch(const std::string& path_, int64_t uid_, std::vector<gid_t>& gids_)
127 : uid(uid_), gids(gids_), path(path_), fs_name(std::string()) {
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
139 bool match(std::string_view target_path,
140 const int caller_uid,
141 const int caller_gid,
142 const std::vector<uint64_t> *caller_gid_list) const;
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 */
150 bool match_path(std::string_view target_path) const;
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)
155 std::string fs_name;
156 bool root_squash=false;
157 };
158
159 struct MDSCapGrant {
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 }
168 MDSCapGrant() {}
169
170 void parse_network();
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;
180 };
181
182 class MDSAuthCaps
183 {
184 public:
185 MDSAuthCaps() = default;
186
187 // this ctor is used by spirit/phoenix
188 explicit MDSAuthCaps(const std::vector<MDSCapGrant>& grants_) : grants(grants_) {}
189
190 void clear() {
191 grants.clear();
192 }
193
194 void set_allow_all();
195 bool parse(std::string_view str, std::ostream *err);
196
197 bool allow_all() const;
198 bool is_capable(std::string_view inode_path,
199 uid_t inode_uid, gid_t inode_gid, unsigned inode_mode,
200 uid_t uid, gid_t gid, const std::vector<uint64_t> *caller_gid_list,
201 unsigned mask, uid_t new_uid, gid_t new_gid,
202 const entity_addr_t& addr) const;
203 bool path_capable(std::string_view inode_path) const;
204
205 bool fs_name_capable(std::string_view fs_name, unsigned mask) const {
206 if (allow_all()) {
207 return true;
208 }
209
210 for (const MDSCapGrant &g : grants) {
211 if (g.match.fs_name == fs_name || g.match.fs_name.empty() ||
212 g.match.fs_name == "*") {
213 if (mask & MAY_READ && g.spec.allow_read()) {
214 return true;
215 }
216
217 if (mask & MAY_WRITE && g.spec.allow_write()) {
218 return true;
219 }
220 }
221 }
222
223 return false;
224 }
225
226 friend std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap);
227 private:
228 std::vector<MDSCapGrant> grants;
229 };
230
231 std::ostream &operator<<(std::ostream &out, const MDSCapMatch &match);
232 std::ostream &operator<<(std::ostream &out, const MDSCapSpec &spec);
233 std::ostream &operator<<(std::ostream &out, const MDSCapGrant &grant);
234 std::ostream &operator<<(std::ostream &out, const MDSAuthCaps &cap);
235
236 #endif // MDS_AUTH_CAPS_H