AuthClientProtocolHandler::AuthClientProtocolHandler(AuthClientHandler *client) :
msg(NULL), got_response(false), got_timeout(false),
- timeout_event(NULL)
+ timeout_event(NULL), lock("AuthClientProtocolHandler")
{
dout(0) << "AuthClientProtocolHandler::AuthClientProtocolHandler" << dendl;
this->client = client;
timeout_event = new C_OpTimeout(this, timeout);
client->timer.add_event_after(timeout, timeout_event);
- cond.Wait(client->lock);
+ cond.Wait(lock);
dout(0) << "got_response=" << got_response << " got_timeout=" << got_timeout << dendl;
// finish.
- client->timer.cancel_event(timeout_event);
- timeout_event = NULL;
+ if (timeout_event) {
+ client->timer.cancel_event(timeout_event);
+ timeout_event = NULL;
+ }
return status;
}
+int AuthClientProtocolHandler::do_async_request(double timeout)
+{
+ got_response = false;
+ client->client->send_message(msg);
+
+#if 0
+ // schedule timeout?
+ assert(timeout_event == 0);
+ timeout_event = new C_OpTimeout(this, timeout);
+ client->timer.add_event_after(timeout, timeout_event);
+
+
+ dout(0) << "got_response=" << got_response << " got_timeout=" << got_timeout << dendl;
+
+ // finish.
+ if (timeout_event) {
+ client->timer.cancel_event(timeout_event);
+ timeout_event = NULL;
+ }
+#endif
+
+ return 0;
+}
+
void AuthClientProtocolHandler::_request_timeout(double timeout)
{
dout(10) << "_request_timeout" << dendl;
- timeout_event = 0;
+ timeout_event = NULL;
if (!got_response) {
got_timeout = 1;
cond.Signal();
int AuthClientProtocolHandler::handle_response(int ret, bufferlist::iterator& iter)
{
- Mutex::Locker l(client->lock);
+ if (!client) {
+ derr(0) << "AuthClientProtocolHandler::handle_response() but client is NULL" << dendl;
+ return -EINVAL;
+ }
- got_response = true;
+ Mutex::Locker l(lock);
status = _handle_response(ret, iter);
- cond.Signal();
return status;
}
return err;
}
+int AuthClientHandler::send_session_request(AuthClient *client, AuthClientProtocolHandler *handler, double timeout)
+{
+ Mutex::Locker l(lock);
+ this->client = client;
+ dout(10) << "start_session" << dendl;
+
+ int err = handler->build_request();
+ dout(0) << "handler.build_request returned " << err << dendl;
+ if (err < 0)
+ return err;
+
+ err = handler->do_async_request(timeout);
+ dout(0) << "handler.do_async_request returned " << err << dendl;
+
+ return err;
+}
+
int AuthClientHandler::authorize(uint32_t service_id, double timeout)
{
Mutex::Locker l(lock);
bool got_timeout;
Context *timeout_event;
uint32_t id;
+ Mutex lock;
// session state
int status;
int handle_response(int ret, bufferlist::iterator& iter);
int do_request(double timeout);
+ int do_async_request(double timeout);
};
class AuthClientAuthenticateHandler : public AuthClientProtocolHandler {
int handle_response(Message *response);
int start_session(AuthClient *client, double timeout);
+ int send_session_request(AuthClient *client, AuthClientProtocolHandler *handler, double timeout);
int authorize(uint32_t service_id, double timeout);
void tick();
};
dest = master;
}
+bool KeyRing::need_rotating_secrets()
+{
+ Mutex::Locker l(lock);
+
+ if (rotating_secrets.secrets.size() < KEY_ROTATE_NUM)
+ return true;
+
+ map<uint64_t, ExpiringCryptoKey>::iterator iter = rotating_secrets.secrets.lower_bound(0);
+ ExpiringCryptoKey& key = iter->second;
+ if (key.expiration < g_clock.now()) {
+ dout(0) << "key.expiration=" << key.expiration << " now=" << g_clock.now() << dendl;
+ return true;
+ }
+
+ return false;
+}
void set_rotating(RotatingSecrets& secrets);
void get_master(CryptoKey& dest);
+
+ bool need_rotating_secrets();
};
Mutex::Locker l(lock);
if (init) {
- _generate_all_rotating_secrets();
+ _generate_all_rotating_secrets(init);
}
rotate_event = new C_RotateTimeout(this, KEY_ROTATE_TIME);
if (!rotate_event)
return 0;
}
-void KeysServer::_generate_all_rotating_secrets()
+void KeysServer::_generate_all_rotating_secrets(bool init)
{
data.rotating_ver++;
dout(0) << "generate_all_rotating_secrets()" << dendl;
- _rotate_secret(CEPHX_PRINCIPAL_MON);
- _rotate_secret(CEPHX_PRINCIPAL_OSD);
- _rotate_secret(CEPHX_PRINCIPAL_MDS);
+
+ int i = KEY_ROTATE_NUM;
+
+ if (init)
+ i = 1;
+
+ for (; i <= KEY_ROTATE_NUM; i++) {
+ _rotate_secret(CEPHX_PRINCIPAL_MON, i);
+ _rotate_secret(CEPHX_PRINCIPAL_OSD, i);
+ _rotate_secret(CEPHX_PRINCIPAL_MDS, i);
+ }
dout(0) << "generated: " << dendl;
}
}
-void KeysServer::_rotate_secret(uint32_t service_id)
+void KeysServer::_rotate_secret(uint32_t service_id, int factor)
{
ExpiringCryptoKey ek;
generate_secret(ek.key);
ek.expiration = g_clock.now();
- ek.expiration += (KEY_ROTATE_TIME * 3);
+ ek.expiration += (KEY_ROTATE_TIME * factor);
data.add_rotating_secret(service_id, ek);
}
void KeysServer::rotate_timeout(double timeout)
{
dout(0) << "KeysServer::rotate_timeout" << dendl;
- _generate_all_rotating_secrets();
+ _generate_all_rotating_secrets(false);
rotate_event = new C_RotateTimeout(this, timeout);
timer.add_event_after(timeout, rotate_event);
#include "common/Timer.h"
#include "Auth.h"
-#define KEY_ROTATE_TIME 5
+#define KEY_ROTATE_TIME 20
#define KEY_ROTATE_NUM 3
Context *rotate_event;
bool generate_secret(CryptoKey& secret);
- void _rotate_secret(uint32_t service_id);
- void _generate_all_rotating_secrets();
+ void _rotate_secret(uint32_t service_id, int factor);
+ void _generate_all_rotating_secrets(bool init);
public:
KeysServer();
switch (m->get_type()) {
case CEPH_MSG_MON_MAP:
+ dout(0) << "CEPH_MSG_MON_MAP begin" << dendl;
handle_monmap((MMonMap*)m);
+ dout(0) << "CEPH_MSG_MON_MAP end" << dendl;
return true;
case CEPH_MSG_CLIENT_MOUNT_ACK:
return true;
case CEPH_MSG_AUTH_REPLY:
- auth.handle_response((MAuthReply*)m);
- delete m;
+ handle_auth((MAuthReply*)m);
return true;
case CEPH_MSG_MON_SUBSCRIBE_ACK:
delete m;
}
+void MonClient::handle_auth(MAuthReply *m)
+{
+ int ret = auth.handle_response((MAuthReply*)m);
+ delete m;
+
+ if (ret == -EAGAIN) {
+ auth.send_session_request(this, &auth_handler, 30.0);
+ } else {
+ state = MC_STATE_AUTHENTICATED;
+ _reopen_session();
+ }
+}
+
+
int MonClient::authenticate(double timeout)
{
Mutex::Locker lock(monc_lock);
_pick_new_mon();
dout(0) << "_reopen_session 0" << dendl;
- auth.start_session(this, 30.0);
- dout(0) << "_reopen_session 1" << dendl;
- _start_auth_rotating(KEY_ROTATE_TIME);
+ if (state == MC_STATE_NONE) {
+ state = MC_STATE_AUTHENTICATING;
+ auth.send_session_request(this, &auth_handler, 30.0);
+ return;
+ }
+
+ if (state == MC_STATE_AUTHENTICATING)
+ return;
+
+ if (keyring && keyring->need_rotating_secrets())
+ _start_auth_rotating(KEY_ROTATE_TIME);
dout(0) << "_reopen_session 2" << dendl;
if (mounting)
{
dout(10) << "tick" << dendl;
+ if (keyring && keyring->need_rotating_secrets()) {
+ dout(0) << "MonClient::tick: need rotating secret" << dendl;
+ _start_auth_rotating(KEY_ROTATE_TIME);
+ }
+
if (hunting) {
dout(0) << "continuing hunt" << dendl;
auth.start_session(this, 30.0);
return -ETIMEDOUT;
}
- timer.cancel_event(auth_timeout_event);
- auth_timeout_event = NULL;
+ if (auth_timeout_event) {
+ timer.cancel_event(auth_timeout_event);
+ auth_timeout_event = NULL;
+ }
return 0;
}
class MMonSubscribeAck;
class MAuthRotating;
+
+enum MonClientState {
+ MC_STATE_NONE,
+ MC_STATE_AUTHENTICATING,
+ MC_STATE_AUTHENTICATED,
+};
+
class MonClient : public Dispatcher, public AuthClient {
public:
MonMap monmap;
private:
+ MonClientState state;
+
Messenger *messenger;
int cur_mon;
void handle_monmap(MMonMap *m);
+ void handle_auth(MAuthReply *m);
+
// monitor session
bool hunting;
// auth tickets
public:
AuthClientHandler auth;
+ AuthClientAuthenticateHandler auth_handler;
double auth_timeout;
public:
void renew_subs() {
}
public:
- MonClient() : messenger(NULL), cur_mon(-1),
+ MonClient() : state(MC_STATE_NONE),
+ messenger(NULL), cur_mon(-1),
monc_lock("MonClient::monc_lock"),
timer(monc_lock),
hunting(false),
auth_timeout_event(NULL),
auth_got_timeout(false),
keyring(NULL),
- mounting(0), mount_err(0) { }
+ mounting(0), mount_err(0),
+ auth_handler(&auth, 0, 0) { }
~MonClient() {
timer.cancel_all_events();
}