X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fauth%2Fcephx%2FCephxProtocol.cc;fp=src%2Fceph%2Fsrc%2Fauth%2Fcephx%2FCephxProtocol.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=5836a33bd531e7a31e662d6d93a5098150a4625b;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/auth/cephx/CephxProtocol.cc b/src/ceph/src/auth/cephx/CephxProtocol.cc deleted file mode 100644 index 5836a33..0000000 --- a/src/ceph/src/auth/cephx/CephxProtocol.cc +++ /dev/null @@ -1,495 +0,0 @@ -// -*- 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) 2009-2011 New Dream Network - * - * 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 "CephxProtocol.h" -#include "common/Clock.h" -#include "common/config.h" -#include "common/debug.h" -#include "include/buffer.h" - -#define dout_subsys ceph_subsys_auth -#undef dout_prefix -#define dout_prefix *_dout << "cephx: " - - - -void cephx_calc_client_server_challenge(CephContext *cct, CryptoKey& secret, uint64_t server_challenge, - uint64_t client_challenge, uint64_t *key, std::string &error) -{ - CephXChallengeBlob b; - b.server_challenge = server_challenge; - b.client_challenge = client_challenge; - - bufferlist enc; - if (encode_encrypt(cct, b, secret, enc, error)) - return; - - uint64_t k = 0; - const uint64_t *p = (const uint64_t *)enc.c_str(); - for (int pos = 0; pos + sizeof(k) <= enc.length(); pos+=sizeof(k), p++) - k ^= mswab(*p); - *key = k; -} - - -/* - * Authentication - */ - -bool cephx_build_service_ticket_blob(CephContext *cct, CephXSessionAuthInfo& info, - CephXTicketBlob& blob) -{ - CephXServiceTicketInfo ticket_info; - ticket_info.session_key = info.session_key; - 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; - blob.secret_id = info.secret_id; - std::string error; - if (!info.service_secret.get_secret().length()) - error = "invalid key"; // Bad key? - else - encode_encrypt_enc_bl(cct, ticket_info, info.service_secret, blob.blob, error); - if (!error.empty()) { - ldout(cct, -1) << "cephx_build_service_ticket_blob failed with error " - << error << dendl; - return false; - } - return true; -} - -/* - * AUTH SERVER: authenticate - * - * Authenticate principal, respond with AuthServiceTicketInfo - * - * {session key, validity}^principal_secret - * {principal_ticket, session key}^service_secret ... "enc_ticket" - */ -bool cephx_build_service_ticket_reply(CephContext *cct, - CryptoKey& principal_secret, - vector ticket_info_vec, - bool should_encrypt_ticket, - CryptoKey& ticket_enc_key, - bufferlist& reply) -{ - __u8 service_ticket_reply_v = 1; - ::encode(service_ticket_reply_v, reply); - - uint32_t num = ticket_info_vec.size(); - ::encode(num, reply); - ldout(cct, 10) << "build_service_ticket_reply encoding " << num - << " tickets with secret " << principal_secret << dendl; - - for (vector::iterator ticket_iter = ticket_info_vec.begin(); - ticket_iter != ticket_info_vec.end(); - ++ticket_iter) { - CephXSessionAuthInfo& info = *ticket_iter; - ::encode(info.service_id, reply); - - __u8 service_ticket_v = 1; - ::encode(service_ticket_v, reply); - - CephXServiceTicket msg_a; - msg_a.session_key = info.session_key; - msg_a.validity = info.validity; - std::string error; - if (encode_encrypt(cct, msg_a, principal_secret, reply, error)) { - ldout(cct, -1) << "error encoding encrypted: " << error << dendl; - return false; - } - - bufferlist service_ticket_bl; - CephXTicketBlob blob; - if (!cephx_build_service_ticket_blob(cct, info, blob)) { - return false; - } - ::encode(blob, service_ticket_bl); - - ldout(cct, 30) << "service_ticket_blob is "; - service_ticket_bl.hexdump(*_dout); - *_dout << dendl; - - ::encode((__u8)should_encrypt_ticket, reply); - if (should_encrypt_ticket) { - if (encode_encrypt(cct, service_ticket_bl, ticket_enc_key, reply, error)) { - ldout(cct, -1) << "error encoding encrypted ticket: " << error << dendl; - return false; - } - } else { - ::encode(service_ticket_bl, reply); - } - } - return true; -} - -/* - * PRINCIPAL: verify our attempt to authenticate succeeded. fill out - * this ServiceTicket with the result. - */ -bool CephXTicketHandler::verify_service_ticket_reply(CryptoKey& secret, - bufferlist::iterator& indata) -{ - __u8 service_ticket_v; - ::decode(service_ticket_v, indata); - - CephXServiceTicket msg_a; - std::string error; - if (decode_decrypt(cct, msg_a, secret, indata, error)) { - ldout(cct, 0) << "verify_service_ticket_reply: failed decode_decrypt, error is: " << error << dendl; - return false; - } - - __u8 ticket_enc; - ::decode(ticket_enc, indata); - - bufferlist service_ticket_bl; - if (ticket_enc) { - ldout(cct, 10) << " got encrypted ticket" << dendl; - std::string error; - if (decode_decrypt(cct, service_ticket_bl, session_key, indata, error)) { - ldout(cct, 10) << "verify_service_ticket_reply: decode_decrypt failed " - << "with " << error << dendl; - return false; - } - } else { - ::decode(service_ticket_bl, indata); - } - bufferlist::iterator iter = service_ticket_bl.begin(); - ::decode(ticket, iter); - ldout(cct, 10) << " ticket.secret_id=" << ticket.secret_id << dendl; - - ldout(cct, 10) << "verify_service_ticket_reply service " << ceph_entity_type_name(service_id) - << " secret_id " << ticket.secret_id - << " session_key " << msg_a.session_key - << " validity=" << msg_a.validity << dendl; - session_key = msg_a.session_key; - if (!msg_a.validity.is_zero()) { - expires = ceph_clock_now(); - expires += msg_a.validity; - renew_after = expires; - renew_after -= ((double)msg_a.validity.sec() / 4); - ldout(cct, 10) << "ticket expires=" << expires << " renew_after=" << renew_after << dendl; - } - - have_key_flag = true; - return true; -} - -bool CephXTicketHandler::have_key() -{ - if (have_key_flag) { - have_key_flag = ceph_clock_now() < expires; - } - - return have_key_flag; -} - -bool CephXTicketHandler::need_key() const -{ - if (have_key_flag) { - return (!expires.is_zero()) && (ceph_clock_now() >= renew_after); - } - - return true; -} - -bool CephXTicketManager::have_key(uint32_t service_id) -{ - map::iterator iter = tickets_map.find(service_id); - if (iter == tickets_map.end()) - return false; - return iter->second.have_key(); -} - -bool CephXTicketManager::need_key(uint32_t service_id) const -{ - map::const_iterator iter = tickets_map.find(service_id); - if (iter == tickets_map.end()) - return true; - return iter->second.need_key(); -} - -void CephXTicketManager::set_have_need_key(uint32_t service_id, uint32_t& have, uint32_t& need) -{ - map::iterator iter = tickets_map.find(service_id); - if (iter == tickets_map.end()) { - have &= ~service_id; - need |= service_id; - ldout(cct, 10) << "set_have_need_key no handler for service " - << ceph_entity_type_name(service_id) << dendl; - return; - } - - //ldout(cct, 10) << "set_have_need_key service " << ceph_entity_type_name(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; -} - -void CephXTicketManager::invalidate_ticket(uint32_t service_id) -{ - map::iterator iter = tickets_map.find(service_id); - if (iter != tickets_map.end()) - iter->second.invalidate_ticket(); -} - -/* - * PRINCIPAL: verify our attempt to authenticate succeeded. fill out - * this ServiceTicket with the result. - */ -bool CephXTicketManager::verify_service_ticket_reply(CryptoKey& secret, - bufferlist::iterator& indata) -{ - __u8 service_ticket_reply_v; - ::decode(service_ticket_reply_v, indata); - - uint32_t num; - ::decode(num, indata); - ldout(cct, 10) << "verify_service_ticket_reply got " << num << " keys" << dendl; - - for (int i=0; i<(int)num; i++) { - uint32_t type; - ::decode(type, indata); - ldout(cct, 10) << "got key for service_id " << ceph_entity_type_name(type) << dendl; - CephXTicketHandler& handler = get_handler(type); - if (!handler.verify_service_ticket_reply(secret, indata)) { - return false; - } - handler.service_id = type; - } - - if (!indata.end()) - return false; - - return true; -} - -/* - * PRINCIPAL: build authorizer to access the service. - * - * ticket, {timestamp}^session_key - */ -CephXAuthorizer *CephXTicketHandler::build_authorizer(uint64_t global_id) const -{ - CephXAuthorizer *a = new CephXAuthorizer(cct); - a->session_key = session_key; - a->nonce = ((uint64_t)rand() << 32) + rand(); - - __u8 authorizer_v = 1; - ::encode(authorizer_v, a->bl); - ::encode(global_id, a->bl); - ::encode(service_id, a->bl); - - ::encode(ticket, a->bl); - - CephXAuthorize msg; - msg.nonce = a->nonce; - - std::string error; - if (encode_encrypt(cct, msg, session_key, a->bl, error)) { - ldout(cct, 0) << "failed to encrypt authorizer: " << error << dendl; - delete a; - return 0; - } - return a; -} - -/* - * PRINCIPAL: build authorizer to access the service. - * - * ticket, {timestamp}^session_key - */ -CephXAuthorizer *CephXTicketManager::build_authorizer(uint32_t service_id) const -{ - map::const_iterator iter = tickets_map.find(service_id); - if (iter == tickets_map.end()) { - ldout(cct, 0) << "no TicketHandler for service " - << ceph_entity_type_name(service_id) << dendl; - return NULL; - } - - const CephXTicketHandler& handler = iter->second; - return handler.build_authorizer(global_id); -} - -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) { - set_have_need_key(i, have, need); - } - } - ldout(cct, 10) << "validate_tickets want " << mask << " have " << have - << " need " << need << dendl; -} - -bool cephx_decode_ticket(CephContext *cct, KeyStore *keys, uint32_t service_id, - CephXTicketBlob& ticket_blob, CephXServiceTicketInfo& ticket_info) -{ - uint64_t secret_id = ticket_blob.secret_id; - CryptoKey service_secret; - - if (!ticket_blob.blob.length()) { - return false; - } - - if (secret_id == (uint64_t)-1) { - if (!keys->get_secret(cct->_conf->name, service_secret)) { - ldout(cct, 0) << "ceph_decode_ticket could not get general service secret for service_id=" - << ceph_entity_type_name(service_id) << " secret_id=" << secret_id << dendl; - return false; - } - } else { - if (!keys->get_service_secret(service_id, secret_id, service_secret)) { - ldout(cct, 0) << "ceph_decode_ticket could not get service secret for service_id=" - << ceph_entity_type_name(service_id) << " secret_id=" << secret_id << dendl; - return false; - } - } - - std::string error; - decode_decrypt_enc_bl(cct, ticket_info, service_secret, ticket_blob.blob, error); - if (!error.empty()) { - ldout(cct, 0) << "ceph_decode_ticket could not decrypt ticket info. error:" - << error << dendl; - return false; - } - - return true; -} - -/* - * SERVICE: verify authorizer and generate reply authorizer - * - * {timestamp + 1}^session_key - */ -bool cephx_verify_authorizer(CephContext *cct, KeyStore *keys, - bufferlist::iterator& indata, - CephXServiceTicketInfo& ticket_info, bufferlist& reply_bl) -{ - __u8 authorizer_v; - uint32_t service_id; - uint64_t global_id; - CryptoKey service_secret; - // ticket blob - CephXTicketBlob ticket; - - - try { - ::decode(authorizer_v, indata); - ::decode(global_id, indata); - ::decode(service_id, indata); - ::decode(ticket, indata); - } catch (buffer::end_of_buffer &e) { - // Unable to decode! - return false; - } - ldout(cct, 10) << "verify_authorizer decrypted service " - << ceph_entity_type_name(service_id) - << " secret_id=" << ticket.secret_id << dendl; - - if (ticket.secret_id == (uint64_t)-1) { - EntityName name; - name.set_type(service_id); - if (!keys->get_secret(name, service_secret)) { - ldout(cct, 0) << "verify_authorizer could not get general service secret for service " - << ceph_entity_type_name(service_id) << " secret_id=" << ticket.secret_id << dendl; - return false; - } - } else { - if (!keys->get_service_secret(service_id, ticket.secret_id, service_secret)) { - ldout(cct, 0) << "verify_authorizer could not get service secret for service " - << ceph_entity_type_name(service_id) << " secret_id=" << ticket.secret_id << dendl; - if (cct->_conf->auth_debug && ticket.secret_id == 0) - assert(0 == "got secret_id=0"); - return false; - } - } - std::string error; - if (!service_secret.get_secret().length()) - error = "invalid key"; // Bad key? - else - decode_decrypt_enc_bl(cct, ticket_info, service_secret, ticket.blob, error); - if (!error.empty()) { - ldout(cct, 0) << "verify_authorizer could not decrypt ticket info: error: " - << error << dendl; - return false; - } - - if (ticket_info.ticket.global_id != global_id) { - ldout(cct, 0) << "verify_authorizer global_id mismatch: declared id=" << global_id - << " ticket_id=" << ticket_info.ticket.global_id << dendl; - return false; - } - - ldout(cct, 10) << "verify_authorizer global_id=" << global_id << dendl; - - // CephXAuthorize - CephXAuthorize auth_msg; - if (decode_decrypt(cct, auth_msg, ticket_info.session_key, indata, error)) { - ldout(cct, 0) << "verify_authorizercould not decrypt authorize request with error: " - << error << dendl; - return false; - } - - /* - * Reply authorizer: - * {timestamp + 1}^session_key - */ - CephXAuthorizeReply reply; - // reply.trans_id = auth_msg.trans_id; - reply.nonce_plus_one = auth_msg.nonce + 1; - if (encode_encrypt(cct, reply, ticket_info.session_key, reply_bl, error)) { - ldout(cct, 10) << "verify_authorizer: encode_encrypt error: " << error << dendl; - return false; - } - - ldout(cct, 10) << "verify_authorizer ok nonce " << hex << auth_msg.nonce << dec - << " reply_bl.length()=" << reply_bl.length() << dendl; - return true; -} - -bool CephXAuthorizer::verify_reply(bufferlist::iterator& indata) -{ - CephXAuthorizeReply reply; - - std::string error; - if (decode_decrypt(cct, reply, session_key, indata, error)) { - ldout(cct, 0) << "verify_reply couldn't decrypt with error: " << error << dendl; - return false; - } - - uint64_t expect = nonce + 1; - if (expect != reply.nonce_plus_one) { - ldout(cct, 0) << "verify_authorizer_reply bad nonce got " << reply.nonce_plus_one << " expected " << expect - << " sent " << nonce << dendl; - return false; - } - return true; -} -