]>
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 | ||
21 | class Cond; | |
22 | ||
23 | struct EntityAuth { | |
24 | uint64_t auid; | |
25 | CryptoKey key; | |
26 | map<string, bufferlist> caps; | |
27 | ||
28 | EntityAuth() : auid(CEPH_AUTH_UID_DEFAULT) {} | |
29 | ||
30 | void encode(bufferlist& bl) const { | |
31 | __u8 struct_v = 2; | |
32 | ::encode(struct_v, bl); | |
33 | ::encode(auid, bl); | |
34 | ::encode(key, bl); | |
35 | ::encode(caps, bl); | |
36 | } | |
37 | void decode(bufferlist::iterator& bl) { | |
38 | __u8 struct_v; | |
39 | ::decode(struct_v, bl); | |
40 | if (struct_v >= 2) | |
41 | ::decode(auid, bl); | |
42 | else auid = CEPH_AUTH_UID_DEFAULT; | |
43 | ::decode(key, bl); | |
44 | ::decode(caps, bl); | |
45 | } | |
46 | }; | |
47 | WRITE_CLASS_ENCODER(EntityAuth) | |
48 | ||
49 | static inline ostream& operator<<(ostream& out, const EntityAuth& a) { | |
50 | return out << "auth(auid = " << a.auid << " key=" << a.key << " with " << a.caps.size() << " caps)"; | |
51 | } | |
52 | ||
53 | struct AuthCapsInfo { | |
54 | bool allow_all; | |
55 | bufferlist caps; | |
56 | ||
57 | AuthCapsInfo() : allow_all(false) {} | |
58 | ||
59 | void encode(bufferlist& bl) const { | |
60 | __u8 struct_v = 1; | |
61 | ::encode(struct_v, bl); | |
62 | __u8 a = (__u8)allow_all; | |
63 | ::encode(a, bl); | |
64 | ::encode(caps, bl); | |
65 | } | |
66 | void decode(bufferlist::iterator& bl) { | |
67 | __u8 struct_v; | |
68 | ::decode(struct_v, bl); | |
69 | __u8 a; | |
70 | ::decode(a, bl); | |
71 | allow_all = (bool)a; | |
72 | ::decode(caps, bl); | |
73 | } | |
74 | }; | |
75 | WRITE_CLASS_ENCODER(AuthCapsInfo) | |
76 | ||
77 | /* | |
78 | * The ticket (if properly validated) authorizes the principal use | |
79 | * services as described by 'caps' during the specified validity | |
80 | * period. | |
81 | */ | |
82 | struct AuthTicket { | |
83 | EntityName name; | |
84 | uint64_t global_id; /* global instance id */ | |
85 | uint64_t auid; | |
86 | utime_t created, renew_after, expires; | |
87 | AuthCapsInfo caps; | |
88 | __u32 flags; | |
89 | ||
90 | AuthTicket() : global_id(0), auid(CEPH_AUTH_UID_DEFAULT), flags(0){} | |
91 | ||
92 | void init_timestamps(utime_t now, double ttl) { | |
93 | created = now; | |
94 | expires = now; | |
95 | expires += ttl; | |
96 | renew_after = now; | |
97 | renew_after += ttl / 2.0; | |
98 | } | |
99 | ||
100 | void encode(bufferlist& bl) const { | |
101 | __u8 struct_v = 2; | |
102 | ::encode(struct_v, bl); | |
103 | ::encode(name, bl); | |
104 | ::encode(global_id, bl); | |
105 | ::encode(auid, bl); | |
106 | ::encode(created, bl); | |
107 | ::encode(expires, bl); | |
108 | ::encode(caps, bl); | |
109 | ::encode(flags, bl); | |
110 | } | |
111 | void decode(bufferlist::iterator& bl) { | |
112 | __u8 struct_v; | |
113 | ::decode(struct_v, bl); | |
114 | ::decode(name, bl); | |
115 | ::decode(global_id, bl); | |
116 | if (struct_v >= 2) | |
117 | ::decode(auid, bl); | |
118 | else auid = CEPH_AUTH_UID_DEFAULT; | |
119 | ::decode(created, bl); | |
120 | ::decode(expires, bl); | |
121 | ::decode(caps, bl); | |
122 | ::decode(flags, bl); | |
123 | } | |
124 | }; | |
125 | WRITE_CLASS_ENCODER(AuthTicket) | |
126 | ||
127 | ||
128 | /* | |
129 | * abstract authorizer class | |
130 | */ | |
131 | struct AuthAuthorizer { | |
132 | __u32 protocol; | |
133 | bufferlist bl; | |
134 | CryptoKey session_key; | |
135 | ||
136 | explicit AuthAuthorizer(__u32 p) : protocol(p) {} | |
137 | virtual ~AuthAuthorizer() {} | |
138 | virtual bool verify_reply(bufferlist::iterator& reply) = 0; | |
139 | }; | |
140 | ||
141 | ||
142 | /* | |
143 | * Key management | |
144 | */ | |
145 | #define KEY_ROTATE_NUM 3 /* prev, current, next */ | |
146 | ||
147 | struct ExpiringCryptoKey { | |
148 | CryptoKey key; | |
149 | utime_t expiration; | |
150 | ||
151 | void encode(bufferlist& bl) const { | |
152 | __u8 struct_v = 1; | |
153 | ::encode(struct_v, bl); | |
154 | ::encode(key, bl); | |
155 | ::encode(expiration, bl); | |
156 | } | |
157 | void decode(bufferlist::iterator& bl) { | |
158 | __u8 struct_v; | |
159 | ::decode(struct_v, bl); | |
160 | ::decode(key, bl); | |
161 | ::decode(expiration, bl); | |
162 | } | |
163 | }; | |
164 | WRITE_CLASS_ENCODER(ExpiringCryptoKey) | |
165 | ||
166 | static inline ostream& operator<<(ostream& out, const ExpiringCryptoKey& c) | |
167 | { | |
168 | return out << c.key << " expires " << c.expiration; | |
169 | } | |
170 | ||
171 | struct RotatingSecrets { | |
172 | map<uint64_t, ExpiringCryptoKey> secrets; | |
173 | version_t max_ver; | |
174 | ||
175 | RotatingSecrets() : max_ver(0) {} | |
176 | ||
177 | void encode(bufferlist& bl) const { | |
178 | __u8 struct_v = 1; | |
179 | ::encode(struct_v, bl); | |
180 | ::encode(secrets, bl); | |
181 | ::encode(max_ver, bl); | |
182 | } | |
183 | void decode(bufferlist::iterator& bl) { | |
184 | __u8 struct_v; | |
185 | ::decode(struct_v, bl); | |
186 | ::decode(secrets, bl); | |
187 | ::decode(max_ver, bl); | |
188 | } | |
189 | ||
190 | uint64_t add(ExpiringCryptoKey& key) { | |
191 | secrets[++max_ver] = key; | |
192 | while (secrets.size() > KEY_ROTATE_NUM) | |
193 | secrets.erase(secrets.begin()); | |
194 | return max_ver; | |
195 | } | |
196 | ||
197 | bool need_new_secrets() const { | |
198 | return secrets.size() < KEY_ROTATE_NUM; | |
199 | } | |
200 | bool need_new_secrets(utime_t now) const { | |
201 | return secrets.size() < KEY_ROTATE_NUM || current().expiration <= now; | |
202 | } | |
203 | ||
204 | ExpiringCryptoKey& previous() { | |
205 | return secrets.begin()->second; | |
206 | } | |
207 | ExpiringCryptoKey& current() { | |
208 | map<uint64_t, ExpiringCryptoKey>::iterator p = secrets.begin(); | |
209 | ++p; | |
210 | return p->second; | |
211 | } | |
212 | const ExpiringCryptoKey& current() const { | |
213 | map<uint64_t, ExpiringCryptoKey>::const_iterator p = secrets.begin(); | |
214 | ++p; | |
215 | return p->second; | |
216 | } | |
217 | ExpiringCryptoKey& next() { | |
218 | return secrets.rbegin()->second; | |
219 | } | |
220 | bool empty() { | |
221 | return secrets.empty(); | |
222 | } | |
223 | ||
224 | void dump(); | |
225 | }; | |
226 | WRITE_CLASS_ENCODER(RotatingSecrets) | |
227 | ||
228 | ||
229 | ||
230 | class KeyStore { | |
231 | public: | |
232 | virtual ~KeyStore() {} | |
233 | virtual bool get_secret(const EntityName& name, CryptoKey& secret) const = 0; | |
234 | virtual bool get_service_secret(uint32_t service_id, uint64_t secret_id, | |
235 | CryptoKey& secret) const = 0; | |
236 | }; | |
237 | ||
238 | static inline bool auth_principal_needs_rotating_keys(EntityName& name) | |
239 | { | |
240 | uint32_t ty(name.get_type()); | |
241 | return ((ty == CEPH_ENTITY_TYPE_OSD) | |
242 | || (ty == CEPH_ENTITY_TYPE_MDS) | |
243 | || (ty == CEPH_ENTITY_TYPE_MGR)); | |
244 | } | |
245 | ||
246 | #endif |