]> git.proxmox.com Git - ceph.git/blame - ceph/src/auth/cephx/CephxSessionHandler.cc
import ceph 14.2.5
[ceph.git] / ceph / src / auth / cephx / CephxSessionHandler.cc
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
7c673cae
FG
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
11fdf7f2 10 * License version 2.1, as published by the Free Software
7c673cae 11 * Foundation. See file COPYING.
11fdf7f2 12 *
7c673cae
FG
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"
11fdf7f2 24
7c673cae
FG
25#define dout_subsys ceph_subsys_auth
26
27int 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
28e407b8
AA
32 if (!HAVE_FEATURE(features, CEPHX_V2)) {
33 // legacy pre-mimic behavior for compatibility
7c673cae 34
28e407b8
AA
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;
eafe8130
TL
40 ceph_le64 magic;
41 ceph_le32 len;
42 ceph_le32 header_crc;
43 ceph_le32 front_crc;
44 ceph_le32 middle_crc;
45 ceph_le32 data_crc;
28e407b8 46 } __attribute__ ((packed)) sigblock = {
eafe8130
TL
47 1, init_le64(AUTH_ENC_MAGIC), init_le32(4*4),
48 init_le32(header.crc), init_le32(footer.front_crc),
49 init_le32(footer.middle_crc), init_le32(footer.data_crc)
28e407b8
AA
50 };
51
11fdf7f2
TL
52 char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))];
53
54 try {
55 const CryptoKey::in_slice_t in {
56 sizeof(sigblock),
57 reinterpret_cast<const unsigned char*>(&sigblock)
58 };
59 const CryptoKey::out_slice_t out {
60 sizeof(exp_buf),
61 reinterpret_cast<unsigned char*>(&exp_buf)
62 };
63 key.encrypt(cct, in, out);
64 } catch (std::exception& e) {
28e407b8
AA
65 lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
66 return -1;
67 }
68
eafe8130 69 *psig = *reinterpret_cast<ceph_le64*>(exp_buf);
28e407b8
AA
70 } else {
71 // newer mimic+ signatures
72 struct {
eafe8130
TL
73 ceph_le32 header_crc;
74 ceph_le32 front_crc;
75 ceph_le32 front_len;
76 ceph_le32 middle_crc;
77 ceph_le32 middle_len;
78 ceph_le32 data_crc;
79 ceph_le32 data_len;
80 ceph_le32 seq_lower_word;
28e407b8 81 } __attribute__ ((packed)) sigblock = {
eafe8130
TL
82 init_le32(header.crc),
83 init_le32(footer.front_crc),
84 init_le32(header.front_len),
85 init_le32(footer.middle_crc),
86 init_le32(header.middle_len),
87 init_le32(footer.data_crc),
88 init_le32(header.data_len),
89 init_le32(header.seq)
28e407b8 90 };
7c673cae 91
11fdf7f2
TL
92 char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))];
93
94 try {
95 const CryptoKey::in_slice_t in {
96 sizeof(sigblock),
97 reinterpret_cast<const unsigned char*>(&sigblock)
98 };
99 const CryptoKey::out_slice_t out {
100 sizeof(exp_buf),
101 reinterpret_cast<unsigned char*>(&exp_buf)
102 };
103 key.encrypt(cct, in, out);
104 } catch (std::exception& e) {
28e407b8
AA
105 lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
106 return -1;
107 }
108
109 struct enc {
eafe8130 110 ceph_le64 a, b, c, d;
11fdf7f2 111 } *penc = reinterpret_cast<enc*>(exp_buf);
28e407b8
AA
112 *psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
113 }
7c673cae
FG
114
115 ldout(cct, 10) << __func__ << " seq " << m->get_seq()
116 << " front_crc_ = " << footer.front_crc
117 << " middle_crc = " << footer.middle_crc
118 << " data_crc = " << footer.data_crc
119 << " sig = " << *psig
120 << dendl;
121 return 0;
122}
123
124int CephxSessionHandler::sign_message(Message *m)
125{
126 // If runtime signing option is off, just return success without signing.
127 if (!cct->_conf->cephx_sign_messages) {
128 return 0;
129 }
130
131 uint64_t sig;
132 int r = _calc_signature(m, &sig);
133 if (r < 0)
134 return r;
135
136 ceph_msg_footer& f = m->get_footer();
137 f.sig = sig;
138 f.flags = (unsigned)f.flags | CEPH_MSG_FOOTER_SIGNED;
7c673cae
FG
139 ldout(cct, 20) << "Putting signature in client message(seq # " << m->get_seq()
140 << "): sig = " << sig << dendl;
141 return 0;
142}
143
144int CephxSessionHandler::check_message_signature(Message *m)
145{
146 // If runtime signing option is off, just return success without checking signature.
147 if (!cct->_conf->cephx_sign_messages) {
148 return 0;
149 }
150 if ((features & CEPH_FEATURE_MSG_AUTH) == 0) {
151 // it's fine, we didn't negotiate this feature.
152 return 0;
153 }
154
155 uint64_t sig;
156 int r = _calc_signature(m, &sig);
157 if (r < 0)
158 return r;
159
7c673cae
FG
160 if (sig != m->get_footer().sig) {
161 // Should have been signed, but signature check failed. PLR
162 if (!(m->get_footer().flags & CEPH_MSG_FOOTER_SIGNED)) {
163 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Sender did not set CEPH_MSG_FOOTER_SIGNED." << dendl;
164 }
165 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " Message signature does not match contents." << dendl;
166 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Signature on message:" << dendl;
167 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig: " << m->get_footer().sig << dendl;
168 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << "Locally calculated signature:" << dendl;
169 ldout(cct, 0) << "SIGN: MSG " << m->get_seq() << " sig_check:" << sig << dendl;
170
171 // For the moment, printing an error message to the log and
172 // returning failure is sufficient. In the long term, we should
173 // probably have code parsing the log looking for this kind of
174 // security failure, particularly when there are large numbers of
175 // them, since the latter is a potential sign of an attack. PLR
176
7c673cae
FG
177 ldout(cct, 0) << "Signature failed." << dendl;
178 return (SESSION_SIGNATURE_FAILURE);
179 }
180
7c673cae
FG
181 return 0;
182}