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
;
85 ldout(cct
, 20) << "Putting signature in client message(seq # " << m
->get_seq()
86 << "): sig = " << sig
<< dendl
;
90 int CephxSessionHandler::check_message_signature(Message
*m
)
92 // If runtime signing option is off, just return success without checking signature.
93 if (!cct
->_conf
->cephx_sign_messages
) {
96 if ((features
& CEPH_FEATURE_MSG_AUTH
) == 0) {
97 // it's fine, we didn't negotiate this feature.
102 int r
= _calc_signature(m
, &sig
);
106 signatures_checked
++;
108 if (sig
!= m
->get_footer().sig
) {
109 // Should have been signed, but signature check failed. PLR
110 if (!(m
->get_footer().flags
& CEPH_MSG_FOOTER_SIGNED
)) {
111 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl
;
113 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << " Message signature does not match contents." << dendl
;
114 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << "Signature on message:" << dendl
;
115 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << " sig: " << m
->get_footer().sig
<< dendl
;
116 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << "Locally calculated signature:" << dendl
;
117 ldout(cct
, 0) << "SIGN: MSG " << m
->get_seq() << " sig_check:" << sig
<< dendl
;
119 // For the moment, printing an error message to the log and
120 // returning failure is sufficient. In the long term, we should
121 // probably have code parsing the log looking for this kind of
122 // security failure, particularly when there are large numbers of
123 // them, since the latter is a potential sign of an attack. PLR
126 ldout(cct
, 0) << "Signature failed." << dendl
;
127 return (SESSION_SIGNATURE_FAILURE
);
130 // If we get here, the signature checked. PLR
131 signatures_matched
++;