// -*- 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 * * 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 "CephxKeyServer.h" #include "common/Mutex.h" class CephContext; struct KeyServerData { version_t version; /* for each entity */ map secrets; KeyRing *extra_secrets; /* for each service type */ version_t rotating_ver; map rotating_secrets; explicit KeyServerData(KeyRing *extra) : version(0), extra_secrets(extra), rotating_ver(0) {} void encode(bufferlist& bl) const { __u8 struct_v = 1; ::encode(struct_v, bl); ::encode(version, bl); ::encode(rotating_ver, bl); ::encode(secrets, bl); ::encode(rotating_secrets, bl); } void decode(bufferlist::iterator& bl) { __u8 struct_v; ::decode(struct_v, bl); ::decode(version, bl); ::decode(rotating_ver, bl); ::decode(secrets, bl); ::decode(rotating_secrets, bl); } void encode_rotating(bufferlist& bl) const { __u8 struct_v = 1; ::encode(struct_v, bl); ::encode(rotating_ver, bl); ::encode(rotating_secrets, bl); } void decode_rotating(bufferlist& rotating_bl) { bufferlist::iterator iter = rotating_bl.begin(); __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() { secrets.clear(); } void add_auth(const EntityName& name, EntityAuth& auth) { secrets[name] = auth; } void remove_secret(const EntityName& name) { map::iterator iter = secrets.find(name); if (iter == secrets.end()) return; secrets.erase(iter); } bool get_service_secret(CephContext *cct, uint32_t service_id, ExpiringCryptoKey& secret, uint64_t& secret_id) const; bool get_service_secret(CephContext *cct, uint32_t service_id, CryptoKey& secret, uint64_t& secret_id) 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; map::iterator secrets_begin() { return secrets.begin(); } map::const_iterator secrets_begin() const { return secrets.begin(); } map::iterator secrets_end() { return secrets.end(); } map::const_iterator secrets_end() const { return secrets.end(); } map::iterator find_name(const EntityName& name) { return secrets.find(name); } map::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; bufferlist rotating_bl; // if SET_ROTATING. otherwise, EntityName name; EntityAuth auth; void encode(bufferlist& bl) const { __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(bufferlist::iterator& bl) { __u8 struct_v; ::decode(struct_v, bl); __u32 _op; ::decode(_op, bl); op = (IncrementalOp)_op; 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; mutable Mutex lock; int _rotate_secret(uint32_t service_id); bool _check_rotating_secrets(); void _dump_rotating_secrets(); int _build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info); 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 string& type, AuthCapsInfo& caps) const; bool get_active_rotating_secret(const EntityName& name, CryptoKey& secret) const; int start_server(); void rotate_timeout(double timeout); int build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info); int build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info, CryptoKey& service_secret, uint64_t secret_id); /* get current secret for specific service type */ bool get_service_secret(uint32_t service_id, ExpiringCryptoKey& service_key, uint64_t& secret_id) const; bool get_service_secret(uint32_t service_id, CryptoKey& service_key, uint64_t& secret_id) 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(bufferlist& bl) const { ::encode(data, bl); } void decode(bufferlist::iterator& bl) { Mutex::Locker l(lock); ::decode(data, bl); } bool contains(const EntityName& name) const; int encode_secrets(Formatter *f, stringstream *ds) const; void encode_formatted(string label, Formatter *f, bufferlist &bl); void encode_plaintext(bufferlist &bl); int list_secrets(stringstream& ds) const { return encode_secrets(NULL, &ds); } version_t get_ver() const { Mutex::Locker l(lock); return data.version; } void clear_secrets() { Mutex::Locker l(lock); data.clear_secrets(); } void apply_data_incremental(KeyServerData::Incremental& inc) { Mutex::Locker l(lock); data.apply_incremental(inc); } void set_ver(version_t ver) { Mutex::Locker l(lock); data.version = ver; } void add_auth(const EntityName& name, EntityAuth& auth) { Mutex::Locker l(lock); data.add_auth(name, auth); } void remove_secret(const EntityName& name) { Mutex::Locker l(lock); data.remove_secret(name); } bool has_secrets() { map::const_iterator b = data.secrets_begin(); return (b != data.secrets_end()); } int get_num_secrets() { Mutex::Locker l(lock); return data.secrets.size(); } void clone_to(KeyServerData& dst) const { Mutex::Locker l(lock); dst = data; } void export_keyring(KeyRing& keyring) { Mutex::Locker l(lock); for (map::iterator p = data.secrets.begin(); p != data.secrets.end(); ++p) { keyring.add(p->first, p->second); } } bool updated_rotating(bufferlist& rotating_bl, version_t& rotating_ver); bool get_rotating_encrypted(const EntityName& name, bufferlist& enc_bl) const; Mutex& get_lock() const { return lock; } bool get_service_caps(const EntityName& name, uint32_t service_id, AuthCapsInfo& caps) const; map::iterator secrets_begin() { return data.secrets_begin(); } map::iterator secrets_end() { return data.secrets_end(); } }; WRITE_CLASS_ENCODER(KeyServer) #endif