#define dout_subsys ceph_subsys_auth
-int CephxSessionHandler::sign_message(Message *m)
+int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig)
{
- // If runtime signing option is off, just return success without signing.
- if (!cct->_conf->cephx_sign_messages) {
- return 0;
- }
- bufferlist bl_plaintext, bl_encrypted;
- ceph_msg_header header = m->get_header();
- std::string error;
-
- ceph_msg_footer& en_footer = m->get_footer();
+ const ceph_msg_header& header = m->get_header();
+ const ceph_msg_footer& footer = m->get_footer();
+ bufferlist bl_plaintext;
::encode(header.crc, bl_plaintext);
- ::encode(en_footer.front_crc, bl_plaintext);
- ::encode(en_footer.middle_crc, bl_plaintext);
- ::encode(en_footer.data_crc, bl_plaintext);
-
- ldout(cct, 10) << "sign_message: seq # " << header.seq << " CRCs are: header " << header.crc
- << " front " << en_footer.front_crc << " middle " << en_footer.middle_crc
- << " data " << en_footer.data_crc << dendl;
+ ::encode(footer.front_crc, bl_plaintext);
+ ::encode(footer.middle_crc, bl_plaintext);
+ ::encode(footer.data_crc, bl_plaintext);
+ bufferlist bl_encrypted;
+ std::string error;
if (encode_encrypt(cct, bl_plaintext, key, bl_encrypted, error)) {
ldout(cct, 0) << "error encrypting message signature: " << error << dendl;
ldout(cct, 0) << "no signature put on message" << dendl;
return SESSION_SIGNATURE_FAILURE;
- }
+ }
bufferlist::iterator ci = bl_encrypted.begin();
// Skip the magic number up front. PLR
ci.advance(4);
- ::decode(en_footer.sig, ci);
+ ::decode(*psig, ci);
+ ldout(cct, 10) << __func__ << " seq " << m->get_seq()
+ << " front_crc_ = " << footer.front_crc
+ << " middle_crc = " << footer.middle_crc
+ << " data_crc = " << footer.data_crc
+ << " sig = " << *psig
+ << dendl;
+ return 0;
+}
- // There's potentially an issue with whether the encoding and decoding done here will work
- // properly when a big endian and little endian machine are talking. We think it's OK,
- // but it should be tested to be sure. PLR
+int CephxSessionHandler::sign_message(Message *m)
+{
+ // If runtime signing option is off, just return success without signing.
+ if (!cct->_conf->cephx_sign_messages) {
+ return 0;
+ }
- // Receiver won't trust this flag to decide if msg should have been signed. It's primarily
- // to debug problems where sender and receiver disagree on need to sign msg. PLR
- en_footer.flags = (unsigned)en_footer.flags | CEPH_MSG_FOOTER_SIGNED;
+ uint64_t sig;
+ int r = _calc_signature(m, &sig);
+ if (r < 0)
+ return r;
+
+ ceph_msg_footer& f = m->get_footer();
+ f.sig = sig;
+ f.flags = (unsigned)f.flags | CEPH_MSG_FOOTER_SIGNED;
messages_signed++;
- ldout(cct, 20) << "Putting signature in client message(seq # " << header.seq << "): sig = " << en_footer.sig << dendl;
+ ldout(cct, 20) << "Putting signature in client message(seq # " << m->get_seq()
+ << "): sig = " << sig << dendl;
return 0;
}
if (!cct->_conf->cephx_sign_messages) {
return 0;
}
-
- bufferlist bl_plaintext, bl_ciphertext;
- std::string sig_error;
- ceph_msg_header& header = m->get_header();
- ceph_msg_footer& footer = m->get_footer();
-
if ((features & CEPH_FEATURE_MSG_AUTH) == 0) {
// it's fine, we didn't negotiate this feature.
return 0;
}
- signatures_checked++;
+ uint64_t sig;
+ int r = _calc_signature(m, &sig);
+ if (r < 0)
+ return r;
- ldout(cct, 10) << "check_message_signature: seq # = " << m->get_seq() << " front_crc_ = " << footer.front_crc
- << " middle_crc = " << footer.middle_crc << " data_crc = " << footer.data_crc << dendl;
- ::encode(header.crc, bl_plaintext);
- ::encode(footer.front_crc, bl_plaintext);
- ::encode(footer.middle_crc, bl_plaintext);
- ::encode(footer.data_crc, bl_plaintext);
-
- // Encrypt the buffer containing the checksums to calculate the signature. PLR
- if (encode_encrypt(cct, bl_plaintext, key, bl_ciphertext, sig_error)) {
- ldout(cct, 0) << "error in encryption for checking message signature: " << sig_error << dendl;
- return (SESSION_SIGNATURE_FAILURE);
- }
-
- bufferlist::iterator ci = bl_ciphertext.begin();
- // Skip the magic number at the front. PLR
- ci.advance(4);
- uint64_t sig_check;
- ::decode(sig_check, ci);
-
- // There's potentially an issue with whether the encoding and decoding done here will work
- // properly when a big endian and little endian machine are talking. We think it's OK,
- // but it should be tested to be sure. PLR
+ signatures_checked++;
- if (sig_check != footer.sig) {
+ if (sig != m->get_footer().sig) {
// Should have been signed, but signature check failed. PLR
- if (!(footer.flags & CEPH_MSG_FOOTER_SIGNED)) {
- ldout(cct, 0) << "SIGN: MSG " << header.seq << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl;
+ if (!(m->get_footer().flags & CEPH_MSG_FOOTER_SIGNED)) {
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl;
}
- ldout(cct, 0) << "SIGN: MSG " << header.seq << " Message signature does not match contents." << dendl;
- ldout(cct, 0) << "SIGN: MSG " << header.seq << "Signature on message:" << dendl;
- ldout(cct, 0) << "SIGN: MSG " << header.seq << " sig: " << footer.sig << dendl;
- ldout(cct, 0) << "SIGN: MSG " << header.seq << "Locally calculated signature:" << dendl;
- ldout(cct, 0) << "SIGN: MSG " << header.seq << " sig_check:" << sig_check << dendl;
-
- // For the moment, printing an error message to the log and returning failure is sufficient.
- // In the long term, we should probably have code parsing the log looking for this kind
- // of security failure, particularly when there are large numbers of them, since the latter
- // is a potential sign of an attack. PLR
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Message signature does not match contents." << dendl;
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Signature on message:" << dendl;
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig: " << m->get_footer().sig << dendl;
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Locally calculated signature:" << dendl;
+ ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig_check:" << sig << dendl;
+
+ // For the moment, printing an error message to the log and
+ // returning failure is sufficient. In the long term, we should
+ // probably have code parsing the log looking for this kind of
+ // security failure, particularly when there are large numbers of
+ // them, since the latter is a potential sign of an attack. PLR
signatures_failed++;
ldout(cct, 0) << "Signature failed." << dendl;