]>
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) 2004-2009 Sage Weil <sage@newdream.net> | |
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 | ||
15 | #ifndef CEPH_KEYSSERVER_H | |
16 | #define CEPH_KEYSSERVER_H | |
17 | ||
18 | #include "auth/KeyRing.h" | |
19 | #include "CephxProtocol.h" | |
11fdf7f2 | 20 | #include "common/ceph_mutex.h" |
9f95a23c | 21 | #include "include/common_fwd.h" |
7c673cae FG |
22 | |
23 | struct KeyServerData { | |
24 | version_t version; | |
25 | ||
26 | /* for each entity */ | |
f67539c2 | 27 | std::map<EntityName, EntityAuth> secrets; |
7c673cae FG |
28 | KeyRing *extra_secrets; |
29 | ||
30 | /* for each service type */ | |
31 | version_t rotating_ver; | |
f67539c2 | 32 | std::map<uint32_t, RotatingSecrets> rotating_secrets; |
7c673cae FG |
33 | |
34 | explicit KeyServerData(KeyRing *extra) | |
35 | : version(0), | |
36 | extra_secrets(extra), | |
37 | rotating_ver(0) {} | |
38 | ||
f67539c2 | 39 | void encode(ceph::buffer::list& bl) const { |
7c673cae | 40 | __u8 struct_v = 1; |
11fdf7f2 TL |
41 | using ceph::encode; |
42 | encode(struct_v, bl); | |
43 | encode(version, bl); | |
44 | encode(rotating_ver, bl); | |
45 | encode(secrets, bl); | |
46 | encode(rotating_secrets, bl); | |
7c673cae | 47 | } |
f67539c2 | 48 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 49 | using ceph::decode; |
7c673cae | 50 | __u8 struct_v; |
11fdf7f2 TL |
51 | decode(struct_v, bl); |
52 | decode(version, bl); | |
53 | decode(rotating_ver, bl); | |
54 | decode(secrets, bl); | |
55 | decode(rotating_secrets, bl); | |
7c673cae FG |
56 | } |
57 | ||
f67539c2 | 58 | void encode_rotating(ceph::buffer::list& bl) const { |
11fdf7f2 | 59 | using ceph::encode; |
7c673cae | 60 | __u8 struct_v = 1; |
11fdf7f2 TL |
61 | encode(struct_v, bl); |
62 | encode(rotating_ver, bl); | |
63 | encode(rotating_secrets, bl); | |
7c673cae | 64 | } |
f67539c2 | 65 | void decode_rotating(ceph::buffer::list& rotating_bl) { |
11fdf7f2 TL |
66 | using ceph::decode; |
67 | auto iter = rotating_bl.cbegin(); | |
7c673cae | 68 | __u8 struct_v; |
11fdf7f2 TL |
69 | decode(struct_v, iter); |
70 | decode(rotating_ver, iter); | |
71 | decode(rotating_secrets, iter); | |
7c673cae FG |
72 | } |
73 | ||
74 | bool contains(const EntityName& name) const { | |
75 | return (secrets.find(name) != secrets.end()); | |
76 | } | |
77 | ||
78 | void clear_secrets() { | |
494da23a | 79 | version = 0; |
7c673cae | 80 | secrets.clear(); |
494da23a TL |
81 | rotating_ver = 0; |
82 | rotating_secrets.clear(); | |
7c673cae FG |
83 | } |
84 | ||
85 | void add_auth(const EntityName& name, EntityAuth& auth) { | |
86 | secrets[name] = auth; | |
87 | } | |
88 | ||
89 | void remove_secret(const EntityName& name) { | |
f67539c2 | 90 | auto iter = secrets.find(name); |
7c673cae FG |
91 | if (iter == secrets.end()) |
92 | return; | |
93 | secrets.erase(iter); | |
94 | } | |
95 | ||
96 | bool get_service_secret(CephContext *cct, uint32_t service_id, | |
c5c27e9a TL |
97 | CryptoKey& secret, uint64_t& secret_id, |
98 | double& ttl) const; | |
7c673cae FG |
99 | bool get_service_secret(CephContext *cct, uint32_t service_id, |
100 | uint64_t secret_id, CryptoKey& secret) const; | |
101 | bool get_auth(const EntityName& name, EntityAuth& auth) const; | |
102 | bool get_secret(const EntityName& name, CryptoKey& secret) const; | |
103 | bool get_caps(CephContext *cct, const EntityName& name, | |
104 | const std::string& type, AuthCapsInfo& caps) const; | |
105 | ||
f67539c2 | 106 | std::map<EntityName, EntityAuth>::iterator secrets_begin() |
7c673cae | 107 | { return secrets.begin(); } |
f67539c2 | 108 | std::map<EntityName, EntityAuth>::const_iterator secrets_begin() const |
7c673cae | 109 | { return secrets.begin(); } |
f67539c2 | 110 | std::map<EntityName, EntityAuth>::iterator secrets_end() |
7c673cae | 111 | { return secrets.end(); } |
f67539c2 | 112 | std::map<EntityName, EntityAuth>::const_iterator secrets_end() const |
7c673cae | 113 | { return secrets.end(); } |
f67539c2 | 114 | std::map<EntityName, EntityAuth>::iterator find_name(const EntityName& name) |
7c673cae | 115 | { return secrets.find(name); } |
f67539c2 | 116 | std::map<EntityName, EntityAuth>::const_iterator find_name(const EntityName& name) const |
7c673cae FG |
117 | { return secrets.find(name); } |
118 | ||
119 | ||
120 | // -- incremental updates -- | |
121 | typedef enum { | |
122 | AUTH_INC_NOP, | |
123 | AUTH_INC_ADD, | |
124 | AUTH_INC_DEL, | |
125 | AUTH_INC_SET_ROTATING, | |
126 | } IncrementalOp; | |
127 | ||
128 | struct Incremental { | |
129 | IncrementalOp op; | |
f67539c2 | 130 | ceph::buffer::list rotating_bl; // if SET_ROTATING. otherwise, |
7c673cae FG |
131 | EntityName name; |
132 | EntityAuth auth; | |
f67539c2 TL |
133 | |
134 | void encode(ceph::buffer::list& bl) const { | |
11fdf7f2 | 135 | using ceph::encode; |
7c673cae | 136 | __u8 struct_v = 1; |
11fdf7f2 | 137 | encode(struct_v, bl); |
7c673cae | 138 | __u32 _op = (__u32)op; |
11fdf7f2 | 139 | encode(_op, bl); |
7c673cae | 140 | if (op == AUTH_INC_SET_ROTATING) { |
11fdf7f2 | 141 | encode(rotating_bl, bl); |
7c673cae | 142 | } else { |
11fdf7f2 TL |
143 | encode(name, bl); |
144 | encode(auth, bl); | |
7c673cae FG |
145 | } |
146 | } | |
f67539c2 | 147 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 148 | using ceph::decode; |
7c673cae | 149 | __u8 struct_v; |
11fdf7f2 | 150 | decode(struct_v, bl); |
7c673cae | 151 | __u32 _op; |
11fdf7f2 | 152 | decode(_op, bl); |
7c673cae | 153 | op = (IncrementalOp)_op; |
11fdf7f2 | 154 | ceph_assert(op >= AUTH_INC_NOP && op <= AUTH_INC_SET_ROTATING); |
7c673cae | 155 | if (op == AUTH_INC_SET_ROTATING) { |
11fdf7f2 | 156 | decode(rotating_bl, bl); |
7c673cae | 157 | } else { |
11fdf7f2 TL |
158 | decode(name, bl); |
159 | decode(auth, bl); | |
7c673cae FG |
160 | } |
161 | } | |
162 | }; | |
163 | ||
164 | void apply_incremental(Incremental& inc) { | |
165 | switch (inc.op) { | |
166 | case AUTH_INC_ADD: | |
167 | add_auth(inc.name, inc.auth); | |
168 | break; | |
169 | ||
170 | case AUTH_INC_DEL: | |
171 | remove_secret(inc.name); | |
172 | break; | |
173 | ||
174 | case AUTH_INC_SET_ROTATING: | |
175 | decode_rotating(inc.rotating_bl); | |
176 | break; | |
177 | ||
178 | case AUTH_INC_NOP: | |
179 | break; | |
180 | ||
181 | default: | |
182 | ceph_abort(); | |
183 | } | |
184 | } | |
185 | ||
186 | }; | |
187 | WRITE_CLASS_ENCODER(KeyServerData) | |
188 | WRITE_CLASS_ENCODER(KeyServerData::Incremental) | |
189 | ||
190 | ||
191 | ||
192 | ||
193 | class KeyServer : public KeyStore { | |
194 | CephContext *cct; | |
195 | KeyServerData data; | |
11fdf7f2 | 196 | mutable ceph::mutex lock; |
7c673cae | 197 | |
a4b75251 | 198 | int _rotate_secret(uint32_t service_id, KeyServerData &pending_data); |
7c673cae FG |
199 | void _dump_rotating_secrets(); |
200 | int _build_session_auth_info(uint32_t service_id, | |
11fdf7f2 | 201 | const AuthTicket& parent_ticket, |
c5c27e9a TL |
202 | CephXSessionAuthInfo& info, |
203 | double ttl); | |
7c673cae FG |
204 | bool _get_service_caps(const EntityName& name, uint32_t service_id, |
205 | AuthCapsInfo& caps) const; | |
206 | public: | |
207 | KeyServer(CephContext *cct_, KeyRing *extra_secrets); | |
208 | bool generate_secret(CryptoKey& secret); | |
209 | ||
210 | bool get_secret(const EntityName& name, CryptoKey& secret) const override; | |
211 | bool get_auth(const EntityName& name, EntityAuth& auth) const; | |
f67539c2 | 212 | bool get_caps(const EntityName& name, const std::string& type, AuthCapsInfo& caps) const; |
7c673cae FG |
213 | bool get_active_rotating_secret(const EntityName& name, CryptoKey& secret) const; |
214 | int start_server(); | |
215 | void rotate_timeout(double timeout); | |
216 | ||
a4b75251 TL |
217 | void dump(); |
218 | ||
11fdf7f2 TL |
219 | int build_session_auth_info(uint32_t service_id, |
220 | const AuthTicket& parent_ticket, | |
221 | CephXSessionAuthInfo& info); | |
222 | int build_session_auth_info(uint32_t service_id, | |
223 | const AuthTicket& parent_ticket, | |
c5c27e9a TL |
224 | const CryptoKey& service_secret, |
225 | uint64_t secret_id, | |
226 | CephXSessionAuthInfo& info); | |
7c673cae FG |
227 | |
228 | /* get current secret for specific service type */ | |
c5c27e9a TL |
229 | bool get_service_secret(uint32_t service_id, CryptoKey& secret, |
230 | uint64_t& secret_id, double& ttl) const; | |
7c673cae FG |
231 | bool get_service_secret(uint32_t service_id, uint64_t secret_id, |
232 | CryptoKey& secret) const override; | |
233 | ||
234 | bool generate_secret(EntityName& name, CryptoKey& secret); | |
235 | ||
f67539c2 | 236 | void encode(ceph::buffer::list& bl) const { |
11fdf7f2 TL |
237 | using ceph::encode; |
238 | encode(data, bl); | |
7c673cae | 239 | } |
f67539c2 | 240 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 TL |
241 | std::scoped_lock l{lock}; |
242 | using ceph::decode; | |
243 | decode(data, bl); | |
7c673cae FG |
244 | } |
245 | bool contains(const EntityName& name) const; | |
f67539c2 TL |
246 | int encode_secrets(ceph::Formatter *f, std::stringstream *ds) const; |
247 | void encode_formatted(std::string label, ceph::Formatter *f, ceph::buffer::list &bl); | |
248 | void encode_plaintext(ceph::buffer::list &bl); | |
249 | int list_secrets(std::stringstream& ds) const { | |
7c673cae FG |
250 | return encode_secrets(NULL, &ds); |
251 | } | |
252 | version_t get_ver() const { | |
11fdf7f2 | 253 | std::scoped_lock l{lock}; |
f67539c2 | 254 | return data.version; |
7c673cae FG |
255 | } |
256 | ||
257 | void clear_secrets() { | |
11fdf7f2 | 258 | std::scoped_lock l{lock}; |
7c673cae FG |
259 | data.clear_secrets(); |
260 | } | |
261 | ||
262 | void apply_data_incremental(KeyServerData::Incremental& inc) { | |
11fdf7f2 | 263 | std::scoped_lock l{lock}; |
7c673cae FG |
264 | data.apply_incremental(inc); |
265 | } | |
266 | void set_ver(version_t ver) { | |
11fdf7f2 | 267 | std::scoped_lock l{lock}; |
7c673cae FG |
268 | data.version = ver; |
269 | } | |
270 | ||
271 | void add_auth(const EntityName& name, EntityAuth& auth) { | |
11fdf7f2 | 272 | std::scoped_lock l{lock}; |
7c673cae FG |
273 | data.add_auth(name, auth); |
274 | } | |
275 | ||
276 | void remove_secret(const EntityName& name) { | |
11fdf7f2 | 277 | std::scoped_lock l{lock}; |
7c673cae FG |
278 | data.remove_secret(name); |
279 | } | |
280 | ||
281 | bool has_secrets() { | |
f67539c2 | 282 | auto b = data.secrets_begin(); |
7c673cae FG |
283 | return (b != data.secrets_end()); |
284 | } | |
285 | int get_num_secrets() { | |
11fdf7f2 | 286 | std::scoped_lock l{lock}; |
7c673cae FG |
287 | return data.secrets.size(); |
288 | } | |
289 | ||
290 | void clone_to(KeyServerData& dst) const { | |
11fdf7f2 | 291 | std::scoped_lock l{lock}; |
7c673cae FG |
292 | dst = data; |
293 | } | |
294 | void export_keyring(KeyRing& keyring) { | |
11fdf7f2 | 295 | std::scoped_lock l{lock}; |
f67539c2 | 296 | for (auto p = data.secrets.begin(); p != data.secrets.end(); ++p) { |
7c673cae FG |
297 | keyring.add(p->first, p->second); |
298 | } | |
299 | } | |
300 | ||
a4b75251 | 301 | bool prepare_rotating_update(ceph::buffer::list& rotating_bl); |
7c673cae | 302 | |
f67539c2 | 303 | bool get_rotating_encrypted(const EntityName& name, ceph::buffer::list& enc_bl) const; |
7c673cae | 304 | |
11fdf7f2 | 305 | ceph::mutex& get_lock() const { return lock; } |
7c673cae FG |
306 | bool get_service_caps(const EntityName& name, uint32_t service_id, |
307 | AuthCapsInfo& caps) const; | |
308 | ||
f67539c2 | 309 | std::map<EntityName, EntityAuth>::iterator secrets_begin() |
7c673cae | 310 | { return data.secrets_begin(); } |
f67539c2 | 311 | std::map<EntityName, EntityAuth>::iterator secrets_end() |
7c673cae FG |
312 | { return data.secrets_end(); } |
313 | }; | |
314 | WRITE_CLASS_ENCODER(KeyServer) | |
315 | ||
316 | ||
317 | #endif |