]> git.proxmox.com Git - ceph.git/blame - ceph/src/auth/cephx/CephxProtocol.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / auth / cephx / CephxProtocol.h
CommitLineData
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_CEPHXPROTOCOL_H
16#define CEPH_CEPHXPROTOCOL_H
17
18/*
19 Ceph X protocol
20
11fdf7f2 21 See doc/dev/cephx.rst
7c673cae 22
7c673cae
FG
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
9f95a23c 37#include "include/common_fwd.h"
7c673cae
FG
38/*
39 * Authentication
40 */
41
42// initial server -> client challenge
43struct CephXServerChallenge {
44 uint64_t server_challenge;
45
46 void encode(bufferlist& bl) const {
11fdf7f2 47 using ceph::encode;
7c673cae 48 __u8 struct_v = 1;
11fdf7f2
TL
49 encode(struct_v, bl);
50 encode(server_challenge, bl);
7c673cae 51 }
11fdf7f2
TL
52 void decode(bufferlist::const_iterator& bl) {
53 using ceph::decode;
7c673cae 54 __u8 struct_v;
11fdf7f2
TL
55 decode(struct_v, bl);
56 decode(server_challenge, bl);
7c673cae
FG
57 }
58};
59WRITE_CLASS_ENCODER(CephXServerChallenge)
60
61
62// request/reply headers, for subsequent exchanges.
63
64struct CephXRequestHeader {
65 __u16 request_type;
66
67 void encode(bufferlist& bl) const {
11fdf7f2
TL
68 using ceph::encode;
69 encode(request_type, bl);
7c673cae 70 }
11fdf7f2
TL
71 void decode(bufferlist::const_iterator& bl) {
72 using ceph::decode;
73 decode(request_type, bl);
7c673cae
FG
74 }
75};
76WRITE_CLASS_ENCODER(CephXRequestHeader)
77
78struct CephXResponseHeader {
79 uint16_t request_type;
80 int32_t status;
81
82 void encode(bufferlist& bl) const {
11fdf7f2
TL
83 using ceph::encode;
84 encode(request_type, bl);
85 encode(status, bl);
7c673cae 86 }
11fdf7f2
TL
87 void decode(bufferlist::const_iterator& bl) {
88 using ceph::decode;
89 decode(request_type, bl);
90 decode(status, bl);
7c673cae
FG
91 }
92};
93WRITE_CLASS_ENCODER(CephXResponseHeader)
94
95struct CephXTicketBlob {
96 uint64_t secret_id;
97 bufferlist blob;
98
99 CephXTicketBlob() : secret_id(0) {}
100
101 void encode(bufferlist& bl) const {
11fdf7f2 102 using ceph::encode;
7c673cae 103 __u8 struct_v = 1;
11fdf7f2
TL
104 encode(struct_v, bl);
105 encode(secret_id, bl);
106 encode(blob, bl);
7c673cae
FG
107 }
108
11fdf7f2
TL
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);
7c673cae
FG
115 }
116};
117WRITE_CLASS_ENCODER(CephXTicketBlob)
118
119// client -> server response to challenge
120struct CephXAuthenticate {
121 uint64_t client_challenge;
122 uint64_t key;
123 CephXTicketBlob old_ticket;
11fdf7f2 124 uint32_t other_keys = 0; // replaces CephXServiceTicketRequest
7c673cae
FG
125
126 void encode(bufferlist& bl) const {
11fdf7f2
TL
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);
7c673cae 134 }
11fdf7f2
TL
135 void decode(bufferlist::const_iterator& bl) {
136 using ceph::decode;
7c673cae 137 __u8 struct_v;
11fdf7f2
TL
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 }
7c673cae
FG
146};
147WRITE_CLASS_ENCODER(CephXAuthenticate)
148
149struct CephXChallengeBlob {
150 uint64_t server_challenge, client_challenge;
151
152 void encode(bufferlist& bl) const {
11fdf7f2
TL
153 using ceph::encode;
154 encode(server_challenge, bl);
155 encode(client_challenge, bl);
7c673cae 156 }
11fdf7f2
TL
157 void decode(bufferlist::const_iterator& bl) {
158 using ceph::decode;
159 decode(server_challenge, bl);
160 decode(client_challenge, bl);
7c673cae
FG
161 }
162};
163WRITE_CLASS_ENCODER(CephXChallengeBlob)
164
165void 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 */
173struct 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
183extern bool cephx_build_service_ticket_blob(CephContext *cct,
184 CephXSessionAuthInfo& ticket_info, CephXTicketBlob& blob);
185
186extern void cephx_build_service_ticket_request(CephContext *cct,
187 uint32_t keys,
188 bufferlist& request);
189
190extern 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
197struct CephXServiceTicketRequest {
198 uint32_t keys;
199
200 void encode(bufferlist& bl) const {
11fdf7f2 201 using ceph::encode;
7c673cae 202 __u8 struct_v = 1;
11fdf7f2
TL
203 encode(struct_v, bl);
204 encode(keys, bl);
7c673cae 205 }
11fdf7f2
TL
206 void decode(bufferlist::const_iterator& bl) {
207 using ceph::decode;
7c673cae 208 __u8 struct_v;
11fdf7f2
TL
209 decode(struct_v, bl);
210 decode(keys, bl);
7c673cae
FG
211 }
212};
213WRITE_CLASS_ENCODER(CephXServiceTicketRequest)
214
215
216/*
217 * Authorize
218 */
219
220struct CephXAuthorizeReply {
221 uint64_t nonce_plus_one;
11fdf7f2 222 std::string connection_secret;
7c673cae 223 void encode(bufferlist& bl) const {
11fdf7f2 224 using ceph::encode;
7c673cae 225 __u8 struct_v = 1;
11fdf7f2
TL
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 }
7c673cae 235 }
11fdf7f2
TL
236 void decode(bufferlist::const_iterator& bl) {
237 using ceph::decode;
7c673cae 238 __u8 struct_v;
11fdf7f2
TL
239 decode(struct_v, bl);
240 decode(nonce_plus_one, bl);
241 if (struct_v >= 2) {
242 decode(connection_secret, bl);
243 }
7c673cae
FG
244 }
245};
246WRITE_CLASS_ENCODER(CephXAuthorizeReply)
247
248
249struct CephXAuthorizer : public AuthAuthorizer {
250private:
251 CephContext *cct;
252public:
253 uint64_t nonce;
28e407b8 254 bufferlist base_bl;
7c673cae
FG
255
256 explicit CephXAuthorizer(CephContext *cct_)
257 : AuthAuthorizer(CEPH_AUTH_CEPHX), cct(cct_), nonce(0) {}
258
259 bool build_authorizer();
11fdf7f2
TL
260 bool verify_reply(bufferlist::const_iterator& reply,
261 std::string *connection_secret) override;
262 bool add_challenge(CephContext *cct, const bufferlist& challenge) override;
7c673cae
FG
263};
264
265
266
267/*
268 * TicketHandler
269 */
270struct 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,
11fdf7f2 282 bufferlist::const_iterator& indata);
7c673cae
FG
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 }
292private:
293 CephContext *cct;
294};
295
296struct 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,
11fdf7f2 304 bufferlist::const_iterator& indata);
7c673cae
FG
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));
11fdf7f2 313 ceph_assert(res.second);
7c673cae
FG
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
323private:
324 CephContext *cct;
325};
326
327
328/* A */
329struct CephXServiceTicket {
330 CryptoKey session_key;
331 utime_t validity;
332
333 void encode(bufferlist& bl) const {
11fdf7f2 334 using ceph::encode;
7c673cae 335 __u8 struct_v = 1;
11fdf7f2
TL
336 encode(struct_v, bl);
337 encode(session_key, bl);
338 encode(validity, bl);
7c673cae 339 }
11fdf7f2
TL
340 void decode(bufferlist::const_iterator& bl) {
341 using ceph::decode;
7c673cae 342 __u8 struct_v;
11fdf7f2
TL
343 decode(struct_v, bl);
344 decode(session_key, bl);
345 decode(validity, bl);
7c673cae
FG
346 }
347};
348WRITE_CLASS_ENCODER(CephXServiceTicket)
349
350/* B */
351struct CephXServiceTicketInfo {
352 AuthTicket ticket;
353 CryptoKey session_key;
354
355 void encode(bufferlist& bl) const {
11fdf7f2 356 using ceph::encode;
7c673cae 357 __u8 struct_v = 1;
11fdf7f2
TL
358 encode(struct_v, bl);
359 encode(ticket, bl);
360 encode(session_key, bl);
7c673cae 361 }
11fdf7f2
TL
362 void decode(bufferlist::const_iterator& bl) {
363 using ceph::decode;
7c673cae 364 __u8 struct_v;
11fdf7f2
TL
365 decode(struct_v, bl);
366 decode(ticket, bl);
367 decode(session_key, bl);
7c673cae
FG
368 }
369};
370WRITE_CLASS_ENCODER(CephXServiceTicketInfo)
371
28e407b8
AA
372struct CephXAuthorizeChallenge : public AuthAuthorizerChallenge {
373 uint64_t server_challenge;
374 void encode(bufferlist& bl) const {
11fdf7f2 375 using ceph::encode;
28e407b8 376 __u8 struct_v = 1;
11fdf7f2
TL
377 encode(struct_v, bl);
378 encode(server_challenge, bl);
28e407b8 379 }
11fdf7f2
TL
380 void decode(bufferlist::const_iterator& bl) {
381 using ceph::decode;
28e407b8 382 __u8 struct_v;
11fdf7f2
TL
383 decode(struct_v, bl);
384 decode(server_challenge, bl);
28e407b8
AA
385 }
386};
387WRITE_CLASS_ENCODER(CephXAuthorizeChallenge)
388
7c673cae
FG
389struct CephXAuthorize {
390 uint64_t nonce;
28e407b8
AA
391 bool have_challenge = false;
392 uint64_t server_challenge_plus_one = 0;
7c673cae 393 void encode(bufferlist& bl) const {
11fdf7f2 394 using ceph::encode;
28e407b8 395 __u8 struct_v = 2;
11fdf7f2
TL
396 encode(struct_v, bl);
397 encode(nonce, bl);
398 encode(have_challenge, bl);
399 encode(server_challenge_plus_one, bl);
7c673cae 400 }
11fdf7f2
TL
401 void decode(bufferlist::const_iterator& bl) {
402 using ceph::decode;
7c673cae 403 __u8 struct_v;
11fdf7f2
TL
404 decode(struct_v, bl);
405 decode(nonce, bl);
28e407b8 406 if (struct_v >= 2) {
11fdf7f2
TL
407 decode(have_challenge, bl);
408 decode(server_challenge_plus_one, bl);
28e407b8 409 }
7c673cae
FG
410 }
411};
412WRITE_CLASS_ENCODER(CephXAuthorize)
413
414/*
415 * Decode an extract ticket
416 */
417bool 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 */
28e407b8 424extern bool cephx_verify_authorizer(
11fdf7f2 425 CephContext *cct,
9f95a23c 426 const KeyStore& keys,
11fdf7f2
TL
427 bufferlist::const_iterator& indata,
428 size_t connection_secret_required_len,
28e407b8
AA
429 CephXServiceTicketInfo& ticket_info,
430 std::unique_ptr<AuthAuthorizerChallenge> *challenge,
11fdf7f2
TL
431 std::string *connection_secret,
432 bufferlist *reply_bl);
7c673cae
FG
433
434
435
436
437
438
439/*
440 * encode+encrypt macros
441 */
442static constexpr uint64_t AUTH_ENC_MAGIC = 0xff009cad8826aa55ull;
443
444template <typename T>
11fdf7f2
TL
445void decode_decrypt_enc_bl(CephContext *cct, T& t, CryptoKey key,
446 const bufferlist& bl_enc,
7c673cae
FG
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
11fdf7f2 455 auto iter2 = bl.cbegin();
7c673cae 456 __u8 struct_v;
11fdf7f2
TL
457 decode(struct_v, iter2);
458 decode(magic, iter2);
7c673cae
FG
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
11fdf7f2 466 decode(t, iter2);
7c673cae
FG
467}
468
469template <typename T>
470void 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;
11fdf7f2 475 encode(struct_v, bl);
7c673cae 476 uint64_t magic = AUTH_ENC_MAGIC;
11fdf7f2
TL
477 encode(magic, bl);
478 encode(t, bl);
7c673cae
FG
479
480 key.encrypt(cct, bl, out, &error);
481}
482
483template <typename T>
484int decode_decrypt(CephContext *cct, T& t, const CryptoKey& key,
11fdf7f2 485 bufferlist::const_iterator& iter, std::string &error)
7c673cae
FG
486{
487 bufferlist bl_enc;
488 try {
11fdf7f2 489 decode(bl_enc, iter);
7c673cae
FG
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
500template <typename T>
501int 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 }
11fdf7f2 509 encode(bl_enc, out);
7c673cae
FG
510 return 0;
511}
512
7c673cae 513#endif