diff --git a/src/auth/cephx/CephxSessionHandler.cc b/src/auth/cephx/CephxSessionHandler.cc index f2e332b41b309..802b93cda52de 100644 --- a/src/auth/cephx/CephxSessionHandler.cc +++ b/src/auth/cephx/CephxSessionHandler.cc @@ -29,42 +29,88 @@ int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig) const ceph_msg_header& header = m->get_header(); const ceph_msg_footer& footer = m->get_footer(); - // optimized signature calculation - // - avoid temporary allocated buffers from encode_encrypt[_enc_bl] - // - skip the leading 4 byte wrapper from encode_encrypt - struct { - __u8 v; - __le64 magic; - __le32 len; - __le32 header_crc; - __le32 front_crc; - __le32 middle_crc; - __le32 data_crc; - } __attribute__ ((packed)) sigblock = { - 1, mswab(AUTH_ENC_MAGIC), mswab(4*4), - mswab(header.crc), mswab(footer.front_crc), - mswab(footer.middle_crc), mswab(footer.data_crc) - }; - - char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))]; - - try { - const CryptoKey::in_slice_t in { - sizeof(sigblock), - reinterpret_cast(&sigblock) + if (!HAVE_FEATURE(features, CEPHX_V2)) { + // legacy pre-mimic behavior for compatibility + + // optimized signature calculation + // - avoid temporary allocated buffers from encode_encrypt[_enc_bl] + // - skip the leading 4 byte wrapper from encode_encrypt + struct { + __u8 v; + __le64 magic; + __le32 len; + __le32 header_crc; + __le32 front_crc; + __le32 middle_crc; + __le32 data_crc; + } __attribute__ ((packed)) sigblock = { + 1, mswab(AUTH_ENC_MAGIC), mswab(4*4), + mswab(header.crc), mswab(footer.front_crc), + mswab(footer.middle_crc), mswab(footer.data_crc) }; - const CryptoKey::out_slice_t out { - sizeof(exp_buf), - reinterpret_cast(&exp_buf) + + char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))]; + + try { + const CryptoKey::in_slice_t in { + sizeof(sigblock), + reinterpret_cast(&sigblock) + }; + const CryptoKey::out_slice_t out { + sizeof(exp_buf), + reinterpret_cast(&exp_buf) + }; + key.encrypt(cct, in, out); + } catch (std::exception& e) { + lderr(cct) << __func__ << " failed to encrypt signature block" << dendl; + return -1; + } + + *psig = *reinterpret_cast<__le64*>(exp_buf); + } else { + // newer mimic+ signatures + struct { + __le32 header_crc; + __le32 front_crc; + __le32 front_len; + __le32 middle_crc; + __le32 middle_len; + __le32 data_crc; + __le32 data_len; + __le32 seq_lower_word; + } __attribute__ ((packed)) sigblock = { + mswab(header.crc), + mswab(footer.front_crc), + mswab(header.front_len), + mswab(footer.middle_crc), + mswab(header.middle_len), + mswab(footer.data_crc), + mswab(header.data_len), + mswab(header.seq) }; - key.encrypt(cct, in, out); - } catch (std::exception& e) { - lderr(cct) << __func__ << " failed to encrypt signature block" << dendl; - return -1; - } + char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))]; + + try { + const CryptoKey::in_slice_t in { + sizeof(sigblock), + reinterpret_cast(&sigblock) + }; + const CryptoKey::out_slice_t out { + sizeof(exp_buf), + reinterpret_cast(&exp_buf) + }; + key.encrypt(cct, in, out); + } catch (std::exception& e) { + lderr(cct) << __func__ << " failed to encrypt signature block" << dendl; + return -1; + } - *psig = *reinterpret_cast<__le64*>(exp_buf); + struct enc { + __le64 a, b, c, d; + } *penc = reinterpret_cast(exp_buf); + *psig = penc->a ^ penc->b ^ penc->c ^ penc->d; + } ldout(cct, 10) << __func__ << " seq " << m->get_seq() << " front_crc_ = " << footer.front_crc