]> git.proxmox.com Git - ceph.git/blob - ceph/src/auth/cephx/CephxProtocol.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / auth / cephx / CephxProtocol.h
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_CEPHXPROTOCOL_H
16 #define CEPH_CEPHXPROTOCOL_H
17
18 /*
19 Ceph X protocol
20
21 See doc/dev/cephx.rst
22
23 */
24
25 /* authenticate requests */
26 #define CEPHX_GET_AUTH_SESSION_KEY 0x0100
27 #define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
28 #define CEPHX_GET_ROTATING_KEY 0x0400
29
30 #define CEPHX_REQUEST_TYPE_MASK 0x0F00
31 #define CEPHX_CRYPT_ERR 1
32
33 #include "auth/Auth.h"
34 #include <errno.h>
35 #include <sstream>
36
37 class CephContext;
38
39 /*
40 * Authentication
41 */
42
43 // initial server -> client challenge
44 struct CephXServerChallenge {
45 uint64_t server_challenge;
46
47 void encode(bufferlist& bl) const {
48 using ceph::encode;
49 __u8 struct_v = 1;
50 encode(struct_v, bl);
51 encode(server_challenge, bl);
52 }
53 void decode(bufferlist::const_iterator& bl) {
54 using ceph::decode;
55 __u8 struct_v;
56 decode(struct_v, bl);
57 decode(server_challenge, bl);
58 }
59 };
60 WRITE_CLASS_ENCODER(CephXServerChallenge)
61
62
63 // request/reply headers, for subsequent exchanges.
64
65 struct CephXRequestHeader {
66 __u16 request_type;
67
68 void encode(bufferlist& bl) const {
69 using ceph::encode;
70 encode(request_type, bl);
71 }
72 void decode(bufferlist::const_iterator& bl) {
73 using ceph::decode;
74 decode(request_type, bl);
75 }
76 };
77 WRITE_CLASS_ENCODER(CephXRequestHeader)
78
79 struct CephXResponseHeader {
80 uint16_t request_type;
81 int32_t status;
82
83 void encode(bufferlist& bl) const {
84 using ceph::encode;
85 encode(request_type, bl);
86 encode(status, bl);
87 }
88 void decode(bufferlist::const_iterator& bl) {
89 using ceph::decode;
90 decode(request_type, bl);
91 decode(status, bl);
92 }
93 };
94 WRITE_CLASS_ENCODER(CephXResponseHeader)
95
96 struct CephXTicketBlob {
97 uint64_t secret_id;
98 bufferlist blob;
99
100 CephXTicketBlob() : secret_id(0) {}
101
102 void encode(bufferlist& bl) const {
103 using ceph::encode;
104 __u8 struct_v = 1;
105 encode(struct_v, bl);
106 encode(secret_id, bl);
107 encode(blob, bl);
108 }
109
110 void decode(bufferlist::const_iterator& bl) {
111 using ceph::decode;
112 __u8 struct_v;
113 decode(struct_v, bl);
114 decode(secret_id, bl);
115 decode(blob, bl);
116 }
117 };
118 WRITE_CLASS_ENCODER(CephXTicketBlob)
119
120 // client -> server response to challenge
121 struct CephXAuthenticate {
122 uint64_t client_challenge;
123 uint64_t key;
124 CephXTicketBlob old_ticket;
125 uint32_t other_keys = 0; // replaces CephXServiceTicketRequest
126
127 void encode(bufferlist& bl) const {
128 using ceph::encode;
129 __u8 struct_v = 2;
130 encode(struct_v, bl);
131 encode(client_challenge, bl);
132 encode(key, bl);
133 encode(old_ticket, bl);
134 encode(other_keys, bl);
135 }
136 void decode(bufferlist::const_iterator& bl) {
137 using ceph::decode;
138 __u8 struct_v;
139 decode(struct_v, bl);
140 decode(client_challenge, bl);
141 decode(key, bl);
142 decode(old_ticket, bl);
143 if (struct_v >= 2) {
144 decode(other_keys, bl);
145 }
146 }
147 };
148 WRITE_CLASS_ENCODER(CephXAuthenticate)
149
150 struct CephXChallengeBlob {
151 uint64_t server_challenge, client_challenge;
152
153 void encode(bufferlist& bl) const {
154 using ceph::encode;
155 encode(server_challenge, bl);
156 encode(client_challenge, bl);
157 }
158 void decode(bufferlist::const_iterator& bl) {
159 using ceph::decode;
160 decode(server_challenge, bl);
161 decode(client_challenge, bl);
162 }
163 };
164 WRITE_CLASS_ENCODER(CephXChallengeBlob)
165
166 void cephx_calc_client_server_challenge(CephContext *cct,
167 CryptoKey& secret, uint64_t server_challenge, uint64_t client_challenge,
168 uint64_t *key, std::string &error);
169
170
171 /*
172 * getting service tickets
173 */
174 struct CephXSessionAuthInfo {
175 uint32_t service_id;
176 uint64_t secret_id;
177 AuthTicket ticket;
178 CryptoKey session_key;
179 CryptoKey service_secret;
180 utime_t validity;
181 };
182
183
184 extern bool cephx_build_service_ticket_blob(CephContext *cct,
185 CephXSessionAuthInfo& ticket_info, CephXTicketBlob& blob);
186
187 extern void cephx_build_service_ticket_request(CephContext *cct,
188 uint32_t keys,
189 bufferlist& request);
190
191 extern bool cephx_build_service_ticket_reply(CephContext *cct,
192 CryptoKey& principal_secret,
193 vector<CephXSessionAuthInfo> ticket_info,
194 bool should_encrypt_ticket,
195 CryptoKey& ticket_enc_key,
196 bufferlist& reply);
197
198 struct CephXServiceTicketRequest {
199 uint32_t keys;
200
201 void encode(bufferlist& bl) const {
202 using ceph::encode;
203 __u8 struct_v = 1;
204 encode(struct_v, bl);
205 encode(keys, bl);
206 }
207 void decode(bufferlist::const_iterator& bl) {
208 using ceph::decode;
209 __u8 struct_v;
210 decode(struct_v, bl);
211 decode(keys, bl);
212 }
213 };
214 WRITE_CLASS_ENCODER(CephXServiceTicketRequest)
215
216
217 /*
218 * Authorize
219 */
220
221 struct CephXAuthorizeReply {
222 uint64_t nonce_plus_one;
223 std::string connection_secret;
224 void encode(bufferlist& bl) const {
225 using ceph::encode;
226 __u8 struct_v = 1;
227 if (connection_secret.size()) {
228 struct_v = 2;
229 }
230 encode(struct_v, bl);
231 encode(nonce_plus_one, bl);
232 if (struct_v >= 2) {
233 struct_v = 2;
234 encode(connection_secret, bl);
235 }
236 }
237 void decode(bufferlist::const_iterator& bl) {
238 using ceph::decode;
239 __u8 struct_v;
240 decode(struct_v, bl);
241 decode(nonce_plus_one, bl);
242 if (struct_v >= 2) {
243 decode(connection_secret, bl);
244 }
245 }
246 };
247 WRITE_CLASS_ENCODER(CephXAuthorizeReply)
248
249
250 struct CephXAuthorizer : public AuthAuthorizer {
251 private:
252 CephContext *cct;
253 public:
254 uint64_t nonce;
255 bufferlist base_bl;
256
257 explicit CephXAuthorizer(CephContext *cct_)
258 : AuthAuthorizer(CEPH_AUTH_CEPHX), cct(cct_), nonce(0) {}
259
260 bool build_authorizer();
261 bool verify_reply(bufferlist::const_iterator& reply,
262 std::string *connection_secret) override;
263 bool add_challenge(CephContext *cct, const bufferlist& challenge) override;
264 };
265
266
267
268 /*
269 * TicketHandler
270 */
271 struct CephXTicketHandler {
272 uint32_t service_id;
273 CryptoKey session_key;
274 CephXTicketBlob ticket; // opaque to us
275 utime_t renew_after, expires;
276 bool have_key_flag;
277
278 CephXTicketHandler(CephContext *cct_, uint32_t service_id_)
279 : service_id(service_id_), have_key_flag(false), cct(cct_) { }
280
281 // to build our ServiceTicket
282 bool verify_service_ticket_reply(CryptoKey& principal_secret,
283 bufferlist::const_iterator& indata);
284 // to access the service
285 CephXAuthorizer *build_authorizer(uint64_t global_id) const;
286
287 bool have_key();
288 bool need_key() const;
289
290 void invalidate_ticket() {
291 have_key_flag = 0;
292 }
293 private:
294 CephContext *cct;
295 };
296
297 struct CephXTicketManager {
298 typedef map<uint32_t, CephXTicketHandler> tickets_map_t;
299 tickets_map_t tickets_map;
300 uint64_t global_id;
301
302 explicit CephXTicketManager(CephContext *cct_) : global_id(0), cct(cct_) {}
303
304 bool verify_service_ticket_reply(CryptoKey& principal_secret,
305 bufferlist::const_iterator& indata);
306
307 CephXTicketHandler& get_handler(uint32_t type) {
308 tickets_map_t::iterator i = tickets_map.find(type);
309 if (i != tickets_map.end())
310 return i->second;
311 CephXTicketHandler newTicketHandler(cct, type);
312 std::pair < tickets_map_t::iterator, bool > res =
313 tickets_map.insert(std::make_pair(type, newTicketHandler));
314 ceph_assert(res.second);
315 return res.first->second;
316 }
317 CephXAuthorizer *build_authorizer(uint32_t service_id) const;
318 bool have_key(uint32_t service_id);
319 bool need_key(uint32_t service_id) const;
320 void set_have_need_key(uint32_t service_id, uint32_t& have, uint32_t& need);
321 void validate_tickets(uint32_t mask, uint32_t& have, uint32_t& need);
322 void invalidate_ticket(uint32_t service_id);
323
324 private:
325 CephContext *cct;
326 };
327
328
329 /* A */
330 struct CephXServiceTicket {
331 CryptoKey session_key;
332 utime_t validity;
333
334 void encode(bufferlist& bl) const {
335 using ceph::encode;
336 __u8 struct_v = 1;
337 encode(struct_v, bl);
338 encode(session_key, bl);
339 encode(validity, bl);
340 }
341 void decode(bufferlist::const_iterator& bl) {
342 using ceph::decode;
343 __u8 struct_v;
344 decode(struct_v, bl);
345 decode(session_key, bl);
346 decode(validity, bl);
347 }
348 };
349 WRITE_CLASS_ENCODER(CephXServiceTicket)
350
351 /* B */
352 struct CephXServiceTicketInfo {
353 AuthTicket ticket;
354 CryptoKey session_key;
355
356 void encode(bufferlist& bl) const {
357 using ceph::encode;
358 __u8 struct_v = 1;
359 encode(struct_v, bl);
360 encode(ticket, bl);
361 encode(session_key, bl);
362 }
363 void decode(bufferlist::const_iterator& bl) {
364 using ceph::decode;
365 __u8 struct_v;
366 decode(struct_v, bl);
367 decode(ticket, bl);
368 decode(session_key, bl);
369 }
370 };
371 WRITE_CLASS_ENCODER(CephXServiceTicketInfo)
372
373 struct CephXAuthorizeChallenge : public AuthAuthorizerChallenge {
374 uint64_t server_challenge;
375 void encode(bufferlist& bl) const {
376 using ceph::encode;
377 __u8 struct_v = 1;
378 encode(struct_v, bl);
379 encode(server_challenge, bl);
380 }
381 void decode(bufferlist::const_iterator& bl) {
382 using ceph::decode;
383 __u8 struct_v;
384 decode(struct_v, bl);
385 decode(server_challenge, bl);
386 }
387 };
388 WRITE_CLASS_ENCODER(CephXAuthorizeChallenge)
389
390 struct CephXAuthorize {
391 uint64_t nonce;
392 bool have_challenge = false;
393 uint64_t server_challenge_plus_one = 0;
394 void encode(bufferlist& bl) const {
395 using ceph::encode;
396 __u8 struct_v = 2;
397 encode(struct_v, bl);
398 encode(nonce, bl);
399 encode(have_challenge, bl);
400 encode(server_challenge_plus_one, bl);
401 }
402 void decode(bufferlist::const_iterator& bl) {
403 using ceph::decode;
404 __u8 struct_v;
405 decode(struct_v, bl);
406 decode(nonce, bl);
407 if (struct_v >= 2) {
408 decode(have_challenge, bl);
409 decode(server_challenge_plus_one, bl);
410 }
411 }
412 };
413 WRITE_CLASS_ENCODER(CephXAuthorize)
414
415 /*
416 * Decode an extract ticket
417 */
418 bool cephx_decode_ticket(CephContext *cct, KeyStore *keys,
419 uint32_t service_id, CephXTicketBlob& ticket_blob,
420 CephXServiceTicketInfo& ticket_info);
421
422 /*
423 * Verify authorizer and generate reply authorizer
424 */
425 extern bool cephx_verify_authorizer(
426 CephContext *cct,
427 KeyStore *keys,
428 bufferlist::const_iterator& indata,
429 size_t connection_secret_required_len,
430 CephXServiceTicketInfo& ticket_info,
431 std::unique_ptr<AuthAuthorizerChallenge> *challenge,
432 std::string *connection_secret,
433 bufferlist *reply_bl);
434
435
436
437
438
439
440 /*
441 * encode+encrypt macros
442 */
443 static constexpr uint64_t AUTH_ENC_MAGIC = 0xff009cad8826aa55ull;
444
445 template <typename T>
446 void decode_decrypt_enc_bl(CephContext *cct, T& t, CryptoKey key,
447 const bufferlist& bl_enc,
448 std::string &error)
449 {
450 uint64_t magic;
451 bufferlist bl;
452
453 if (key.decrypt(cct, bl_enc, bl, &error) < 0)
454 return;
455
456 auto iter2 = bl.cbegin();
457 __u8 struct_v;
458 decode(struct_v, iter2);
459 decode(magic, iter2);
460 if (magic != AUTH_ENC_MAGIC) {
461 ostringstream oss;
462 oss << "bad magic in decode_decrypt, " << magic << " != " << AUTH_ENC_MAGIC;
463 error = oss.str();
464 return;
465 }
466
467 decode(t, iter2);
468 }
469
470 template <typename T>
471 void encode_encrypt_enc_bl(CephContext *cct, const T& t, const CryptoKey& key,
472 bufferlist& out, std::string &error)
473 {
474 bufferlist bl;
475 __u8 struct_v = 1;
476 encode(struct_v, bl);
477 uint64_t magic = AUTH_ENC_MAGIC;
478 encode(magic, bl);
479 encode(t, bl);
480
481 key.encrypt(cct, bl, out, &error);
482 }
483
484 template <typename T>
485 int decode_decrypt(CephContext *cct, T& t, const CryptoKey& key,
486 bufferlist::const_iterator& iter, std::string &error)
487 {
488 bufferlist bl_enc;
489 try {
490 decode(bl_enc, iter);
491 decode_decrypt_enc_bl(cct, t, key, bl_enc, error);
492 }
493 catch (buffer::error &e) {
494 error = "error decoding block for decryption";
495 }
496 if (!error.empty())
497 return CEPHX_CRYPT_ERR;
498 return 0;
499 }
500
501 template <typename T>
502 int encode_encrypt(CephContext *cct, const T& t, const CryptoKey& key,
503 bufferlist& out, std::string &error)
504 {
505 bufferlist bl_enc;
506 encode_encrypt_enc_bl(cct, t, key, bl_enc, error);
507 if (!error.empty()){
508 return CEPHX_CRYPT_ERR;
509 }
510 encode(bl_enc, out);
511 return 0;
512 }
513
514 #endif