/*
* Key management
*/
-#define KEY_ROTATE_TIME 20
#define KEY_ROTATE_NUM 3
struct ExpiringCryptoKey {
{
dout(10) << "build_request" << dendl;
+ dout(10) << "validate_tickets: want=" << want << " need=" << need << " have=" << have << dendl;
validate_tickets();
dout(10) << "want=" << want << " need=" << need << " have=" << have << dendl;
if (need) {
/* get service tickets */
- dout(10) << "get service keys: want=" << hex << want << " need=" << need << " have=" << have << dec << dendl;
+ dout(10) << "get service keys: want=" << want << " need=" << need << " have=" << have << dendl;
CephXRequestHeader header;
header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY;
dout(0) << "could not verify service_ticket reply" << dendl;
return -EPERM;
}
- if (want == have)
+ validate_tickets();
+ if (!need) {
ret = 0;
+ }
}
break;
void CephxClientHandler::validate_tickets()
{
- tickets.validate_tickets(want, need);
+ tickets.validate_tickets(want, have, need);
}
bool CephxClientHandler::need_tickets()
{
validate_tickets();
+
+ dout(20) << "need_tickets: want=" << want << " need=" << need << " have=" << have << dendl;
+
return (need != 0);
}
{
data.rotating_ver++;
data.next_rotating_time = g_clock.now();
- data.next_rotating_time += KEY_ROTATE_TIME;
+ data.next_rotating_time += g_conf.auth_mon_ticket_ttl;
dout(0) << "generate_all_rotating_secrets()" << dendl;
int i = KEY_ROTATE_NUM;
ExpiringCryptoKey ek;
generate_secret(ek.key);
ek.expiration = g_clock.now();
- ek.expiration += (KEY_ROTATE_TIME * factor);
+ ek.expiration += (g_conf.auth_mon_ticket_ttl * factor);
data.add_rotating_secret(service_id, ek);
}
CephXServiceTicket msg_a;
msg_a.session_key = info.session_key;
+ msg_a.validity = info.validity;
if (encode_encrypt(msg_a, principal_secret, reply) < 0)
return false;
<< " session_key " << msg_a.session_key
<< " validity=" << msg_a.validity << dendl;
session_key = msg_a.session_key;
- has_key_flag = true;
+ if (!msg_a.validity.is_zero()) {
+ expires = g_clock.now();
+ expires += msg_a.validity;
+ renew_after = expires;
+ renew_after -= ((double)msg_a.validity.sec() / 4);
+ dout(10) << "ticket expires=" << expires << " renew_after=" << renew_after << dendl;
+ }
+
+ have_key_flag = true;
return true;
}
-bool CephXTicketHandler::has_key()
+bool CephXTicketHandler::have_key()
{
- if (has_key_flag) {
- has_key_flag = g_clock.now() < expires;
+ if (have_key_flag) {
+ dout(20) << "have_key: g_clock.now()=" << g_clock.now() << " renew_after=" << renew_after << " expires=" << expires << dendl;
+ have_key_flag = g_clock.now() < expires;
}
- return has_key_flag;
+ return have_key_flag;
}
-bool CephXTicketHandler::needs_key()
+bool CephXTicketHandler::need_key()
{
- if (has_key_flag) {
+ if (have_key_flag) {
+ dout(20) << "need_key: g_clock.now()=" << g_clock.now() << " renew_after=" << renew_after << " expires=" << expires << dendl;
return (!expires.is_zero()) && (g_clock.now() >= renew_after);
}
return true;
}
-bool CephXTicketManager::has_key(uint32_t service_id)
+bool CephXTicketManager::have_key(uint32_t service_id)
{
map<uint32_t, CephXTicketHandler>::iterator iter = tickets_map.find(service_id);
if (iter == tickets_map.end())
return false;
- return iter->second.has_key();
+ return iter->second.have_key();
}
-bool CephXTicketManager::needs_key(uint32_t service_id)
+bool CephXTicketManager::need_key(uint32_t service_id)
{
map<uint32_t, CephXTicketHandler>::iterator iter = tickets_map.find(service_id);
if (iter == tickets_map.end())
return true;
- return iter->second.needs_key();
+ return iter->second.need_key();
+}
+
+void CephXTicketManager::set_have_need_key(uint32_t service_id, uint32_t& have, uint32_t& need)
+{
+ map<uint32_t, CephXTicketHandler>::iterator iter = tickets_map.find(service_id);
+ if (iter == tickets_map.end()) {
+ have &= ~service_id;
+ need |= service_id;
+ dout(0) << "couldn't find entry for service_id " << service_id << dendl;
+ return;
+ }
+
+ dout(10) << "service_id=" << service_id << " need=" << iter->second.need_key() << " have=" << iter->second.have_key() << dendl;
+ if (iter->second.need_key())
+ need |= service_id;
+ else
+ need &= ~service_id;
+
+ if (iter->second.have_key())
+ have |= service_id;
+ else
+ have &= ~service_id;
}
/*
return handler.build_authorizer();
}
-void CephXTicketManager::validate_tickets(uint32_t mask, uint32_t& need)
+void CephXTicketManager::validate_tickets(uint32_t mask, uint32_t& have, uint32_t& need)
{
uint32_t i;
need = 0;
for (i = 1; i<=mask; i<<=1) {
- if ((mask & i) && needs_key(i)) {
- need |= i;
+ if (mask & i) {
+ set_have_need_key(i, have, need);
}
}
}
AuthTicket ticket;
CryptoKey session_key;
CryptoKey service_secret;
+ utime_t validity;
};
CryptoKey session_key;
AuthBlob ticket; // opaque to us
utime_t renew_after, expires;
- bool has_key_flag;
+ bool have_key_flag;
- CephXTicketHandler() : service_id(0), has_key_flag(false) {}
+ CephXTicketHandler() : service_id(0), have_key_flag(false) {}
// to build our ServiceTicket
bool verify_service_ticket_reply(CryptoKey& principal_secret,
// to access the service
CephXAuthorizer *build_authorizer();
- bool has_key();
- bool needs_key();
+ bool have_key();
+ bool need_key();
};
struct CephXTicketManager {
return handler;
}
CephXAuthorizer *build_authorizer(uint32_t service_id);
- bool has_key(uint32_t service_id);
- bool needs_key(uint32_t service_id);
- void validate_tickets(uint32_t mask, uint32_t& need);
+ bool have_key(uint32_t service_id);
+ bool need_key(uint32_t service_id);
+ void set_have_need_key(uint32_t service_id, uint32_t& have, uint32_t& need);
+ void validate_tickets(uint32_t mask, uint32_t& have, uint32_t& need);
};
for (int pos = 0; pos + sizeof(req.key) <= key_enc.length(); pos+=sizeof(req.key), p++) {
expected_key ^= *p;
}
- dout(0) << " checking key: req.key=" << hex << req.key << " expected_key=" << expected_key << dec << dendl;
+ dout(20) << " checking key: req.key=" << hex << req.key << " expected_key=" << expected_key << dec << dendl;
if (req.key != expected_key) {
dout(0) << " unexpected key: req.key=" << req.key << " expected_key=" << expected_key << dendl;
ret = -EPERM;
break;
}
- info.ticket.name = req.name;
info.ticket.init_timestamps(g_clock.now(), g_conf.auth_mon_ticket_ttl);
+ info.ticket.name = req.name;
+ info.validity += g_conf.auth_mon_ticket_ttl;
key_server->generate_secret(session_key);
ret = r;
break;
}
+ info.validity += g_conf.auth_service_ticket_ttl;
info_vec.push_back(info);
}
}
OPTION(mon_clientid_prealloc, 0, OPT_INT, 100), // how many clientids to prealloc
OPTION(paxos_propose_interval, 0, OPT_DOUBLE, 1.0), // gather updates for this long before proposing a map update
OPTION(paxos_observer_timeout, 0, OPT_DOUBLE, 5*60), // gather updates for this long before proposing a map update
- OPTION(auth_mon_ticket_ttl, 0, OPT_DOUBLE, 60*60*24),
+ OPTION(auth_mon_ticket_ttl, 0, OPT_DOUBLE, 60*60*12),
OPTION(auth_service_ticket_ttl, 0, OPT_DOUBLE, 60*60),
OPTION(auth_nonce_len, 0, OPT_INT, 16),
OPTION(client_cache_size, 0, OPT_INT, 1000),
int MonClient::_check_auth_rotating()
{
if (state == MC_STATE_HAVE_SESSION && auth && auth->need_tickets()) {
+ dout(10) << "need new tickets!" << dendl;
MAuth *m = new MAuth;
m->protocol = auth->get_protocol();
auth->build_request(m->auth_payload);
r = rados.write(pool, oid, 0, bl, bl.length() - 2);
cout << "rados.write returned " << r << std::endl;
r = rados.write(pool, oid, 0, bl, bl.length() - 3);
+ cout << "*** press enter to continue ***" << std::endl;
+ getchar();
cout << "rados.write returned " << r << std::endl;
r = rados.write(pool, oid, 0, bl, bl.length() - 4);
cout << "rados.write returned " << r << std::endl;