]>
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_AUTHTYPES_H | |
16 | #define CEPH_AUTHTYPES_H | |
17 | ||
18 | #include "Crypto.h" | |
19 | #include "common/entity_name.h" | |
20 | ||
11fdf7f2 TL |
21 | // The _MAX values are a bit wonky here because we are overloading the first |
22 | // byte of the auth payload to identify both the type of authentication to be | |
23 | // used *and* the encoding version for the authenticator. So, we define a | |
24 | // range. | |
25 | enum { | |
26 | AUTH_MODE_NONE = 0, | |
27 | AUTH_MODE_AUTHORIZER = 1, | |
28 | AUTH_MODE_AUTHORIZER_MAX = 9, | |
29 | AUTH_MODE_MON = 10, | |
30 | AUTH_MODE_MON_MAX = 19, | |
31 | }; | |
32 | ||
7c673cae FG |
33 | |
34 | struct EntityAuth { | |
7c673cae | 35 | CryptoKey key; |
9f95a23c | 36 | std::map<std::string, ceph::buffer::list> caps; |
7c673cae | 37 | |
9f95a23c | 38 | void encode(ceph::buffer::list& bl) const { |
7c673cae | 39 | __u8 struct_v = 2; |
11fdf7f2 TL |
40 | using ceph::encode; |
41 | encode(struct_v, bl); | |
42 | encode((uint64_t)CEPH_AUTH_UID_DEFAULT, bl); | |
43 | encode(key, bl); | |
44 | encode(caps, bl); | |
7c673cae | 45 | } |
9f95a23c | 46 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 47 | using ceph::decode; |
7c673cae | 48 | __u8 struct_v; |
11fdf7f2 TL |
49 | decode(struct_v, bl); |
50 | if (struct_v >= 2) { | |
51 | uint64_t old_auid; | |
52 | decode(old_auid, bl); | |
53 | } | |
54 | decode(key, bl); | |
55 | decode(caps, bl); | |
7c673cae FG |
56 | } |
57 | }; | |
58 | WRITE_CLASS_ENCODER(EntityAuth) | |
59 | ||
9f95a23c | 60 | inline std::ostream& operator<<(std::ostream& out, const EntityAuth& a) { |
11fdf7f2 | 61 | return out << "auth(key=" << a.key << ")"; |
7c673cae FG |
62 | } |
63 | ||
64 | struct AuthCapsInfo { | |
65 | bool allow_all; | |
9f95a23c | 66 | ceph::buffer::list caps; |
7c673cae FG |
67 | |
68 | AuthCapsInfo() : allow_all(false) {} | |
69 | ||
9f95a23c | 70 | void encode(ceph::buffer::list& bl) const { |
11fdf7f2 | 71 | using ceph::encode; |
7c673cae | 72 | __u8 struct_v = 1; |
11fdf7f2 | 73 | encode(struct_v, bl); |
7c673cae | 74 | __u8 a = (__u8)allow_all; |
11fdf7f2 TL |
75 | encode(a, bl); |
76 | encode(caps, bl); | |
7c673cae | 77 | } |
9f95a23c | 78 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 79 | using ceph::decode; |
7c673cae | 80 | __u8 struct_v; |
11fdf7f2 | 81 | decode(struct_v, bl); |
7c673cae | 82 | __u8 a; |
11fdf7f2 | 83 | decode(a, bl); |
7c673cae | 84 | allow_all = (bool)a; |
11fdf7f2 | 85 | decode(caps, bl); |
7c673cae FG |
86 | } |
87 | }; | |
88 | WRITE_CLASS_ENCODER(AuthCapsInfo) | |
89 | ||
90 | /* | |
91 | * The ticket (if properly validated) authorizes the principal use | |
92 | * services as described by 'caps' during the specified validity | |
93 | * period. | |
94 | */ | |
95 | struct AuthTicket { | |
96 | EntityName name; | |
97 | uint64_t global_id; /* global instance id */ | |
7c673cae FG |
98 | utime_t created, renew_after, expires; |
99 | AuthCapsInfo caps; | |
100 | __u32 flags; | |
101 | ||
11fdf7f2 | 102 | AuthTicket() : global_id(0), flags(0){} |
7c673cae FG |
103 | |
104 | void init_timestamps(utime_t now, double ttl) { | |
105 | created = now; | |
106 | expires = now; | |
107 | expires += ttl; | |
108 | renew_after = now; | |
109 | renew_after += ttl / 2.0; | |
110 | } | |
111 | ||
9f95a23c | 112 | void encode(ceph::buffer::list& bl) const { |
11fdf7f2 | 113 | using ceph::encode; |
7c673cae | 114 | __u8 struct_v = 2; |
11fdf7f2 TL |
115 | encode(struct_v, bl); |
116 | encode(name, bl); | |
117 | encode(global_id, bl); | |
118 | encode((uint64_t)CEPH_AUTH_UID_DEFAULT, bl); | |
119 | encode(created, bl); | |
120 | encode(expires, bl); | |
121 | encode(caps, bl); | |
122 | encode(flags, bl); | |
123 | } | |
9f95a23c | 124 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 125 | using ceph::decode; |
7c673cae | 126 | __u8 struct_v; |
11fdf7f2 TL |
127 | decode(struct_v, bl); |
128 | decode(name, bl); | |
129 | decode(global_id, bl); | |
130 | if (struct_v >= 2) { | |
131 | uint64_t old_auid; | |
132 | decode(old_auid, bl); | |
133 | } | |
134 | decode(created, bl); | |
135 | decode(expires, bl); | |
136 | decode(caps, bl); | |
137 | decode(flags, bl); | |
7c673cae FG |
138 | } |
139 | }; | |
140 | WRITE_CLASS_ENCODER(AuthTicket) | |
141 | ||
142 | ||
143 | /* | |
144 | * abstract authorizer class | |
145 | */ | |
146 | struct AuthAuthorizer { | |
147 | __u32 protocol; | |
9f95a23c | 148 | ceph::buffer::list bl; |
7c673cae FG |
149 | CryptoKey session_key; |
150 | ||
151 | explicit AuthAuthorizer(__u32 p) : protocol(p) {} | |
152 | virtual ~AuthAuthorizer() {} | |
9f95a23c | 153 | virtual bool verify_reply(ceph::buffer::list::const_iterator& reply, |
11fdf7f2 | 154 | std::string *connection_secret) = 0; |
9f95a23c TL |
155 | virtual bool add_challenge(CephContext *cct, |
156 | const ceph::buffer::list& challenge) = 0; | |
28e407b8 AA |
157 | }; |
158 | ||
159 | struct AuthAuthorizerChallenge { | |
160 | virtual ~AuthAuthorizerChallenge() {} | |
7c673cae FG |
161 | }; |
162 | ||
11fdf7f2 TL |
163 | struct AuthConnectionMeta { |
164 | uint32_t auth_method = CEPH_AUTH_UNKNOWN; //< CEPH_AUTH_* | |
165 | ||
166 | /// client: initial empty, but populated if server said bad method | |
167 | std::vector<uint32_t> allowed_methods; | |
168 | ||
169 | int auth_mode = AUTH_MODE_NONE; ///< AUTH_MODE_* | |
170 | ||
171 | int con_mode = 0; ///< negotiated mode | |
172 | ||
173 | bool is_mode_crc() const { | |
174 | return con_mode == CEPH_CON_MODE_CRC; | |
175 | } | |
176 | bool is_mode_secure() const { | |
177 | return con_mode == CEPH_CON_MODE_SECURE; | |
178 | } | |
179 | ||
180 | CryptoKey session_key; ///< per-ticket key | |
181 | ||
182 | size_t get_connection_secret_length() const { | |
183 | switch (con_mode) { | |
184 | case CEPH_CON_MODE_CRC: | |
185 | return 0; | |
186 | case CEPH_CON_MODE_SECURE: | |
187 | return 16 * 4; | |
188 | } | |
189 | return 0; | |
190 | } | |
191 | std::string connection_secret; ///< per-connection key | |
192 | ||
193 | std::unique_ptr<AuthAuthorizer> authorizer; | |
194 | std::unique_ptr<AuthAuthorizerChallenge> authorizer_challenge; | |
195 | }; | |
7c673cae FG |
196 | |
197 | /* | |
198 | * Key management | |
199 | */ | |
200 | #define KEY_ROTATE_NUM 3 /* prev, current, next */ | |
201 | ||
202 | struct ExpiringCryptoKey { | |
203 | CryptoKey key; | |
204 | utime_t expiration; | |
205 | ||
9f95a23c | 206 | void encode(ceph::buffer::list& bl) const { |
11fdf7f2 | 207 | using ceph::encode; |
7c673cae | 208 | __u8 struct_v = 1; |
11fdf7f2 TL |
209 | encode(struct_v, bl); |
210 | encode(key, bl); | |
211 | encode(expiration, bl); | |
7c673cae | 212 | } |
9f95a23c | 213 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 214 | using ceph::decode; |
7c673cae | 215 | __u8 struct_v; |
11fdf7f2 TL |
216 | decode(struct_v, bl); |
217 | decode(key, bl); | |
218 | decode(expiration, bl); | |
7c673cae FG |
219 | } |
220 | }; | |
221 | WRITE_CLASS_ENCODER(ExpiringCryptoKey) | |
222 | ||
9f95a23c | 223 | inline std::ostream& operator<<(std::ostream& out, const ExpiringCryptoKey& c) |
7c673cae FG |
224 | { |
225 | return out << c.key << " expires " << c.expiration; | |
226 | } | |
227 | ||
228 | struct RotatingSecrets { | |
9f95a23c | 229 | std::map<uint64_t, ExpiringCryptoKey> secrets; |
7c673cae | 230 | version_t max_ver; |
9f95a23c | 231 | |
7c673cae | 232 | RotatingSecrets() : max_ver(0) {} |
9f95a23c TL |
233 | |
234 | void encode(ceph::buffer::list& bl) const { | |
11fdf7f2 | 235 | using ceph::encode; |
7c673cae | 236 | __u8 struct_v = 1; |
11fdf7f2 TL |
237 | encode(struct_v, bl); |
238 | encode(secrets, bl); | |
239 | encode(max_ver, bl); | |
7c673cae | 240 | } |
9f95a23c | 241 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 242 | using ceph::decode; |
7c673cae | 243 | __u8 struct_v; |
11fdf7f2 TL |
244 | decode(struct_v, bl); |
245 | decode(secrets, bl); | |
246 | decode(max_ver, bl); | |
7c673cae FG |
247 | } |
248 | ||
249 | uint64_t add(ExpiringCryptoKey& key) { | |
250 | secrets[++max_ver] = key; | |
251 | while (secrets.size() > KEY_ROTATE_NUM) | |
252 | secrets.erase(secrets.begin()); | |
253 | return max_ver; | |
254 | } | |
255 | ||
256 | bool need_new_secrets() const { | |
257 | return secrets.size() < KEY_ROTATE_NUM; | |
258 | } | |
9f95a23c | 259 | bool need_new_secrets(const utime_t& now) const { |
7c673cae FG |
260 | return secrets.size() < KEY_ROTATE_NUM || current().expiration <= now; |
261 | } | |
262 | ||
263 | ExpiringCryptoKey& previous() { | |
264 | return secrets.begin()->second; | |
265 | } | |
266 | ExpiringCryptoKey& current() { | |
9f95a23c | 267 | auto p = secrets.begin(); |
7c673cae FG |
268 | ++p; |
269 | return p->second; | |
270 | } | |
271 | const ExpiringCryptoKey& current() const { | |
9f95a23c | 272 | auto p = secrets.begin(); |
7c673cae FG |
273 | ++p; |
274 | return p->second; | |
275 | } | |
276 | ExpiringCryptoKey& next() { | |
277 | return secrets.rbegin()->second; | |
278 | } | |
279 | bool empty() { | |
280 | return secrets.empty(); | |
281 | } | |
282 | ||
283 | void dump(); | |
284 | }; | |
285 | WRITE_CLASS_ENCODER(RotatingSecrets) | |
286 | ||
287 | ||
288 | ||
289 | class KeyStore { | |
290 | public: | |
291 | virtual ~KeyStore() {} | |
292 | virtual bool get_secret(const EntityName& name, CryptoKey& secret) const = 0; | |
293 | virtual bool get_service_secret(uint32_t service_id, uint64_t secret_id, | |
294 | CryptoKey& secret) const = 0; | |
295 | }; | |
296 | ||
11fdf7f2 | 297 | inline bool auth_principal_needs_rotating_keys(EntityName& name) |
7c673cae FG |
298 | { |
299 | uint32_t ty(name.get_type()); | |
300 | return ((ty == CEPH_ENTITY_TYPE_OSD) | |
301 | || (ty == CEPH_ENTITY_TYPE_MDS) | |
302 | || (ty == CEPH_ENTITY_TYPE_MGR)); | |
303 | } | |
304 | ||
305 | #endif |