1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "CephxSessionHandler.h"
16 #include "CephxProtocol.h"
21 #include "common/config.h"
22 #include "include/ceph_features.h"
23 #include "msg/Message.h"
25 #define dout_subsys ceph_subsys_auth
27 int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig)
29 const ceph_msg_header& header = m->get_header();
30 const ceph_msg_footer& footer = m->get_footer();
32 // optimized signature calculation
33 // - avoid temporary allocated buffers from encode_encrypt[_enc_bl]
34 // - skip the leading 4 byte wrapper from encode_encrypt
43 } __attribute__ ((packed)) sigblock = {
44 1, mswab(AUTH_ENC_MAGIC), mswab<uint32_t>(4*4),
45 mswab<uint32_t>(header.crc), mswab<uint32_t>(footer.front_crc),
46 mswab<uint32_t>(footer.middle_crc), mswab<uint32_t>(footer.data_crc)
48 bufferlist bl_plaintext;
49 bl_plaintext.append(buffer::create_static(sizeof(sigblock), (char*)&sigblock));
51 bufferlist bl_ciphertext;
52 if (key.encrypt(cct, bl_plaintext, bl_ciphertext, NULL) < 0) {
53 lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
57 bufferlist::iterator ci = bl_ciphertext.begin();
60 ldout(cct, 10) << __func__ << " seq " << m->get_seq()
61 << " front_crc_ = " << footer.front_crc
62 << " middle_crc = " << footer.middle_crc
63 << " data_crc = " << footer.data_crc
69 int CephxSessionHandler::sign_message(Message *m)
71 // If runtime signing option is off, just return success without signing.
72 if (!cct->_conf->cephx_sign_messages) {
77 int r = _calc_signature(m, &sig);
81 ceph_msg_footer& f = m->get_footer();
83 f.flags = (unsigned)f.flags | CEPH_MSG_FOOTER_SIGNED;
84 ldout(cct, 20) << "Putting signature in client message(seq # " << m->get_seq()
85 << "): sig = " << sig << dendl;
89 int CephxSessionHandler::check_message_signature(Message *m)
91 // If runtime signing option is off, just return success without checking signature.
92 if (!cct->_conf->cephx_sign_messages) {
95 if ((features & CEPH_FEATURE_MSG_AUTH) == 0) {
96 // it's fine, we didn't negotiate this feature.
101 int r = _calc_signature(m, &sig);
105 if (sig != m->get_footer().sig) {
106 // Should have been signed, but signature check failed. PLR
107 if (!(m->get_footer().flags & CEPH_MSG_FOOTER_SIGNED)) {
108 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl;
110 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Message signature does not match contents." << dendl;
111 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Signature on message:" << dendl;
112 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig: " << m->get_footer().sig << dendl;
113 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Locally calculated signature:" << dendl;
114 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig_check:" << sig << dendl;
116 // For the moment, printing an error message to the log and
117 // returning failure is sufficient. In the long term, we should
118 // probably have code parsing the log looking for this kind of
119 // security failure, particularly when there are large numbers of
120 // them, since the latter is a potential sign of an attack. PLR
122 ldout(cct, 0) << "Signature failed." << dendl;
123 return (SESSION_SIGNATURE_FAILURE);