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