From 87198660d50d5346e41dfc6de81dff4c5dec4031 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 17 Sep 2009 10:18:59 -0700 Subject: [PATCH] auth: rotate rotating keys every time interval --- src/Makefile.am | 6 ++ src/auth/Auth.h | 3 + src/auth/AuthServiceManager.cc | 1 - src/auth/KeyRing.cc | 105 +++++++++++++++++++++++++ src/auth/KeysServer.cc | 140 +++++++++++++++++++++++++++++++++ 5 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 src/auth/KeyRing.cc create mode 100644 src/auth/KeysServer.cc diff --git a/src/Makefile.am b/src/Makefile.am index 8c25f8429d7d0..3e44523093532 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -171,6 +171,10 @@ endif testcrypto_SOURCES = testcrypto.cc testcrypto_LDADD = libcommon.a -lcrypto bin_PROGRAMS += testcrypto + +testkeys_SOURCES = testkeys.cc +testkeys_LDADD = libcommon.a -lcrypto +bin_PROGRAMS += testkeys ## object classes # libtestclass.so: testclass.cc @@ -284,6 +288,8 @@ libcommon_files = \ auth/AuthServiceManager.cc \ auth/Crypto.cc \ auth/ExportControl.cc \ + auth/KeyRing.cc \ + auth/KeysServer.cc \ common/LogClient.cc \ msg/Message.cc \ common/Logger.cc \ diff --git a/src/auth/Auth.h b/src/auth/Auth.h index 8bc6f69143f27..8ae579304f1de 100644 --- a/src/auth/Auth.h +++ b/src/auth/Auth.h @@ -42,6 +42,9 @@ struct EntityName { }; WRITE_CLASS_ENCODER(EntityName); +inline bool operator<(const EntityName& a, const EntityName& b) { + return a.entity_type < b.entity_type || (a.entity_type == b.entity_type && a.name < b.name); +} /* * The ticket (if properly validated) authorizes the principal use * services as described by 'caps' during the specified validity diff --git a/src/auth/AuthServiceManager.cc b/src/auth/AuthServiceManager.cc index a6c3ecf40c173..8ca0064604f65 100644 --- a/src/auth/AuthServiceManager.cc +++ b/src/auth/AuthServiceManager.cc @@ -92,7 +92,6 @@ public: } }; - static CephAuthServer auth_server; /* diff --git a/src/auth/KeyRing.cc b/src/auth/KeyRing.cc new file mode 100644 index 0000000000000..47bc5f3c0f2c0 --- /dev/null +++ b/src/auth/KeyRing.cc @@ -0,0 +1,105 @@ +// -*- 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. + * + */ + +#include +#include + +#include "config.h" + +#include "Crypto.h" + +using namespace std; + +#define NUM_CONCURRENT_KEYS 3 + +/* + KeyRing is being used at the service side, for holding the temporary rotating + key of that service +*/ + +class KeyRing { + CryptoKey master; + map keys; + deque keys_fifo; + Mutex lock; +public: + KeyRing() : lock("KeyRing") {} + + bool load_master(const char *filename); + bool set_next_key(uint64_t id, CryptoKey& key); + + void get_master(CryptoKey& dest); +}; + + +bool KeyRing::load_master(const char *filename) +{ + int fd = open(filename, O_RDONLY); + if (fd < 0) { + dout(0) << "can't open key ring file " << filename << dendl; + return false; + } + + // get size + struct stat st; + int rc = fstat(fd, &st); + if (rc != 0) { + dout(0) << "error stating key ring file " << filename << dendl; + return false; + } + __int32_t len = st.st_size; + + bufferlist bl; + + bufferptr bp(len); + int off = 0; + while (off < len) { + int r = read(fd, bp.c_str()+off, len-off); + if (r < 0) { + derr(0) << "errno on read " << strerror(errno) << dendl; + return false; + } + off += r; + } + bl.append(bp); + close(fd); + + return true; +} + +bool KeyRing::set_next_key(uint64_t id, CryptoKey& key) +{ + Mutex::Locker l(lock); + + keys[id] = key; + keys_fifo.push_back(id); + + while (keys_fifo.size() > NUM_CONCURRENT_KEYS) { + uint32_t old_id = keys_fifo[0]; + keys_fifo.pop_front(); + map::iterator iter = keys.find(old_id); + assert(iter != keys.end()); + keys.erase(iter); + } + + return true; +} + +void KeyRing::get_master(CryptoKey& dest) +{ + Mutex::Locker l(lock); + + dest = master; +} + diff --git a/src/auth/KeysServer.cc b/src/auth/KeysServer.cc new file mode 100644 index 0000000000000..1da88551c7baa --- /dev/null +++ b/src/auth/KeysServer.cc @@ -0,0 +1,140 @@ +// -*- 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. + * + */ + +#include "config.h" + +#include "KeysServer.h" + +#include "Crypto.h" +#include "common/Timer.h" +#include "Auth.h" +#include "AuthProtocol.h" + +static void hexdump(string msg, const char *s, int len) +{ + int buf_len = len*4; + char buf[buf_len]; + int pos = 0; + for (int i=0; i::iterator iter = rotating_secrets.begin(); + + for (; iter != rotating_secrets.end(); ++iter) { + dout(0) << "service id: " << iter->first << dendl; + RotatingSecret& key = iter->second; + bufferptr bp = key.secret.get_secret(); + hexdump("key", bp.c_str(), bp.length()); + dout(0) << "expiration: " << key.expiration << dendl; + } +} + +void KeysServer::_rotate_secret(uint32_t service_id) +{ + RotatingSecret secret; + generate_secret(secret.secret); + secret.expiration = g_clock.now(); + secret.expiration += (KEY_ROTATE_TIME * 3); + + rotating_secrets[service_id] = secret; +} + +void KeysServer::rotate_timeout(double timeout) +{ + generate_all_rotating_secrets(); + + rotate_event = new C_RotateTimeout(this, timeout); + timer.add_event_after(timeout, rotate_event); +} + +bool KeysServer::get_secret(EntityName& name, CryptoKey& secret) +{ + Mutex::Locker l(secrets_lock); + + map::iterator iter = secrets.find(name); + if (iter == secrets.end()) + return false; + + secret = iter->second; + return true; +} + +bool KeysServer::get_service_secret(uint32_t service_id, RotatingSecret& secret) +{ + Mutex::Locker l(rotating_lock); + + map::iterator iter = rotating_secrets.find(service_id); + if (iter == rotating_secrets.end()) + return false; + + secret = iter->second; + return true; +} + +bool KeysServer::generate_secret(CryptoKey& secret) +{ + bufferptr bp; + CryptoHandler *crypto = ceph_crypto_mgr.get_crypto(CEPH_SECRET_AES); + if (!crypto) + return false; + + if (crypto->create(bp) < 0) + return false; + + secret.set_secret(CEPH_SECRET_AES, bp); + + return true; +} + +bool KeysServer::generate_secret(EntityName& name, CryptoKey& secret) +{ + if (!generate_secret(secret)) + return false; + + Mutex::Locker l(secrets_lock); + + secrets[name] = secret; + + return true; +} + -- 2.39.5