1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "AuthRegistry.h"
5
6 #include "cephx/CephxAuthorizeHandler.h"
7 #ifdef HAVE_GSSAPI
8 #include "krb/KrbAuthorizeHandler.hpp"
9 #endif
10 #include "none/AuthNoneAuthorizeHandler.h"
11 #include "common/ceph_context.h"
12 #include "common/debug.h"
13 #include "auth/KeyRing.h"
14
15 #define dout_subsys ceph_subsys_auth
16 #undef dout_prefix
17 #define dout_prefix *_dout << "AuthRegistry(" << this << ") "
18
19 AuthRegistry::AuthRegistry(CephContext *cct)
20 : cct(cct)
21 {
22 cct->_conf.add_observer(this);
23 }
24
(1) Event exn_spec_violation: |
An exception of type "std::system_error" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate(). |
Also see events: |
[fun_call_w_exception] |
25 AuthRegistry::~AuthRegistry()
26 {
(2) Event fun_call_w_exception: |
Called function throws an exception of type "std::system_error". [details] |
Also see events: |
[exn_spec_violation] |
27 cct->_conf.remove_observer(this);
28 for (auto i : authorize_handlers) {
29 delete i.second;
30 }
31 }
32
33 const char** AuthRegistry::get_tracked_conf_keys() const
34 {
35 static const char *keys[] = {
36 "auth_supported",
37 "auth_client_required",
38 "auth_cluster_required",
39 "auth_service_required",
40 "ms_mon_cluster_mode",
41 "ms_mon_service_mode",
42 "ms_mon_client_mode",
43 "ms_cluster_mode",
44 "ms_service_mode",
45 "ms_client_mode",
46 "keyring",
47 NULL
48 };
49 return keys;
50 }
51
52 void AuthRegistry::handle_conf_change(
53 const ConfigProxy& conf,
54 const std::set<std::string>& changed)
55 {
56 std::scoped_lock l(lock);
57 _refresh_config();
58 }
59
60
61 void AuthRegistry::_parse_method_list(const string& s,
62 std::vector<uint32_t> *v)
63 {
64 std::list<std::string> sup_list;
65 get_str_list(s, sup_list);
66 if (sup_list.empty()) {
67 lderr(cct) << "WARNING: empty auth protocol list" << dendl;
68 }
69 v->clear();
70 for (auto& i : sup_list) {
71 ldout(cct, 5) << "adding auth protocol: " << i << dendl;
72 if (i == "cephx") {
73 v->push_back(CEPH_AUTH_CEPHX);
74 } else if (i == "none") {
75 v->push_back(CEPH_AUTH_NONE);
76 } else if (i == "gss") {
77 v->push_back(CEPH_AUTH_GSS);
78 } else {
79 lderr(cct) << "WARNING: unknown auth protocol defined: " << i << dendl;
80 }
81 }
82 if (v->empty()) {
83 lderr(cct) << "WARNING: no auth protocol defined" << dendl;
84 }
85 ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
86 }
87
88 void AuthRegistry::_parse_mode_list(const string& s,
89 std::vector<uint32_t> *v)
90 {
91 std::list<std::string> sup_list;
92 get_str_list(s, sup_list);
93 if (sup_list.empty()) {
94 lderr(cct) << "WARNING: empty auth protocol list" << dendl;
95 }
96 v->clear();
97 for (auto& i : sup_list) {
98 ldout(cct, 5) << "adding con mode: " << i << dendl;
99 if (i == "crc") {
100 v->push_back(CEPH_CON_MODE_CRC);
101 } else if (i == "secure") {
102 v->push_back(CEPH_CON_MODE_SECURE);
103 } else {
104 lderr(cct) << "WARNING: unknown connection mode " << i << dendl;
105 }
106 }
107 if (v->empty()) {
108 lderr(cct) << "WARNING: no connection modes defined" << dendl;
109 }
110 ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
111 }
112
113 void AuthRegistry::_refresh_config()
114 {
115 if (cct->_conf->auth_supported.size()) {
116 _parse_method_list(cct->_conf->auth_supported, &cluster_methods);
117 _parse_method_list(cct->_conf->auth_supported, &service_methods);
118 _parse_method_list(cct->_conf->auth_supported, &client_methods);
119 } else {
120 _parse_method_list(cct->_conf->auth_cluster_required, &cluster_methods);
121 _parse_method_list(cct->_conf->auth_service_required, &service_methods);
122 _parse_method_list(cct->_conf->auth_client_required, &client_methods);
123 }
124 _parse_mode_list(cct->_conf.get_val<string>("ms_mon_cluster_mode"),
125 &mon_cluster_modes);
126 _parse_mode_list(cct->_conf.get_val<string>("ms_mon_service_mode"),
127 &mon_service_modes);
128 _parse_mode_list(cct->_conf.get_val<string>("ms_mon_client_mode"),
129 &mon_client_modes);
130 _parse_mode_list(cct->_conf.get_val<string>("ms_cluster_mode"),
131 &cluster_modes);
132 _parse_mode_list(cct->_conf.get_val<string>("ms_service_mode"),
133 &service_modes);
134 _parse_mode_list(cct->_conf.get_val<string>("ms_client_mode"),
135 &client_modes);
136
137 ldout(cct,10) << __func__ << " cluster_methods " << cluster_methods
138 << " service_methods " << service_methods
139 << " client_methods " << client_methods
140 << dendl;
141 ldout(cct,10) << __func__ << " mon_cluster_modes " << mon_cluster_modes
142 << " mon_service_modes " << mon_service_modes
143 << " mon_client_modes " << mon_client_modes
144 << "; cluster_modes " << cluster_modes
145 << " service_modes " << service_modes
146 << " client_modes " << client_modes
147 << dendl;
148
149 // if we have no keyring, filter out cephx
150 _no_keyring_disabled_cephx = false;
151 bool any_cephx = false;
152 for (auto *p : {&cluster_methods, &service_methods, &client_methods}) {
153 auto q = std::find(p->begin(), p->end(), CEPH_AUTH_CEPHX);
154 if (q != p->end()) {
155 any_cephx = true;
156 break;
157 }
158 }
159 if (any_cephx) {
160 KeyRing k;
161 int r = k.from_ceph_context(cct);
162 if (r == -ENOENT) {
163 for (auto *p : {&cluster_methods, &service_methods, &client_methods}) {
164 auto q = std::find(p->begin(), p->end(), CEPH_AUTH_CEPHX);
165 if (q != p->end()) {
166 p->erase(q);
167 _no_keyring_disabled_cephx = true;
168 }
169 }
170 }
171 if (_no_keyring_disabled_cephx) {
172 lderr(cct) << "no keyring found at " << cct->_conf->keyring
173 << ", disabling cephx" << dendl;
174 }
175 }
176 }
177
178 void AuthRegistry::get_supported_methods(
179 int peer_type,
180 std::vector<uint32_t> *methods,
181 std::vector<uint32_t> *modes) const
182 {
183 if (methods) {
184 methods->clear();
185 }
186 if (modes) {
187 modes->clear();
188 }
189 std::scoped_lock l(lock);
190 switch (cct->get_module_type()) {
191 case CEPH_ENTITY_TYPE_CLIENT:
192 // i am client
193 if (methods) {
194 *methods = client_methods;
195 }
196 if (modes) {
197 switch (peer_type) {
198 case CEPH_ENTITY_TYPE_MON:
199 *modes = mon_client_modes;
200 break;
201 default:
202 *modes = client_modes;
203 }
204 }
205 return;
206 case CEPH_ENTITY_TYPE_MON:
207 // i am mon
208 switch (peer_type) {
209 case CEPH_ENTITY_TYPE_MON:
210 // they are mon
211 if (methods) {
212 *methods = cluster_methods;
213 }
214 if (modes) {
215 *modes = mon_cluster_modes;
216 }
217 break;
218 default:
219 // they are anything but mons
220 if (methods) {
221 *methods = service_methods;
222 }
223 if (modes) {
224 *modes = mon_service_modes;
225 }
226 }
227 return;
228 default:
229 // i am a non-mon daemon
230 switch (peer_type) {
231 case CEPH_ENTITY_TYPE_MON:
232 case CEPH_ENTITY_TYPE_MGR:
233 case CEPH_ENTITY_TYPE_MDS:
234 case CEPH_ENTITY_TYPE_OSD:
235 // they are another daemon
236 if (methods) {
237 *methods = cluster_methods;
238 }
239 if (modes) {
240 *modes = cluster_modes;
241 }
242 break;
243 default:
244 // they are a client
245 if (methods) {
246 *methods = service_methods;
247 }
248 if (modes) {
249 *modes = service_modes;
250 }
251 break;
252 }
253 }
254 }
255
256 bool AuthRegistry::is_supported_method(int peer_type, int method) const
257 {
258 std::vector<uint32_t> s;
259 get_supported_methods(peer_type, &s);
260 return std::find(s.begin(), s.end(), method) != s.end();
261 }
262
263 bool AuthRegistry::any_supported_methods(int peer_type) const
264 {
265 std::vector<uint32_t> s;
266 get_supported_methods(peer_type, &s);
267 return !s.empty();
268 }
269
270 void AuthRegistry::get_supported_modes(
271 int peer_type,
272 uint32_t auth_method,
273 std::vector<uint32_t> *modes) const
274 {
275 std::vector<uint32_t> s;
276 get_supported_methods(peer_type, nullptr, &s);
277 if (auth_method == CEPH_AUTH_NONE) {
278 // filter out all but crc for AUTH_NONE
279 modes->clear();
280 for (auto mode : s) {
281 if (mode == CEPH_CON_MODE_CRC) {
282 modes->push_back(mode);
283 }
284 }
285 } else {
286 *modes = s;
287 }
288 }
289
290 uint32_t AuthRegistry::pick_mode(
291 int peer_type,
292 uint32_t auth_method,
293 const std::vector<uint32_t>& preferred_modes)
294 {
295 std::vector<uint32_t> allowed_modes;
296 get_supported_modes(peer_type, auth_method, &allowed_modes);
297 for (auto mode : preferred_modes) {
298 if (std::find(allowed_modes.begin(), allowed_modes.end(), mode)
299 != allowed_modes.end()) {
300 return mode;
301 }
302 }
303 ldout(cct,1) << "failed to pick con mode from client's " << preferred_modes
304 << " and our " << allowed_modes << dendl;
305 return CEPH_CON_MODE_UNKNOWN;
306 }
307
308 AuthAuthorizeHandler *AuthRegistry::get_handler(int peer_type, int method)
309 {
310 std::scoped_lock l{lock};
311 ldout(cct,20) << __func__ << " peer_type " << peer_type << " method " << method
312 << " cluster_methods " << cluster_methods
313 << " service_methods " << service_methods
314 << " client_methods " << client_methods
315 << dendl;
316 if (cct->get_module_type() == CEPH_ENTITY_TYPE_CLIENT) {
317 return nullptr;
318 }
319 switch (peer_type) {
320 case CEPH_ENTITY_TYPE_MON:
321 case CEPH_ENTITY_TYPE_MGR:
322 case CEPH_ENTITY_TYPE_MDS:
323 case CEPH_ENTITY_TYPE_OSD:
324 if (std::find(cluster_methods.begin(), cluster_methods.end(), method) ==
325 cluster_methods.end()) {
326 return nullptr;
327 }
328 break;
329 default:
330 if (std::find(service_methods.begin(), service_methods.end(), method) ==
331 service_methods.end()) {
332 return nullptr;
333 }
334 break;
335 }
336
337 auto iter = authorize_handlers.find(method);
338 if (iter != authorize_handlers.end()) {
339 return iter->second;
340 }
341 AuthAuthorizeHandler *ah = nullptr;
342 switch (method) {
343 case CEPH_AUTH_NONE:
344 ah = new AuthNoneAuthorizeHandler();
345 break;
346 case CEPH_AUTH_CEPHX:
347 ah = new CephxAuthorizeHandler();
348 break;
349 #ifdef HAVE_GSSAPI
350 case CEPH_AUTH_GSS:
351 ah = new KrbAuthorizeHandler();
352 break;
353 #endif
354 }
355 if (ah) {
356 authorize_handlers[method] = ah;
357 }
358 return ah;
359 }
360
361