Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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   // optimized signature calculation
33   // - avoid temporary allocated buffers from encode_encrypt[_enc_bl]
34   // - skip the leading 4 byte wrapper from encode_encrypt
35   struct {
36     __u8 v;
37     __le64 magic;
38     __le32 len;
39     __le32 header_crc;
40     __le32 front_crc;
41     __le32 middle_crc;
42     __le32 data_crc;
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)
47   };
48   bufferlist bl_plaintext;
49   bl_plaintext.append(buffer::create_static(sizeof(sigblock), (char*)&sigblock));
50
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;
54     return -1;
55   }
56
57   bufferlist::iterator ci = bl_ciphertext.begin();
58   ::decode(*psig, ci);
59
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
64                  << " sig = " << *psig
65                  << dendl;
66   return 0;
67 }
68
69 int CephxSessionHandler::sign_message(Message *m)
70 {
71   // If runtime signing option is off, just return success without signing.
72   if (!cct->_conf->cephx_sign_messages) {
73     return 0;
74   }
75
76   uint64_t sig;
77   int r = _calc_signature(m, &sig);
78   if (r < 0)
79     return r;
80
81   ceph_msg_footer& f = m->get_footer();
82   f.sig = sig;
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;
86   return 0;
87 }
88
89 int CephxSessionHandler::check_message_signature(Message *m)
90 {
91   // If runtime signing option is off, just return success without checking signature.
92   if (!cct->_conf->cephx_sign_messages) {
93     return 0;
94   }
95   if ((features & CEPH_FEATURE_MSG_AUTH) == 0) {
96     // it's fine, we didn't negotiate this feature.
97     return 0;
98   }
99
100   uint64_t sig;
101   int r = _calc_signature(m, &sig);
102   if (r < 0)
103     return r;
104
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;
109     }
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;
115
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
121
122     ldout(cct, 0) << "Signature failed." << dendl;
123     return (SESSION_SIGNATURE_FAILURE);
124   }
125
126   return 0;
127 }
128