#undef dout_prefix
#define dout_prefix *_dout << "cephx client: "
+void CephxClientHandler::reset()
+{
+ ldout(cct,10) << __func__ << dendl;
+ starting = true;
+ server_challenge = 0;
+}
+
int CephxClientHandler::build_request(bufferlist& bl) const
{
ldout(cct, 10) << "build_request" << dendl;
req.old_ticket = ticket_handler->ticket;
+ // for nautilus+ servers: request other keys at the same time
+ req.other_keys = need;
+
if (req.old_ticket.blob.length()) {
ldout(cct, 20) << "old ticket len=" << req.old_ticket.blob.length() << dendl;
}
CryptoKey *session_key,
CryptoKey *connection_secret)
{
- ldout(cct, 10) << "handle_response ret = " << ret << dendl;
+ ldout(cct, 10) << this << " handle_response ret = " << ret << dendl;
if (ret < 0)
return ret; // hrm!
return -EPERM;
}
ldout(cct, 10) << " want=" << want << " need=" << need << " have=" << have << dendl;
+ if (!indata.end()) {
+ bufferlist cbl, extra_tickets;
+ decode(cbl, indata);
+ decode(extra_tickets, indata);
+ ldout(cct, 10) << " got connection bl " << cbl.length()
+ << " and extra tickets " << extra_tickets.length()
+ << dendl;
+ if (session_key && connection_secret) {
+ CephXTicketHandler& ticket_handler =
+ tickets.get_handler(CEPH_ENTITY_TYPE_AUTH);
+ if (session_key) {
+ *session_key = ticket_handler.session_key;
+ }
+ if (cbl.length() && connection_secret) {
+ auto p = cbl.cbegin();
+ string err;
+ if (decode_decrypt(cct, *connection_secret, *session_key, p,
+ err) < 0) {
+ lderr(cct) << __func__ << " failed to decrypt connection_secret"
+ << dendl;
+ } else {
+ ldout(cct, 10) << " got connection_secret " << dendl;
+ }
+ }
+ if (extra_tickets.length()) {
+ auto p = extra_tickets.cbegin();
+ if (!tickets.verify_service_ticket_reply(
+ *session_key, p)) {
+ lderr(cct) << "could not verify extra service_tickets" << dendl;
+ } else {
+ ldout(cct, 10) << " got extra service_tickets" << dendl;
+ }
+ }
+ }
+ }
validate_tickets();
if (_need_tickets())
ret = -EAGAIN;
else
ret = 0;
- }
+ }
break;
case CEPHX_GET_PRINCIPAL_SESSION_KEY:
reset();
}
- void reset() override {
- starting = true;
- server_challenge = 0;
- }
+ void reset() override;
void prepare_build_request() override;
int build_request(bufferlist& bl) const override;
int handle_response(int ret, bufferlist::const_iterator& iter,
ticket_info.ticket = info.ticket;
ticket_info.ticket.caps = info.ticket.caps;
- ldout(cct, 10) << "build_service_ticket service " << ceph_entity_type_name(info.service_id)
- << " secret_id " << info.secret_id
- << " ticket_info.ticket.name=" << ticket_info.ticket.name.to_str() << dendl;
+ ldout(cct, 10) << "build_service_ticket service "
+ << ceph_entity_type_name(info.service_id)
+ << " secret_id " << info.secret_id
+ << " ticket_info.ticket.name="
+ << ticket_info.ticket.name.to_str()
+ << " ticket.global_id " << info.ticket.global_id << dendl;
blob.secret_id = info.secret_id;
std::string error;
if (!info.service_secret.get_secret().length())
* PRINCIPAL: verify our attempt to authenticate succeeded. fill out
* this ServiceTicket with the result.
*/
-bool CephXTicketHandler::verify_service_ticket_reply(CryptoKey& secret,
- bufferlist::const_iterator& indata)
+bool CephXTicketHandler::verify_service_ticket_reply(
+ CryptoKey& secret,
+ bufferlist::const_iterator& indata)
{
__u8 service_ticket_v;
decode(service_ticket_v, indata);
handler.service_id = type;
}
- if (!indata.end())
- return false;
-
return true;
}
uint64_t client_challenge;
uint64_t key;
CephXTicketBlob old_ticket;
+ uint32_t other_keys = 0; // replaces CephXServiceTicketRequest
void encode(bufferlist& bl) const {
- using ceph::encode;
- __u8 struct_v = 1;
- encode(struct_v, bl);
- encode(client_challenge, bl);
- encode(key, bl);
- encode(old_ticket, bl);
+ using ceph::encode;
+ __u8 struct_v = 2;
+ encode(struct_v, bl);
+ encode(client_challenge, bl);
+ encode(key, bl);
+ encode(old_ticket, bl);
+ encode(other_keys, bl);
}
void decode(bufferlist::const_iterator& bl) {
- using ceph::decode;
- __u8 struct_v;
- decode(struct_v, bl);
- decode(client_challenge, bl);
- decode(key, bl);
- decode(old_ticket, bl);
- }
+ using ceph::decode;
+ __u8 struct_v;
+ decode(struct_v, bl);
+ decode(client_challenge, bl);
+ decode(key, bl);
+ decode(old_ticket, bl);
+ if (struct_v >= 2) {
+ decode(other_keys, bl);
+ }
+ }
};
WRITE_CLASS_ENCODER(CephXAuthenticate)
bufferlist *result_bl,
uint64_t *global_id,
AuthCapsInfo *caps,
- CryptoKey *session_key,
- CryptoKey *connection_secret)
+ CryptoKey *psession_key,
+ CryptoKey *pconnection_secret)
{
int ret = 0;
should_enc_ticket = true;
}
+ ldout(cct,10) << __func__ << " auth ticket global_id " << *global_id
+ << dendl;
info.ticket.init_timestamps(ceph_clock_now(),
cct->_conf->auth_mon_ticket_ttl);
info.ticket.name = entity_name;
key_server->generate_secret(session_key);
info.session_key = session_key;
+ if (psession_key) {
+ *psession_key = session_key;
+ }
info.service_id = CEPH_ENTITY_TYPE_AUTH;
if (!key_server->get_service_secret(CEPH_ENTITY_TYPE_AUTH, info.service_secret, info.secret_id)) {
ldout(cct, 0) << " could not get service secret for auth subsystem" << dendl;
ret = -EACCES;
break;
}
+
+ if (req.other_keys) {
+ // nautilus+ client
+ // generate a connection_secret
+ bufferlist cbl;
+ if (pconnection_secret) {
+ key_server->generate_secret(*pconnection_secret);
+ string err;
+ encode_encrypt(cct, *pconnection_secret, session_key, cbl, err);
+ }
+ encode(cbl, *result_bl);
+ // provite all of the other tickets at the same time
+ vector<CephXSessionAuthInfo> info_vec;
+ for (uint32_t service_id = 1; service_id <= req.other_keys;
+ service_id <<= 1) {
+ if (req.other_keys & service_id) {
+ ldout(cct, 10) << " adding key for service "
+ << ceph_entity_type_name(service_id) << dendl;
+ CephXSessionAuthInfo svc_info;
+ key_server->build_session_auth_info(
+ service_id,
+ info.ticket,
+ svc_info);
+ svc_info.validity += cct->_conf->auth_service_ticket_ttl;
+ info_vec.push_back(svc_info);
+ }
+ }
+ bufferlist extra;
+ if (!info_vec.empty()) {
+ CryptoKey no_key;
+ cephx_build_service_ticket_reply(
+ cct, session_key, info_vec, false, no_key, extra);
+ }
+ encode(extra, *result_bl);
+ }
+
// caller should try to finish authentication
ret = 1;
}
// note: no challenge here.
if (!cephx_verify_authorizer(
cct, key_server, indata, auth_ticket_info, nullptr,
-#warning FIXME mon connection needs connection_secret too
nullptr,
tmp_bl)) {
ret = -EPERM;