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(bufferlist
& bl
) const {
50 encode(server_challenge
, bl
);
52 void decode(bufferlist::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(bufferlist
& bl
) const {
69 encode(request_type
, bl
);
71 void decode(bufferlist::const_iterator
& bl
) {
73 decode(request_type
, bl
);
76 WRITE_CLASS_ENCODER(CephXRequestHeader
)
78 struct CephXResponseHeader
{
79 uint16_t request_type
;
82 void encode(bufferlist
& bl
) const {
84 encode(request_type
, bl
);
87 void decode(bufferlist::const_iterator
& bl
) {
89 decode(request_type
, bl
);
93 WRITE_CLASS_ENCODER(CephXResponseHeader
)
95 struct CephXTicketBlob
{
99 CephXTicketBlob() : secret_id(0) {}
101 void encode(bufferlist
& bl
) const {
104 encode(struct_v
, bl
);
105 encode(secret_id
, bl
);
109 void decode(bufferlist::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 void encode(bufferlist
& bl
) const {
129 encode(struct_v
, bl
);
130 encode(client_challenge
, bl
);
132 encode(old_ticket
, bl
);
133 encode(other_keys
, bl
);
135 void decode(bufferlist::const_iterator
& bl
) {
138 decode(struct_v
, bl
);
139 decode(client_challenge
, bl
);
141 decode(old_ticket
, bl
);
143 decode(other_keys
, bl
);
147 WRITE_CLASS_ENCODER(CephXAuthenticate
)
149 struct CephXChallengeBlob
{
150 uint64_t server_challenge
, client_challenge
;
152 void encode(bufferlist
& bl
) const {
154 encode(server_challenge
, bl
);
155 encode(client_challenge
, bl
);
157 void decode(bufferlist::const_iterator
& bl
) {
159 decode(server_challenge
, bl
);
160 decode(client_challenge
, bl
);
163 WRITE_CLASS_ENCODER(CephXChallengeBlob
)
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
);
171 * getting service tickets
173 struct CephXSessionAuthInfo
{
177 CryptoKey session_key
;
178 CryptoKey service_secret
;
183 extern bool cephx_build_service_ticket_blob(CephContext
*cct
,
184 CephXSessionAuthInfo
& ticket_info
, CephXTicketBlob
& blob
);
186 extern void cephx_build_service_ticket_request(CephContext
*cct
,
188 bufferlist
& request
);
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
,
197 struct CephXServiceTicketRequest
{
200 void encode(bufferlist
& bl
) const {
203 encode(struct_v
, bl
);
206 void decode(bufferlist::const_iterator
& bl
) {
209 decode(struct_v
, bl
);
213 WRITE_CLASS_ENCODER(CephXServiceTicketRequest
)
220 struct CephXAuthorizeReply
{
221 uint64_t nonce_plus_one
;
222 std::string connection_secret
;
223 void encode(bufferlist
& bl
) const {
226 if (connection_secret
.size()) {
229 encode(struct_v
, bl
);
230 encode(nonce_plus_one
, bl
);
233 encode(connection_secret
, bl
);
236 void decode(bufferlist::const_iterator
& bl
) {
239 decode(struct_v
, bl
);
240 decode(nonce_plus_one
, bl
);
242 decode(connection_secret
, bl
);
246 WRITE_CLASS_ENCODER(CephXAuthorizeReply
)
249 struct CephXAuthorizer
: public AuthAuthorizer
{
256 explicit CephXAuthorizer(CephContext
*cct_
)
257 : AuthAuthorizer(CEPH_AUTH_CEPHX
), cct(cct_
), nonce(0) {}
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
;
270 struct CephXTicketHandler
{
272 CryptoKey session_key
;
273 CephXTicketBlob ticket
; // opaque to us
274 utime_t renew_after
, expires
;
277 CephXTicketHandler(CephContext
*cct_
, uint32_t service_id_
)
278 : service_id(service_id_
), have_key_flag(false), cct(cct_
) { }
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;
287 bool need_key() const;
289 void invalidate_ticket() {
296 struct CephXTicketManager
{
297 typedef map
<uint32_t, CephXTicketHandler
> tickets_map_t
;
298 tickets_map_t tickets_map
;
301 explicit CephXTicketManager(CephContext
*cct_
) : global_id(0), cct(cct_
) {}
303 bool verify_service_ticket_reply(CryptoKey
& principal_secret
,
304 bufferlist::const_iterator
& indata
);
306 CephXTicketHandler
& get_handler(uint32_t type
) {
307 tickets_map_t::iterator i
= tickets_map
.find(type
);
308 if (i
!= tickets_map
.end())
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
;
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
);
329 struct CephXServiceTicket
{
330 CryptoKey session_key
;
333 void encode(bufferlist
& bl
) const {
336 encode(struct_v
, bl
);
337 encode(session_key
, bl
);
338 encode(validity
, bl
);
340 void decode(bufferlist::const_iterator
& bl
) {
343 decode(struct_v
, bl
);
344 decode(session_key
, bl
);
345 decode(validity
, bl
);
348 WRITE_CLASS_ENCODER(CephXServiceTicket
)
351 struct CephXServiceTicketInfo
{
353 CryptoKey session_key
;
355 void encode(bufferlist
& bl
) const {
358 encode(struct_v
, bl
);
360 encode(session_key
, bl
);
362 void decode(bufferlist::const_iterator
& bl
) {
365 decode(struct_v
, bl
);
367 decode(session_key
, bl
);
370 WRITE_CLASS_ENCODER(CephXServiceTicketInfo
)
372 struct CephXAuthorizeChallenge
: public AuthAuthorizerChallenge
{
373 uint64_t server_challenge
;
374 void encode(bufferlist
& bl
) const {
377 encode(struct_v
, bl
);
378 encode(server_challenge
, bl
);
380 void decode(bufferlist::const_iterator
& bl
) {
383 decode(struct_v
, bl
);
384 decode(server_challenge
, bl
);
387 WRITE_CLASS_ENCODER(CephXAuthorizeChallenge
)
389 struct CephXAuthorize
{
391 bool have_challenge
= false;
392 uint64_t server_challenge_plus_one
= 0;
393 void encode(bufferlist
& bl
) const {
396 encode(struct_v
, bl
);
398 encode(have_challenge
, bl
);
399 encode(server_challenge_plus_one
, bl
);
401 void decode(bufferlist::const_iterator
& bl
) {
404 decode(struct_v
, bl
);
407 decode(have_challenge
, bl
);
408 decode(server_challenge_plus_one
, bl
);
412 WRITE_CLASS_ENCODER(CephXAuthorize
)
415 * Decode an extract ticket
417 bool cephx_decode_ticket(CephContext
*cct
, KeyStore
*keys
,
418 uint32_t service_id
, CephXTicketBlob
& ticket_blob
,
419 CephXServiceTicketInfo
& ticket_info
);
422 * Verify authorizer and generate reply authorizer
424 extern bool cephx_verify_authorizer(
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
);
440 * encode+encrypt macros
442 static constexpr uint64_t AUTH_ENC_MAGIC
= 0xff009cad8826aa55ull
;
444 template <typename T
>
445 void decode_decrypt_enc_bl(CephContext
*cct
, T
& t
, CryptoKey key
,
446 const bufferlist
& bl_enc
,
452 if (key
.decrypt(cct
, bl_enc
, bl
, &error
) < 0)
455 auto iter2
= bl
.cbegin();
457 decode(struct_v
, iter2
);
458 decode(magic
, iter2
);
459 if (magic
!= AUTH_ENC_MAGIC
) {
461 oss
<< "bad magic in decode_decrypt, " << magic
<< " != " << AUTH_ENC_MAGIC
;
469 template <typename T
>
470 void encode_encrypt_enc_bl(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
471 bufferlist
& out
, std::string
&error
)
475 encode(struct_v
, bl
);
476 uint64_t magic
= AUTH_ENC_MAGIC
;
480 key
.encrypt(cct
, bl
, out
, &error
);
483 template <typename T
>
484 int decode_decrypt(CephContext
*cct
, T
& t
, const CryptoKey
& key
,
485 bufferlist::const_iterator
& iter
, std::string
&error
)
489 decode(bl_enc
, iter
);
490 decode_decrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
492 catch (buffer::error
&e
) {
493 error
= "error decoding block for decryption";
496 return CEPHX_CRYPT_ERR
;
500 template <typename T
>
501 int encode_encrypt(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
502 bufferlist
& out
, std::string
&error
)
505 encode_encrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
507 return CEPHX_CRYPT_ERR
;