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"
43 // initial server -> client challenge
44 struct CephXServerChallenge
{
45 uint64_t server_challenge
;
47 void encode(bufferlist
& bl
) const {
51 encode(server_challenge
, bl
);
53 void decode(bufferlist::const_iterator
& bl
) {
57 decode(server_challenge
, bl
);
60 WRITE_CLASS_ENCODER(CephXServerChallenge
)
63 // request/reply headers, for subsequent exchanges.
65 struct CephXRequestHeader
{
68 void encode(bufferlist
& bl
) const {
70 encode(request_type
, bl
);
72 void decode(bufferlist::const_iterator
& bl
) {
74 decode(request_type
, bl
);
77 WRITE_CLASS_ENCODER(CephXRequestHeader
)
79 struct CephXResponseHeader
{
80 uint16_t request_type
;
83 void encode(bufferlist
& bl
) const {
85 encode(request_type
, bl
);
88 void decode(bufferlist::const_iterator
& bl
) {
90 decode(request_type
, bl
);
94 WRITE_CLASS_ENCODER(CephXResponseHeader
)
96 struct CephXTicketBlob
{
100 CephXTicketBlob() : secret_id(0) {}
102 void encode(bufferlist
& bl
) const {
105 encode(struct_v
, bl
);
106 encode(secret_id
, bl
);
110 void decode(bufferlist::const_iterator
& bl
) {
113 decode(struct_v
, bl
);
114 decode(secret_id
, bl
);
118 WRITE_CLASS_ENCODER(CephXTicketBlob
)
120 // client -> server response to challenge
121 struct CephXAuthenticate
{
122 uint64_t client_challenge
;
124 CephXTicketBlob old_ticket
;
125 uint32_t other_keys
= 0; // replaces CephXServiceTicketRequest
127 void encode(bufferlist
& bl
) const {
130 encode(struct_v
, bl
);
131 encode(client_challenge
, bl
);
133 encode(old_ticket
, bl
);
134 encode(other_keys
, bl
);
136 void decode(bufferlist::const_iterator
& bl
) {
139 decode(struct_v
, bl
);
140 decode(client_challenge
, bl
);
142 decode(old_ticket
, bl
);
144 decode(other_keys
, bl
);
148 WRITE_CLASS_ENCODER(CephXAuthenticate
)
150 struct CephXChallengeBlob
{
151 uint64_t server_challenge
, client_challenge
;
153 void encode(bufferlist
& bl
) const {
155 encode(server_challenge
, bl
);
156 encode(client_challenge
, bl
);
158 void decode(bufferlist::const_iterator
& bl
) {
160 decode(server_challenge
, bl
);
161 decode(client_challenge
, bl
);
164 WRITE_CLASS_ENCODER(CephXChallengeBlob
)
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
);
172 * getting service tickets
174 struct CephXSessionAuthInfo
{
178 CryptoKey session_key
;
179 CryptoKey service_secret
;
184 extern bool cephx_build_service_ticket_blob(CephContext
*cct
,
185 CephXSessionAuthInfo
& ticket_info
, CephXTicketBlob
& blob
);
187 extern void cephx_build_service_ticket_request(CephContext
*cct
,
189 bufferlist
& request
);
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
,
198 struct CephXServiceTicketRequest
{
201 void encode(bufferlist
& bl
) const {
204 encode(struct_v
, bl
);
207 void decode(bufferlist::const_iterator
& bl
) {
210 decode(struct_v
, bl
);
214 WRITE_CLASS_ENCODER(CephXServiceTicketRequest
)
221 struct CephXAuthorizeReply
{
222 uint64_t nonce_plus_one
;
223 std::string connection_secret
;
224 void encode(bufferlist
& bl
) const {
227 if (connection_secret
.size()) {
230 encode(struct_v
, bl
);
231 encode(nonce_plus_one
, bl
);
234 encode(connection_secret
, bl
);
237 void decode(bufferlist::const_iterator
& bl
) {
240 decode(struct_v
, bl
);
241 decode(nonce_plus_one
, bl
);
243 decode(connection_secret
, bl
);
247 WRITE_CLASS_ENCODER(CephXAuthorizeReply
)
250 struct CephXAuthorizer
: public AuthAuthorizer
{
257 explicit CephXAuthorizer(CephContext
*cct_
)
258 : AuthAuthorizer(CEPH_AUTH_CEPHX
), cct(cct_
), nonce(0) {}
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
;
271 struct CephXTicketHandler
{
273 CryptoKey session_key
;
274 CephXTicketBlob ticket
; // opaque to us
275 utime_t renew_after
, expires
;
278 CephXTicketHandler(CephContext
*cct_
, uint32_t service_id_
)
279 : service_id(service_id_
), have_key_flag(false), cct(cct_
) { }
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;
288 bool need_key() const;
290 void invalidate_ticket() {
297 struct CephXTicketManager
{
298 typedef map
<uint32_t, CephXTicketHandler
> tickets_map_t
;
299 tickets_map_t tickets_map
;
302 explicit CephXTicketManager(CephContext
*cct_
) : global_id(0), cct(cct_
) {}
304 bool verify_service_ticket_reply(CryptoKey
& principal_secret
,
305 bufferlist::const_iterator
& indata
);
307 CephXTicketHandler
& get_handler(uint32_t type
) {
308 tickets_map_t::iterator i
= tickets_map
.find(type
);
309 if (i
!= tickets_map
.end())
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
;
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
);
330 struct CephXServiceTicket
{
331 CryptoKey session_key
;
334 void encode(bufferlist
& bl
) const {
337 encode(struct_v
, bl
);
338 encode(session_key
, bl
);
339 encode(validity
, bl
);
341 void decode(bufferlist::const_iterator
& bl
) {
344 decode(struct_v
, bl
);
345 decode(session_key
, bl
);
346 decode(validity
, bl
);
349 WRITE_CLASS_ENCODER(CephXServiceTicket
)
352 struct CephXServiceTicketInfo
{
354 CryptoKey session_key
;
356 void encode(bufferlist
& bl
) const {
359 encode(struct_v
, bl
);
361 encode(session_key
, bl
);
363 void decode(bufferlist::const_iterator
& bl
) {
366 decode(struct_v
, bl
);
368 decode(session_key
, bl
);
371 WRITE_CLASS_ENCODER(CephXServiceTicketInfo
)
373 struct CephXAuthorizeChallenge
: public AuthAuthorizerChallenge
{
374 uint64_t server_challenge
;
375 void encode(bufferlist
& bl
) const {
378 encode(struct_v
, bl
);
379 encode(server_challenge
, bl
);
381 void decode(bufferlist::const_iterator
& bl
) {
384 decode(struct_v
, bl
);
385 decode(server_challenge
, bl
);
388 WRITE_CLASS_ENCODER(CephXAuthorizeChallenge
)
390 struct CephXAuthorize
{
392 bool have_challenge
= false;
393 uint64_t server_challenge_plus_one
= 0;
394 void encode(bufferlist
& bl
) const {
397 encode(struct_v
, bl
);
399 encode(have_challenge
, bl
);
400 encode(server_challenge_plus_one
, bl
);
402 void decode(bufferlist::const_iterator
& bl
) {
405 decode(struct_v
, bl
);
408 decode(have_challenge
, bl
);
409 decode(server_challenge_plus_one
, bl
);
413 WRITE_CLASS_ENCODER(CephXAuthorize
)
416 * Decode an extract ticket
418 bool cephx_decode_ticket(CephContext
*cct
, KeyStore
*keys
,
419 uint32_t service_id
, CephXTicketBlob
& ticket_blob
,
420 CephXServiceTicketInfo
& ticket_info
);
423 * Verify authorizer and generate reply authorizer
425 extern bool cephx_verify_authorizer(
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
);
441 * encode+encrypt macros
443 static constexpr uint64_t AUTH_ENC_MAGIC
= 0xff009cad8826aa55ull
;
445 template <typename T
>
446 void decode_decrypt_enc_bl(CephContext
*cct
, T
& t
, CryptoKey key
,
447 const bufferlist
& bl_enc
,
453 if (key
.decrypt(cct
, bl_enc
, bl
, &error
) < 0)
456 auto iter2
= bl
.cbegin();
458 decode(struct_v
, iter2
);
459 decode(magic
, iter2
);
460 if (magic
!= AUTH_ENC_MAGIC
) {
462 oss
<< "bad magic in decode_decrypt, " << magic
<< " != " << AUTH_ENC_MAGIC
;
470 template <typename T
>
471 void encode_encrypt_enc_bl(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
472 bufferlist
& out
, std::string
&error
)
476 encode(struct_v
, bl
);
477 uint64_t magic
= AUTH_ENC_MAGIC
;
481 key
.encrypt(cct
, bl
, out
, &error
);
484 template <typename T
>
485 int decode_decrypt(CephContext
*cct
, T
& t
, const CryptoKey
& key
,
486 bufferlist::const_iterator
& iter
, std::string
&error
)
490 decode(bl_enc
, iter
);
491 decode_decrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
493 catch (buffer::error
&e
) {
494 error
= "error decoding block for decryption";
497 return CEPHX_CRYPT_ERR
;
501 template <typename T
>
502 int encode_encrypt(CephContext
*cct
, const T
& t
, const CryptoKey
& key
,
503 bufferlist
& out
, std::string
&error
)
506 encode_encrypt_enc_bl(cct
, t
, key
, bl_enc
, error
);
508 return CEPHX_CRYPT_ERR
;