explicit AuthAuthorizer(__u32 p) : protocol(p) {}
virtual ~AuthAuthorizer() {}
- virtual bool verify_reply(bufferlist::const_iterator& reply) = 0;
+ virtual bool verify_reply(bufferlist::const_iterator& reply,
+ CryptoKey *connection_secret) = 0;
virtual bool add_challenge(CephContext *cct, bufferlist& challenge) = 0;
};
struct AuthAuthorizeHandler {
virtual ~AuthAuthorizeHandler() {}
- virtual bool verify_authorizer(CephContext *cct, KeyStore *keys,
- bufferlist& authorizer_data, bufferlist& authorizer_reply,
- EntityName& entity_name, uint64_t& global_id,
- AuthCapsInfo& caps_info, CryptoKey& session_key,
- std::unique_ptr<AuthAuthorizerChallenge> *challenge) = 0;
+ virtual bool verify_authorizer(
+ CephContext *cct,
+ KeyStore *keys,
+ bufferlist& authorizer_data,
+ bufferlist& authorizer_reply,
+ EntityName& entity_name,
+ uint64_t& global_id,
+ AuthCapsInfo& caps_info,
+ CryptoKey& session_key,
+ CryptoKey *connection_secret,
+ std::unique_ptr<AuthAuthorizerChallenge> *challenge) = 0;
virtual int authorizer_session_crypto() = 0;
};
#define dout_subsys ceph_subsys_auth
-AuthSessionHandler *get_auth_session_handler(CephContext *cct, int protocol, CryptoKey key, uint64_t features)
+AuthSessionHandler *get_auth_session_handler(
+ CephContext *cct, int protocol,
+ const CryptoKey& key,
+ const CryptoKey& connection_secret,
+ uint64_t features)
{
// Should add code to only print the SHA1 hash of the key, unless in secure debugging mode
if (key.get_type() == CEPH_CRYPTO_NONE) {
return nullptr;
}
- return new CephxSessionHandler(cct, key, features);
+ return new CephxSessionHandler(cct, key, connection_secret, features);
case CEPH_AUTH_NONE:
- return new AuthNoneSessionHandler(cct, key);
+ return new AuthNoneSessionHandler(cct, key, connection_secret);
case CEPH_AUTH_UNKNOWN:
- return new AuthUnknownSessionHandler(cct, key);
+ return new AuthUnknownSessionHandler(cct, key, connection_secret);
#ifdef HAVE_GSSAPI
case CEPH_AUTH_GSS:
- return new KrbSessionHandler(cct, key);
+ return new KrbSessionHandler(cct, key, connection_secret);
#endif
default:
return nullptr;
protected:
CephContext *cct;
int protocol;
- CryptoKey key;
+ CryptoKey key; // per mon authentication
+ CryptoKey connection_secret; // per connection
public:
explicit AuthSessionHandler(CephContext *cct_) : cct(cct_), protocol(CEPH_AUTH_UNKNOWN) {}
- AuthSessionHandler(CephContext *cct_, int protocol_, CryptoKey key_) : cct(cct_),
- protocol(protocol_), key(key_) {}
+ AuthSessionHandler(CephContext *cct_, int protocol_,
+ const CryptoKey& key_,
+ const CryptoKey& cs_)
+ : cct(cct_),
+ protocol(protocol_),
+ key(key_),
+ connection_secret(cs_) {}
virtual ~AuthSessionHandler() { }
virtual bool no_security() = 0;
};
-extern AuthSessionHandler *get_auth_session_handler(CephContext *cct, int protocol, CryptoKey key,
- uint64_t features);
+extern AuthSessionHandler *get_auth_session_handler(
+ CephContext *cct, int protocol,
+ const CryptoKey& key,
+ const CryptoKey& connection_secret,
+ uint64_t features);
#endif
bool CephxAuthorizeHandler::verify_authorizer(
- CephContext *cct, KeyStore *keys,
- bufferlist& authorizer_data, bufferlist& authorizer_reply,
- EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
+ CephContext *cct,
+ KeyStore *keys,
+ bufferlist& authorizer_data,
+ bufferlist& authorizer_reply,
+ EntityName& entity_name,
+ uint64_t& global_id,
+ AuthCapsInfo& caps_info,
CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge)
{
auto iter = authorizer_data.cbegin();
CephXServiceTicketInfo auth_ticket_info;
- bool isvalid = cephx_verify_authorizer(cct, keys, iter, auth_ticket_info, challenge,
+ bool isvalid = cephx_verify_authorizer(cct, keys, iter, auth_ticket_info,
+ challenge, connection_secret,
authorizer_reply);
if (isvalid) {
class CephContext;
struct CephxAuthorizeHandler : public AuthAuthorizeHandler {
- bool verify_authorizer(CephContext *cct, KeyStore *keys,
- bufferlist& authorizer_data, bufferlist& authorizer_reply,
- EntityName& entity_name, uint64_t& global_id,
- AuthCapsInfo& caps_info, CryptoKey& session_key,
- std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
+ bool verify_authorizer(
+ CephContext *cct,
+ KeyStore *keys,
+ bufferlist& authorizer_data,
+ bufferlist& authorizer_reply,
+ EntityName& entity_name,
+ uint64_t& global_id,
+ AuthCapsInfo& caps_info,
+ CryptoKey& session_key,
+ CryptoKey *connection_secret,
+ std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
int authorizer_session_crypto() override;
};
bufferlist::const_iterator& indata,
CephXServiceTicketInfo& ticket_info,
std::unique_ptr<AuthAuthorizerChallenge> *challenge,
+ CryptoKey *connection_secret,
bufferlist& reply_bl)
{
__u8 authorizer_v;
// ticket blob
CephXTicketBlob ticket;
-
try {
decode(authorizer_v, indata);
decode(global_id, indata);
CephXAuthorizeReply reply;
// reply.trans_id = auth_msg.trans_id;
reply.nonce_plus_one = auth_msg.nonce + 1;
+ if (connection_secret) {
+ // generate a connection secret
+ bufferptr bp;
+ CryptoHandler *crypto = cct->get_crypto_handler(CEPH_CRYPTO_AES);
+ assert(crypto);
+ int r = crypto->create(cct->random(), bp);
+ assert(r >= 0);
+ connection_secret->set_secret(CEPH_CRYPTO_AES, bp, ceph_clock_now());
+ reply.connection_secret = *connection_secret;
+ }
if (encode_encrypt(cct, reply, ticket_info.session_key, reply_bl, error)) {
ldout(cct, 10) << "verify_authorizer: encode_encrypt error: " << error << dendl;
return false;
return true;
}
-bool CephXAuthorizer::verify_reply(bufferlist::const_iterator& indata)
+bool CephXAuthorizer::verify_reply(bufferlist::const_iterator& indata,
+ CryptoKey *connection_secret)
{
CephXAuthorizeReply reply;
<< " sent " << nonce << dendl;
return false;
}
+
+ if (connection_secret &&
+ reply.connection_secret.get_type()) {
+ *connection_secret = reply.connection_secret;
+ }
return true;
}
struct CephXAuthorizeReply {
uint64_t nonce_plus_one;
+ CryptoKey connection_secret;
void encode(bufferlist& bl) const {
using ceph::encode;
__u8 struct_v = 1;
+ if (connection_secret.get_type()) {
+ struct_v = 2;
+ }
encode(struct_v, bl);
encode(nonce_plus_one, bl);
+ if (struct_v >= 2) {
+ struct_v = 2;
+ encode(connection_secret, bl);
+ }
}
void decode(bufferlist::const_iterator& bl) {
using ceph::decode;
__u8 struct_v;
decode(struct_v, bl);
decode(nonce_plus_one, bl);
+ if (struct_v >= 2) {
+ decode(connection_secret, bl);
+ }
}
};
WRITE_CLASS_ENCODER(CephXAuthorizeReply)
: AuthAuthorizer(CEPH_AUTH_CEPHX), cct(cct_), nonce(0) {}
bool build_authorizer();
- bool verify_reply(bufferlist::const_iterator& reply) override;
+ bool verify_reply(bufferlist::const_iterator& reply,
+ CryptoKey *connection_secret) override;
bool add_challenge(CephContext *cct, bufferlist& challenge) override;
};
bufferlist::const_iterator& indata,
CephXServiceTicketInfo& ticket_info,
std::unique_ptr<AuthAuthorizerChallenge> *challenge,
+ CryptoKey *connection_secret,
bufferlist& reply_bl);
bufferlist tmp_bl;
CephXServiceTicketInfo auth_ticket_info;
// note: no challenge here.
- if (!cephx_verify_authorizer(cct, key_server, indata, auth_ticket_info, nullptr,
- tmp_bl)) {
+ if (!cephx_verify_authorizer(
+ cct, key_server, indata, auth_ticket_info, nullptr,
+#warning FIXME mon connection needs connection_secret too
+ nullptr,
+ tmp_bl)) {
ret = -EPERM;
break;
}
uint64_t features;
public:
- CephxSessionHandler(CephContext *cct_, CryptoKey session_key, uint64_t features)
- : AuthSessionHandler(cct_, CEPH_AUTH_CEPHX, session_key),
+ CephxSessionHandler(CephContext *cct_,
+ const CryptoKey& session_key,
+ const CryptoKey& connection_secret,
+ uint64_t features)
+ : AuthSessionHandler(cct_, CEPH_AUTH_CEPHX, session_key, connection_secret),
features(features) {}
~CephxSessionHandler() override {}
EntityName& entity_name,
uint64_t& global_id,
AuthCapsInfo& caps_info,
- CryptoKey& session_key,
+ CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<
AuthAuthorizerChallenge>* challenge)
{
bool verify_authorizer(CephContext*, KeyStore*,
bufferlist&, bufferlist&,
EntityName&, uint64_t&,
- AuthCapsInfo&, CryptoKey&,
+ AuthCapsInfo&, CryptoKey&,
+ CryptoKey *connection_secret,
std::unique_ptr<
AuthAuthorizerChallenge>* = nullptr) override;
return false;
}
- bool verify_reply(bufferlist::const_iterator& buff_list) override {
+ bool verify_reply(bufferlist::const_iterator& buff_list,
+ CryptoKey *connection_secret) override {
return true;
}
bool add_challenge(CephContext* ceph_ctx,
class KrbSessionHandler : public AuthSessionHandler {
public:
- KrbSessionHandler(CephContext* ceph_ctx, CryptoKey session_key) :
- AuthSessionHandler(ceph_ctx, CEPH_AUTH_GSS, session_key) { }
+ KrbSessionHandler(CephContext* ceph_ctx,
+ const CryptoKey& session_key,
+ const CryptoKey& connection_secret) :
+ AuthSessionHandler(ceph_ctx, CEPH_AUTH_GSS, session_key,
+ connection_secret) { }
~KrbSessionHandler() override = default;
bool no_security() override { return true; }
bufferlist& authorizer_data, bufferlist& authorizer_reply,
EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge)
{
auto iter = authorizer_data.cbegin();
class CephContext;
struct AuthNoneAuthorizeHandler : public AuthAuthorizeHandler {
- bool verify_authorizer(CephContext *cct, KeyStore *keys,
- bufferlist& authorizer_data, bufferlist& authorizer_reply,
- EntityName& entity_name, uint64_t& global_id,
- AuthCapsInfo& caps_info, CryptoKey& session_key,
- std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
+ bool verify_authorizer(
+ CephContext *cct, KeyStore *keys,
+ bufferlist& authorizer_data, bufferlist& authorizer_reply,
+ EntityName& entity_name, uint64_t& global_id,
+ AuthCapsInfo& caps_info, CryptoKey& session_key,
+ CryptoKey *connection_secret,
+ std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
int authorizer_session_crypto() override;
};
encode(global_id, bl);
return 0;
}
- bool verify_reply(bufferlist::const_iterator& reply) override { return true; }
+ bool verify_reply(bufferlist::const_iterator& reply,
+ CryptoKey *connection_secret) override { return true; }
bool add_challenge(CephContext *cct, bufferlist& ch) override { return true; }
};
class AuthNoneSessionHandler : public AuthSessionHandler {
public:
- AuthNoneSessionHandler(CephContext *cct_, CryptoKey session_key)
- : AuthSessionHandler(cct_, CEPH_AUTH_NONE, session_key) {}
+ AuthNoneSessionHandler(CephContext *cct_,
+ const CryptoKey& session_key,
+ const CryptoKey& connection_secret)
+ : AuthSessionHandler(cct_, CEPH_AUTH_NONE, session_key, connection_secret) {}
~AuthNoneSessionHandler() override {}
bool no_security() override {
bufferlist& authorizer_data, bufferlist& authorizer_reply,
EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge)
{
// For unknown authorizers, there's nothing to verify. They're "OK" by definition. PLR
bufferlist& authorizer_data, bufferlist& authorizer_reply,
EntityName& entity_name, uint64_t& global_id,
AuthCapsInfo& caps_info, CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
int authorizer_session_crypto() override;
};
class AuthUnknownSessionHandler : public AuthSessionHandler {
public:
- AuthUnknownSessionHandler(CephContext *cct_, CryptoKey session_key)
- : AuthSessionHandler(cct_, CEPH_AUTH_UNKNOWN, session_key) {}
+ AuthUnknownSessionHandler(CephContext *cct_,
+ const CryptoKey& session_key,
+ const CryptoKey& connection_secret)
+ : AuthSessionHandler(cct_, CEPH_AUTH_UNKNOWN,
+ session_key, connection_secret) {}
~AuthUnknownSessionHandler() override {}
bool no_security() override {
bufferlist& authorizer_reply,
bool& isvalid,
CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge)
{
if (authorizer.length() == 0) {
con->peer_global_id,
con->peer_caps_info,
session_key,
+ connection_secret,
challenge);
if (isvalid) {
dis->ms_handle_authentication(con);
Connection *con, int peer_type,
int protocol, bufferlist& authorizer, bufferlist& authorizer_reply,
bool& isvalid, CryptoKey& session_key,
+ CryptoKey *connection_secret,
std::unique_ptr<AuthAuthorizerChallenge> *challenge);
/**
}
auto iter = authorizer_reply.cbegin();
- if (authorizer && !authorizer->verify_reply(iter)) {
+ if (authorizer && !authorizer->verify_reply(iter,
+ nullptr /* connection_secret */)) {
ldout(cct, 0) << __func__ << " failed verifying authorize reply" << dendl;
return _fault();
}
<< authorizer << dendl;
session_security.reset(get_auth_session_handler(
cct, authorizer->protocol, authorizer->session_key,
+ authorizer->session_key /* connection_secret */,
connection->get_features()));
} else {
// We have no authorizer, so we shouldn't be applying security to messages
if (!messenger->ms_deliver_verify_authorizer(
connection, connection->peer_type, connect_msg.authorizer_protocol,
authorizer_buf, authorizer_reply, authorizer_valid, session_key,
+ nullptr /* connection_secret */,
need_challenge ? &authorizer_challenge : nullptr) ||
!authorizer_valid) {
connection->lock.lock();
session_security.reset(
get_auth_session_handler(cct, connect_msg.authorizer_protocol,
- session_key, connection->get_features()));
+ session_key,
+ session_key /* connection secret */,
+ connection->get_features()));
bufferlist reply_bl;
reply_bl.append((char *)&reply, sizeof(reply));
ldout(cct, 20) << __func__ << " payload_len=" << length << dendl;
AuthDoneFrame auth_done(payload, length);
-
+ CryptoKey connection_secret;
if (authorizer) {
auto iter = auth_done.auth_payload().cbegin();
- if (!authorizer->verify_reply(iter)) {
+ if (!authorizer->verify_reply(iter, &connection_secret)) {
ldout(cct, 0) << __func__ << " failed verifying authorize reply" << dendl;
return _fault();
}
<< authorizer << dendl;
session_security.reset(get_auth_session_handler(
cct, authorizer->protocol, authorizer->session_key,
+ connection_secret,
CEPH_FEATURE_MSG_AUTH | CEPH_FEATURE_CEPHX_V2));
auth_flags = auth_done.flags();
} else {
connection->lock.unlock();
if (!messenger->ms_deliver_verify_authorizer(
- connection, connection->peer_type, auth_method, auth_payload,
- authorizer_reply, authorizer_valid, session_key,
- &authorizer_challenge) ||
+ connection, connection->peer_type, auth_method, auth_payload,
+ authorizer_reply, authorizer_valid, session_key,
+ &connection_secret,
+ &authorizer_challenge) ||
!authorizer_valid) {
connection->lock.lock();
session_security.reset(
get_auth_session_handler(cct, auth_method, session_key,
+ connection_secret,
CEPH_FEATURE_MSG_AUTH | CEPH_FEATURE_CEPHX_V2));
if (cct->_conf.get_val<bool>("ms_msgr2_sign_messages")) {
messenger->ms_deliver_verify_authorizer(
connection, connection->peer_type, auth_method,
auth_request.auth_payload(), authorizer_reply, authorizer_valid,
- session_key, nullptr);
+ session_key,
+ nullptr /* connection_secret */,
+ nullptr);
connection->lock.lock();
if (!authorizer_valid) {
bool got_bad_auth;
uint32_t got_bad_method;
CryptoKey session_key;
+ CryptoKey connection_secret;
std::shared_ptr<AuthSessionHandler> session_security;
std::unique_ptr<AuthAuthorizerChallenge> authorizer_challenge;
uint64_t auth_flags;
if (!msgr->ms_deliver_verify_authorizer(
connection_state.get(), peer_type, connect.authorizer_protocol, authorizer,
authorizer_reply, authorizer_valid, session_key,
+ nullptr /* connection_secret */,
need_challenge ? &authorizer_challenge : nullptr) ||
!authorizer_valid) {
pipe_lock.Lock();
get_auth_session_handler(msgr->cct,
connect.authorizer_protocol,
session_key,
+ session_key, /* connection_secret */
connection_state->get_features()));
// notify
if (authorizer) {
auto iter = authorizer_reply.cbegin();
- if (!authorizer->verify_reply(iter)) {
+ if (!authorizer->verify_reply(iter, nullptr /* connection_secret */)) {
ldout(msgr->cct,0) << "failed verifying authorize reply" << dendl;
goto fail;
}
if (authorizer != NULL) {
session_security.reset(
- get_auth_session_handler(msgr->cct,
- authorizer->protocol,
- authorizer->session_key,
- connection_state->get_features()));
+ get_auth_session_handler(
+ msgr->cct,
+ authorizer->protocol,
+ authorizer->session_key,
+ authorizer->session_key /* connection secret*/,
+ connection_state->get_features()));
} else {
// We have no authorizer, so we shouldn't be applying security to messages in this pipe. PLR
session_security.reset();