1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
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.
15 #ifndef CEPH_CEPHXPROTOCOL_H
16 #define CEPH_CEPHXPROTOCOL_H
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
30 #define CEPHX_REQUEST_TYPE_MASK 0x0F00
31 #define CEPHX_CRYPT_ERR 1
33 #include "auth/Auth.h"
37 #include "include/common_fwd.h"
42 // initial server -> client challenge
43 struct CephXServerChallenge
{
44 uint64_t server_challenge
;
46 void encode(ceph::buffer::list
& bl
) const {
50 encode(server_challenge
, bl
);
52 void decode(ceph::buffer::list::const_iterator
& bl
) {
56 decode(server_challenge
, bl
);
59 WRITE_CLASS_ENCODER(CephXServerChallenge
)
62 // request/reply headers, for subsequent exchanges.
64 struct CephXRequestHeader
{
67 void encode(ceph::buffer::list
& bl
) const {
69 encode(request_type
, bl
);
71 void decode(ceph::buffer::list::const_iterator
& bl
) {
73 decode(request_type
, bl
);
76 WRITE_CLASS_ENCODER(CephXRequestHeader
)
78 struct CephXResponseHeader
{
79 uint16_t request_type
;
82 void encode(ceph::buffer::list
& bl
) const {
84 encode(request_type
, bl
);
87 void decode(ceph::buffer::list::const_iterator
& bl
) {
89 decode(request_type
, bl
);
93 WRITE_CLASS_ENCODER(CephXResponseHeader
)
95 struct CephXTicketBlob
{
97 ceph::buffer::list blob
;
99 CephXTicketBlob() : secret_id(0) {}
101 void encode(ceph::buffer::list
& bl
) const {
104 encode(struct_v
, bl
);
105 encode(secret_id
, bl
);
109 void decode(ceph::buffer::list::const_iterator
& bl
) {
112 decode(struct_v
, bl
);
113 decode(secret_id
, bl
);
117 WRITE_CLASS_ENCODER(CephXTicketBlob
)
119 // client -> server response to challenge
120 struct CephXAuthenticate
{
121 uint64_t client_challenge
;
123 CephXTicketBlob old_ticket
;
124 uint32_t other_keys
= 0; // replaces CephXServiceTicketRequest
126 bool old_ticket_may_be_omitted
;
128 void encode(ceph::buffer::list
& bl
) const {
131 encode(struct_v
, bl
);
132 encode(client_challenge
, bl
);
134 encode(old_ticket
, bl
);
135 encode(other_keys
, bl
);
137 void decode(ceph::buffer::list::const_iterator
& bl
) {
140 decode(struct_v
, bl
);
141 decode(client_challenge
, bl
);
143 decode(old_ticket
, bl
);
145 decode(other_keys
, bl
);
148 // v2 and v3 encodings are the same, but:
149 // - some clients that send v1 or v2 don't populate old_ticket
150 // on reconnects (but do on renewals)
151 // - any client that sends v3 or later is expected to populate
152 // old_ticket both on reconnects and renewals
153 old_ticket_may_be_omitted
= struct_v
< 3;
156 WRITE_CLASS_ENCODER(CephXAuthenticate
)
158 struct CephXChallengeBlob
{
159 uint64_t server_challenge
, client_challenge
;
161 void encode(ceph::buffer::list
& bl
) const {
163 encode(server_challenge
, bl
);
164 encode(client_challenge
, bl
);
166 void decode(ceph::buffer::list::const_iterator
& bl
) {
168 decode(server_challenge
, bl
);
169 decode(client_challenge
, bl
);
172 WRITE_CLASS_ENCODER(CephXChallengeBlob
)
174 void cephx_calc_client_server_challenge(CephContext
*cct
,
175 CryptoKey
& secret
, uint64_t server_challenge
, uint64_t client_challenge
,
176 uint64_t *key
, std::string
&error
);
180 * getting service tickets
182 struct CephXSessionAuthInfo
{
186 CryptoKey session_key
;
187 CryptoKey service_secret
;
192 extern bool cephx_build_service_ticket_blob(CephContext
*cct
,
193 CephXSessionAuthInfo
& ticket_info
, CephXTicketBlob
& blob
);
195 extern void cephx_build_service_ticket_request(CephContext
*cct
,
197 ceph::buffer::list
& request
);
199 extern bool cephx_build_service_ticket_reply(CephContext
*cct
,
200 CryptoKey
& principal_secret
,
201 std::vector
<CephXSessionAuthInfo
> ticket_info
,
202 bool should_encrypt_ticket
,
203 CryptoKey
& ticket_enc_key
,
204 ceph::buffer::list
& reply
);
206 struct CephXServiceTicketRequest
{
209 void encode(ceph::buffer::list
& bl
) const {
212 encode(struct_v
, bl
);
215 void decode(ceph::buffer::list::const_iterator
& bl
) {
218 decode(struct_v
, bl
);
222 WRITE_CLASS_ENCODER(CephXServiceTicketRequest
)
229 struct CephXAuthorizeReply
{
230 uint64_t nonce_plus_one
;
231 std::string connection_secret
;
232 void encode(ceph::buffer::list
& bl
) const {
235 if (connection_secret
.size()) {
238 encode(struct_v
, bl
);
239 encode(nonce_plus_one
, bl
);
242 encode(connection_secret
, bl
);
245 void decode(ceph::buffer::list::const_iterator
& bl
) {
248 decode(struct_v
, bl
);
249 decode(nonce_plus_one
, bl
);
251 decode(connection_secret
, bl
);
255 WRITE_CLASS_ENCODER(CephXAuthorizeReply
)
258 struct CephXAuthorizer
: public AuthAuthorizer
{
263 ceph::buffer::list base_bl
;
265 explicit CephXAuthorizer(CephContext
*cct_
)
266 : AuthAuthorizer(CEPH_AUTH_CEPHX
), cct(cct_
), nonce(0) {}
268 bool build_authorizer();
269 bool verify_reply(ceph::buffer::list::const_iterator
& reply
,
270 std::string
*connection_secret
) override
;
271 bool add_challenge(CephContext
*cct
, const ceph::buffer::list
& challenge
) override
;
279 struct CephXTicketHandler
{
281 CryptoKey session_key
;
282 CephXTicketBlob ticket
; // opaque to us
283 utime_t renew_after
, expires
;
286 CephXTicketHandler(CephContext
*cct_
, uint32_t service_id_
)
287 : service_id(service_id_
), have_key_flag(false), cct(cct_
) { }
289 // to build our ServiceTicket
290 bool verify_service_ticket_reply(CryptoKey
& principal_secret
,
291 ceph::buffer::list::const_iterator
& indata
);
292 // to access the service
293 CephXAuthorizer
*build_authorizer(uint64_t global_id
) const;
296 bool need_key() const;
298 void invalidate_ticket() {
299 have_key_flag
= false;
305 struct CephXTicketManager
{
306 typedef std::map
<uint32_t, CephXTicketHandler
> tickets_map_t
;
307 tickets_map_t tickets_map
;
310 explicit CephXTicketManager(CephContext
*cct_
) : global_id(0), cct(cct_
) {}
312 bool verify_service_ticket_reply(CryptoKey
& principal_secret
,
313 ceph::buffer::list::const_iterator
& indata
);
315 CephXTicketHandler
& get_handler(uint32_t type
) {
316 tickets_map_t::iterator i
= tickets_map
.find(type
);
317 if (i
!= tickets_map
.end())
319 CephXTicketHandler
newTicketHandler(cct
, type
);
320 std::pair
< tickets_map_t::iterator
, bool > res
=
321 tickets_map
.insert(std::make_pair(type
, newTicketHandler
));
322 ceph_assert(res
.second
);
323 return res
.first
->second
;
325 CephXAuthorizer
*build_authorizer(uint32_t service_id
) const;
326 bool have_key(uint32_t service_id
);
327 bool need_key(uint32_t service_id
) const;
328 void set_have_need_key(uint32_t service_id
, uint32_t& have
, uint32_t& need
);
329 void validate_tickets(uint32_t mask
, uint32_t& have
, uint32_t& need
);
330 void invalidate_ticket(uint32_t service_id
);
338 struct CephXServiceTicket
{
339 CryptoKey session_key
;
342 void encode(ceph::buffer::list
& bl
) const {
345 encode(struct_v
, bl
);
346 encode(session_key
, bl
);
347 encode(validity
, bl
);
349 void decode(ceph::buffer::list::const_iterator
& bl
) {
352 decode(struct_v
, bl
);
353 decode(session_key
, bl
);
354 decode(validity
, bl
);
357 WRITE_CLASS_ENCODER(CephXServiceTicket
)
360 struct CephXServiceTicketInfo
{
362 CryptoKey session_key
;
364 void encode(ceph::buffer::list
& bl
) const {
367 encode(struct_v
, bl
);
369 encode(session_key
, bl
);
371 void decode(ceph::buffer::list::const_iterator
& bl
) {
374 decode(struct_v
, bl
);
376 decode(session_key
, bl
);
379 WRITE_CLASS_ENCODER(CephXServiceTicketInfo
)
381 struct CephXAuthorizeChallenge
: public AuthAuthorizerChallenge
{
382 uint64_t server_challenge
;
383 void encode(ceph::buffer::list
& bl
) const {
386 encode(struct_v
, bl
);
387 encode(server_challenge
, bl
);
389 void decode(ceph::buffer::list::const_iterator
& bl
) {
392 decode(struct_v
, bl
);
393 decode(server_challenge
, bl
);
396 WRITE_CLASS_ENCODER(CephXAuthorizeChallenge
)
398 struct CephXAuthorize
{
400 bool have_challenge
= false;
401 uint64_t server_challenge_plus_one
= 0;
402 void encode(ceph::buffer::list
& bl
) const {
405 encode(struct_v
, bl
);
407 encode(have_challenge
, bl
);
408 encode(server_challenge_plus_one
, bl
);
410 void decode(ceph::buffer::list::const_iterator
& bl
) {
413 decode(struct_v
, bl
);
416 decode(have_challenge
, bl
);
417 decode(server_challenge_plus_one
, bl
);
421 WRITE_CLASS_ENCODER(CephXAuthorize
)
424 * Decode an extract ticket
426 bool cephx_decode_ticket(CephContext
*cct
, KeyStore
*keys
,
428 const CephXTicketBlob
& ticket_blob
,
429 CephXServiceTicketInfo
& ticket_info
);
432 * Verify authorizer and generate reply authorizer
434 extern bool cephx_verify_authorizer(
436 const KeyStore
& keys
,
437 ceph::buffer::list::const_iterator
& indata
,
438 size_t connection_secret_required_len
,
439 CephXServiceTicketInfo
& ticket_info
,
440 std::unique_ptr
<AuthAuthorizerChallenge
> *challenge
,
441 std::string
*connection_secret
,
442 ceph::buffer::list
*reply_bl
);
450 * encode+encrypt macros
452 static constexpr uint64_t AUTH_ENC_MAGIC
= 0xff009cad8826aa55ull
;
454 template <typename T
>
455 void decode_decrypt_enc_bl(CephContext
*cct
, T
& t
, CryptoKey key
,
456 const ceph::buffer::list
& bl_enc
,
460 ceph::buffer::list bl
;
462 if (key
.decrypt(cct
, bl_enc
, bl
, &error
) < 0)
465 auto iter2
= bl
.cbegin();
468 decode(struct_v
, iter2
);
469 decode(magic
, iter2
);
470 if (magic
!= AUTH_ENC_MAGIC
) {
471 std::ostringstream oss
;
472 oss
<< "bad magic in decode_decrypt, " << magic
<< " != " << AUTH_ENC_MAGIC
;
480 template <typename T
>
481 void encode_encrypt_enc_bl(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
482 ceph::buffer::list
& out
, std::string
&error
)
484 ceph::buffer::list bl
;
487 encode(struct_v
, bl
);
488 uint64_t magic
= AUTH_ENC_MAGIC
;
492 key
.encrypt(cct
, bl
, out
, &error
);
495 template <typename T
>
496 int decode_decrypt(CephContext
*cct
, T
& t
, const CryptoKey
& key
,
497 ceph::buffer::list::const_iterator
& iter
, std::string
&error
)
499 ceph::buffer::list bl_enc
;
502 decode(bl_enc
, iter
);
503 decode_decrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
505 catch (ceph::buffer::error
&e
) {
506 error
= "error decoding block for decryption";
509 return CEPHX_CRYPT_ERR
;
513 template <typename T
>
514 int encode_encrypt(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
515 ceph::buffer::list
& out
, std::string
&error
)
518 ceph::buffer::list bl_enc
;
519 encode_encrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
521 return CEPHX_CRYPT_ERR
;