diff options
Diffstat (limited to '')
-rw-r--r-- | src/auth/cephx/CephxKeyServer.h | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/auth/cephx/CephxKeyServer.h b/src/auth/cephx/CephxKeyServer.h new file mode 100644 index 000000000..64915c8ce --- /dev/null +++ b/src/auth/cephx/CephxKeyServer.h @@ -0,0 +1,323 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net> + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_KEYSSERVER_H +#define CEPH_KEYSSERVER_H + +#include "auth/KeyRing.h" +#include "CephxProtocol.h" +#include "common/ceph_mutex.h" +#include "include/common_fwd.h" + +struct KeyServerData { + version_t version; + + /* for each entity */ + std::map<EntityName, EntityAuth> secrets; + KeyRing *extra_secrets; + + /* for each service type */ + version_t rotating_ver; + std::map<uint32_t, RotatingSecrets> rotating_secrets; + + explicit KeyServerData(KeyRing *extra) + : version(0), + extra_secrets(extra), + rotating_ver(0) {} + + void encode(ceph::buffer::list& bl) const { + __u8 struct_v = 1; + using ceph::encode; + encode(struct_v, bl); + encode(version, bl); + encode(rotating_ver, bl); + encode(secrets, bl); + encode(rotating_secrets, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + __u8 struct_v; + decode(struct_v, bl); + decode(version, bl); + decode(rotating_ver, bl); + decode(secrets, bl); + decode(rotating_secrets, bl); + } + + void encode_rotating(ceph::buffer::list& bl) const { + using ceph::encode; + __u8 struct_v = 1; + encode(struct_v, bl); + encode(rotating_ver, bl); + encode(rotating_secrets, bl); + } + void decode_rotating(ceph::buffer::list& rotating_bl) { + using ceph::decode; + auto iter = rotating_bl.cbegin(); + __u8 struct_v; + decode(struct_v, iter); + decode(rotating_ver, iter); + decode(rotating_secrets, iter); + } + + bool contains(const EntityName& name) const { + return (secrets.find(name) != secrets.end()); + } + + void clear_secrets() { + version = 0; + secrets.clear(); + rotating_ver = 0; + rotating_secrets.clear(); + } + + void add_auth(const EntityName& name, EntityAuth& auth) { + secrets[name] = auth; + } + + void remove_secret(const EntityName& name) { + auto iter = secrets.find(name); + if (iter == secrets.end()) + return; + secrets.erase(iter); + } + + bool get_service_secret(CephContext *cct, uint32_t service_id, + CryptoKey& secret, uint64_t& secret_id, + double& ttl) const; + bool get_service_secret(CephContext *cct, uint32_t service_id, + uint64_t secret_id, CryptoKey& secret) const; + bool get_auth(const EntityName& name, EntityAuth& auth) const; + bool get_secret(const EntityName& name, CryptoKey& secret) const; + bool get_caps(CephContext *cct, const EntityName& name, + const std::string& type, AuthCapsInfo& caps) const; + + std::map<EntityName, EntityAuth>::iterator secrets_begin() + { return secrets.begin(); } + std::map<EntityName, EntityAuth>::const_iterator secrets_begin() const + { return secrets.begin(); } + std::map<EntityName, EntityAuth>::iterator secrets_end() + { return secrets.end(); } + std::map<EntityName, EntityAuth>::const_iterator secrets_end() const + { return secrets.end(); } + std::map<EntityName, EntityAuth>::iterator find_name(const EntityName& name) + { return secrets.find(name); } + std::map<EntityName, EntityAuth>::const_iterator find_name(const EntityName& name) const + { return secrets.find(name); } + + + // -- incremental updates -- + typedef enum { + AUTH_INC_NOP, + AUTH_INC_ADD, + AUTH_INC_DEL, + AUTH_INC_SET_ROTATING, + } IncrementalOp; + + struct Incremental { + IncrementalOp op; + ceph::buffer::list rotating_bl; // if SET_ROTATING. otherwise, + EntityName name; + EntityAuth auth; + + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + __u8 struct_v = 1; + encode(struct_v, bl); + __u32 _op = (__u32)op; + encode(_op, bl); + if (op == AUTH_INC_SET_ROTATING) { + encode(rotating_bl, bl); + } else { + encode(name, bl); + encode(auth, bl); + } + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + __u8 struct_v; + decode(struct_v, bl); + __u32 _op; + decode(_op, bl); + op = (IncrementalOp)_op; + ceph_assert(op >= AUTH_INC_NOP && op <= AUTH_INC_SET_ROTATING); + if (op == AUTH_INC_SET_ROTATING) { + decode(rotating_bl, bl); + } else { + decode(name, bl); + decode(auth, bl); + } + } + }; + + void apply_incremental(Incremental& inc) { + switch (inc.op) { + case AUTH_INC_ADD: + add_auth(inc.name, inc.auth); + break; + + case AUTH_INC_DEL: + remove_secret(inc.name); + break; + + case AUTH_INC_SET_ROTATING: + decode_rotating(inc.rotating_bl); + break; + + case AUTH_INC_NOP: + break; + + default: + ceph_abort(); + } + } + +}; +WRITE_CLASS_ENCODER(KeyServerData) +WRITE_CLASS_ENCODER(KeyServerData::Incremental) + + + + +class KeyServer : public KeyStore { + CephContext *cct; + KeyServerData data; + std::map<EntityName, CryptoKey> used_pending_keys; + mutable ceph::mutex lock; + + int _rotate_secret(uint32_t service_id, KeyServerData &pending_data); + void _dump_rotating_secrets(); + int _build_session_auth_info(uint32_t service_id, + const AuthTicket& parent_ticket, + CephXSessionAuthInfo& info, + double ttl); + bool _get_service_caps(const EntityName& name, uint32_t service_id, + AuthCapsInfo& caps) const; +public: + KeyServer(CephContext *cct_, KeyRing *extra_secrets); + bool generate_secret(CryptoKey& secret); + + bool get_secret(const EntityName& name, CryptoKey& secret) const override; + bool get_auth(const EntityName& name, EntityAuth& auth) const; + bool get_caps(const EntityName& name, const std::string& type, AuthCapsInfo& caps) const; + bool get_active_rotating_secret(const EntityName& name, CryptoKey& secret) const; + + void note_used_pending_key(const EntityName& name, const CryptoKey& key); + void clear_used_pending_keys(); + std::map<EntityName,CryptoKey> get_used_pending_keys(); + + int start_server(); + void rotate_timeout(double timeout); + + void dump(); + + int build_session_auth_info(uint32_t service_id, + const AuthTicket& parent_ticket, + CephXSessionAuthInfo& info); + int build_session_auth_info(uint32_t service_id, + const AuthTicket& parent_ticket, + const CryptoKey& service_secret, + uint64_t secret_id, + CephXSessionAuthInfo& info); + + /* get current secret for specific service type */ + bool get_service_secret(uint32_t service_id, CryptoKey& secret, + uint64_t& secret_id, double& ttl) const; + bool get_service_secret(uint32_t service_id, uint64_t secret_id, + CryptoKey& secret) const override; + + bool generate_secret(EntityName& name, CryptoKey& secret); + + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + encode(data, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + std::scoped_lock l{lock}; + using ceph::decode; + decode(data, bl); + } + bool contains(const EntityName& name) const; + int encode_secrets(ceph::Formatter *f, std::stringstream *ds) const; + void encode_formatted(std::string label, ceph::Formatter *f, ceph::buffer::list &bl); + void encode_plaintext(ceph::buffer::list &bl); + int list_secrets(std::stringstream& ds) const { + return encode_secrets(NULL, &ds); + } + version_t get_ver() const { + std::scoped_lock l{lock}; + return data.version; + } + + void clear_secrets() { + std::scoped_lock l{lock}; + data.clear_secrets(); + } + + void apply_data_incremental(KeyServerData::Incremental& inc) { + std::scoped_lock l{lock}; + data.apply_incremental(inc); + } + void set_ver(version_t ver) { + std::scoped_lock l{lock}; + data.version = ver; + } + + void add_auth(const EntityName& name, EntityAuth& auth) { + std::scoped_lock l{lock}; + data.add_auth(name, auth); + } + + void remove_secret(const EntityName& name) { + std::scoped_lock l{lock}; + data.remove_secret(name); + } + + bool has_secrets() { + auto b = data.secrets_begin(); + return (b != data.secrets_end()); + } + int get_num_secrets() { + std::scoped_lock l{lock}; + return data.secrets.size(); + } + + void clone_to(KeyServerData& dst) const { + std::scoped_lock l{lock}; + dst = data; + } + void export_keyring(KeyRing& keyring) { + std::scoped_lock l{lock}; + for (auto p = data.secrets.begin(); p != data.secrets.end(); ++p) { + keyring.add(p->first, p->second); + } + } + + bool prepare_rotating_update(ceph::buffer::list& rotating_bl); + + bool get_rotating_encrypted(const EntityName& name, ceph::buffer::list& enc_bl) const; + + ceph::mutex& get_lock() const { return lock; } + bool get_service_caps(const EntityName& name, uint32_t service_id, + AuthCapsInfo& caps) const; + + std::map<EntityName, EntityAuth>::iterator secrets_begin() + { return data.secrets_begin(); } + std::map<EntityName, EntityAuth>::iterator secrets_end() + { return data.secrets_end(); } +}; +WRITE_CLASS_ENCODER(KeyServer) + + +#endif |