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