]> git.proxmox.com Git - ceph.git/blob - ceph/src/auth/cephx/CephxSessionHandler.cc
update sources to 12.2.7
[ceph.git] / ceph / src / auth / cephx / CephxSessionHandler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
7 *
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.
12 *
13 */
14
15 #include "CephxSessionHandler.h"
16 #include "CephxProtocol.h"
17
18 #include <errno.h>
19 #include <sstream>
20
21 #include "common/config.h"
22 #include "include/ceph_features.h"
23 #include "msg/Message.h"
24
25 #define dout_subsys ceph_subsys_auth
26
27 int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig)
28 {
29 const ceph_msg_header& header = m->get_header();
30 const ceph_msg_footer& footer = m->get_footer();
31
32 if (!HAVE_FEATURE(features, CEPHX_V2)) {
33 // legacy pre-mimic behavior for compatibility
34
35 // optimized signature calculation
36 // - avoid temporary allocated buffers from encode_encrypt[_enc_bl]
37 // - skip the leading 4 byte wrapper from encode_encrypt
38 struct {
39 __u8 v;
40 __le64 magic;
41 __le32 len;
42 __le32 header_crc;
43 __le32 front_crc;
44 __le32 middle_crc;
45 __le32 data_crc;
46 } __attribute__ ((packed)) sigblock = {
47 1, mswab(AUTH_ENC_MAGIC), mswab<uint32_t>(4*4),
48 mswab<uint32_t>(header.crc), mswab<uint32_t>(footer.front_crc),
49 mswab<uint32_t>(footer.middle_crc), mswab<uint32_t>(footer.data_crc)
50 };
51
52 bufferlist bl_plaintext;
53 bl_plaintext.append(buffer::create_static(sizeof(sigblock),
54 (char*)&sigblock));
55
56 bufferlist bl_ciphertext;
57 if (key.encrypt(cct, bl_plaintext, bl_ciphertext, NULL) < 0) {
58 lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
59 return -1;
60 }
61
62 bufferlist::iterator ci = bl_ciphertext.begin();
63 ::decode(*psig, ci);
64 } else {
65 // newer mimic+ signatures
66 struct {
67 __le32 header_crc;
68 __le32 front_crc;
69 __le32 front_len;
70 __le32 middle_crc;
71 __le32 middle_len;
72 __le32 data_crc;
73 __le32 data_len;
74 __le32 seq_lower_word;
75 } __attribute__ ((packed)) sigblock = {
76 mswab<uint32_t>(header.crc),
77 mswab<uint32_t>(footer.front_crc),
78 mswab<uint32_t>(header.front_len),
79 mswab<uint32_t>(footer.middle_crc),
80 mswab<uint32_t>(header.middle_len),
81 mswab<uint32_t>(footer.data_crc),
82 mswab<uint32_t>(header.data_len),
83 mswab<uint32_t>(header.seq)
84 };
85
86 bufferlist bl_plaintext;
87 bl_plaintext.append(buffer::create_static(sizeof(sigblock),
88 (char*)&sigblock));
89
90 bufferlist bl_ciphertext;
91 if (key.encrypt(cct, bl_plaintext, bl_ciphertext, NULL) < 0) {
92 lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
93 return -1;
94 }
95
96 struct enc {
97 __le64 a, b, c, d;
98 } *penc = reinterpret_cast<enc*>(bl_ciphertext.c_str());
99 *psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
100 }
101
102 ldout(cct, 10) << __func__ << " seq " << m->get_seq()
103 << " front_crc_ = " << footer.front_crc
104 << " middle_crc = " << footer.middle_crc
105 << " data_crc = " << footer.data_crc
106 << " sig = " << *psig
107 << dendl;
108 return 0;
109 }
110
111 int CephxSessionHandler::sign_message(Message *m)
112 {
113 // If runtime signing option is off, just return success without signing.
114 if (!cct->_conf->cephx_sign_messages) {
115 return 0;
116 }
117
118 uint64_t sig;
119 int r = _calc_signature(m, &sig);
120 if (r < 0)
121 return r;
122
123 ceph_msg_footer& f = m->get_footer();
124 f.sig = sig;
125 f.flags = (unsigned)f.flags | CEPH_MSG_FOOTER_SIGNED;
126 ldout(cct, 20) << "Putting signature in client message(seq # " << m->get_seq()
127 << "): sig = " << sig << dendl;
128 return 0;
129 }
130
131 int CephxSessionHandler::check_message_signature(Message *m)
132 {
133 // If runtime signing option is off, just return success without checking signature.
134 if (!cct->_conf->cephx_sign_messages) {
135 return 0;
136 }
137 if ((features & CEPH_FEATURE_MSG_AUTH) == 0) {
138 // it's fine, we didn't negotiate this feature.
139 return 0;
140 }
141
142 uint64_t sig;
143 int r = _calc_signature(m, &sig);
144 if (r < 0)
145 return r;
146
147 if (sig != m->get_footer().sig) {
148 // Should have been signed, but signature check failed. PLR
149 if (!(m->get_footer().flags & CEPH_MSG_FOOTER_SIGNED)) {
150 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl;
151 }
152 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Message signature does not match contents." << dendl;
153 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Signature on message:" << dendl;
154 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig: " << m->get_footer().sig << dendl;
155 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Locally calculated signature:" << dendl;
156 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig_check:" << sig << dendl;
157
158 // For the moment, printing an error message to the log and
159 // returning failure is sufficient. In the long term, we should
160 // probably have code parsing the log looking for this kind of
161 // security failure, particularly when there are large numbers of
162 // them, since the latter is a potential sign of an attack. PLR
163
164 ldout(cct, 0) << "Signature failed." << dendl;
165 return (SESSION_SIGNATURE_FAILURE);
166 }
167
168 return 0;
169 }
170