X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fauth%2Fcephx%2FCephxSessionHandler.cc;fp=src%2Fceph%2Fsrc%2Fauth%2Fcephx%2FCephxSessionHandler.cc;h=5694a22c0766eac87103ce0b157391b70578f5a2;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/auth/cephx/CephxSessionHandler.cc b/src/ceph/src/auth/cephx/CephxSessionHandler.cc new file mode 100644 index 0000000..5694a22 --- /dev/null +++ b/src/ceph/src/auth/cephx/CephxSessionHandler.cc @@ -0,0 +1,128 @@ +// -*- 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) 2004-2009 Sage Weil + * + * 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 "CephxSessionHandler.h" +#include "CephxProtocol.h" + +#include +#include + +#include "common/config.h" +#include "include/ceph_features.h" +#include "msg/Message.h" + +#define dout_subsys ceph_subsys_auth + +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) + }; + bufferlist bl_plaintext; + bl_plaintext.append(buffer::create_static(sizeof(sigblock), (char*)&sigblock)); + + bufferlist bl_ciphertext; + if (key.encrypt(cct, bl_plaintext, bl_ciphertext, NULL) < 0) { + lderr(cct) << __func__ << " failed to encrypt signature block" << dendl; + return -1; + } + + bufferlist::iterator ci = bl_ciphertext.begin(); + ::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; +} + +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; + } + + 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; + ldout(cct, 20) << "Putting signature in client message(seq # " << m->get_seq() + << "): sig = " << sig << dendl; + return 0; +} + +int CephxSessionHandler::check_message_signature(Message *m) +{ + // If runtime signing option is off, just return success without checking signature. + if (!cct->_conf->cephx_sign_messages) { + return 0; + } + if ((features & CEPH_FEATURE_MSG_AUTH) == 0) { + // it's fine, we didn't negotiate this feature. + return 0; + } + + uint64_t sig; + int r = _calc_signature(m, &sig); + if (r < 0) + return r; + + if (sig != m->get_footer().sig) { + // Should have been signed, but signature check failed. PLR + 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 " << 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 + + ldout(cct, 0) << "Signature failed." << dendl; + return (SESSION_SIGNATURE_FAILURE); + } + + return 0; +} +