libcli/smb: change smb_signing to skip the NBT_HEADER_SIZE internally
[samba.git] / libcli / smb / smb_signing.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB Signing Code
4    Copyright (C) Jeremy Allison 2003.
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6    Copyright (C) Stefan Metzmacher 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "../lib/crypto/md5.h"
24 #include "smb_common.h"
25 #include "smb_signing.h"
26
27 /* Used by the SMB signing functions. */
28
29 struct smb_signing_state {
30         /* is signing localy allowed */
31         bool allowed;
32
33         /* is signing localy desired */
34         bool desired;
35
36         /* is signing localy mandatory */
37         bool mandatory;
38
39         /* is signing negotiated by the peer */
40         bool negotiated;
41
42         bool active; /* Have I ever seen a validly signed packet? */
43
44         /* mac_key.length > 0 means signing is started */
45         DATA_BLOB mac_key;
46
47         /* the next expected seqnum */
48         uint32_t seqnum;
49
50         TALLOC_CTX *mem_ctx;
51         void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
52         void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
53 };
54
55 static void smb_signing_reset_info(struct smb_signing_state *si)
56 {
57         si->active = false;
58         si->seqnum = 0;
59
60         if (si->free_fn) {
61                 si->free_fn(si->mem_ctx, si->mac_key.data);
62         } else {
63                 talloc_free(si->mac_key.data);
64         }
65         si->mac_key.data = NULL;
66         si->mac_key.length = 0;
67 }
68
69 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
70                                               bool allowed,
71                                               bool desired,
72                                               bool mandatory,
73                                               void *(*alloc_fn)(TALLOC_CTX *, size_t),
74                                               void (*free_fn)(TALLOC_CTX *, void *))
75 {
76         struct smb_signing_state *si;
77
78         if (alloc_fn) {
79                 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
80                 if (p == NULL) {
81                         return NULL;
82                 }
83                 memset(p, 0, sizeof(struct smb_signing_state));
84                 si = (struct smb_signing_state *)p;
85                 si->mem_ctx = mem_ctx;
86                 si->alloc_fn = alloc_fn;
87                 si->free_fn = free_fn;
88         } else {
89                 si = talloc_zero(mem_ctx, struct smb_signing_state);
90                 if (si == NULL) {
91                         return NULL;
92                 }
93         }
94
95         if (mandatory) {
96                 desired = true;
97         }
98
99         if (desired) {
100                 allowed = true;
101         }
102
103         si->allowed = allowed;
104         si->desired = desired;
105         si->mandatory = mandatory;
106
107         return si;
108 }
109
110 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
111                                            bool allowed,
112                                            bool desired,
113                                            bool mandatory)
114 {
115         return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
116                                    NULL, NULL);
117 }
118
119 static bool smb_signing_good(struct smb_signing_state *si,
120                              bool good, uint32_t seq)
121 {
122         if (good) {
123                 if (!si->active) {
124                         si->active = true;
125                 }
126                 return true;
127         }
128
129         if (!si->mandatory && !si->active) {
130                 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
131                 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n"
132                           "isn't sending correct signatures. Turning off.\n"));
133                 smb_signing_reset_info(si);
134                 return true;
135         }
136
137         /* Mandatory signing or bad packet after signing started - fail and disconnect. */
138         DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
139         return false;
140 }
141
142 static void smb_signing_md5(const DATA_BLOB *mac_key,
143                             const uint8_t *hdr, size_t len,
144                             uint32_t seq_number,
145                             uint8_t calc_md5_mac[16])
146 {
147         const size_t offset_end_of_sig = (HDR_SS_FIELD + 8);
148         uint8_t sequence_buf[8];
149         struct MD5Context md5_ctx;
150
151         /*
152          * Firstly put the sequence number into the first 4 bytes.
153          * and zero out the next 4 bytes.
154          *
155          * We do this here, to avoid modifying the packet.
156          */
157
158         DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number ));
159
160         SIVAL(sequence_buf, 0, seq_number);
161         SIVAL(sequence_buf, 4, 0);
162
163         /* Calculate the 16 byte MAC - but don't alter the data in the
164            incoming packet.
165
166            This makes for a bit of fussing about, but it's not too bad.
167         */
168         MD5Init(&md5_ctx);
169
170         /* intialise with the key */
171         MD5Update(&md5_ctx, mac_key->data, mac_key->length);
172
173         /* copy in the first bit of the SMB header */
174         MD5Update(&md5_ctx, hdr, HDR_SS_FIELD);
175
176         /* copy in the sequence number, instead of the signature */
177         MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
178
179         /* copy in the rest of the packet in, skipping the signature */
180         MD5Update(&md5_ctx, hdr + offset_end_of_sig,
181                   len - (offset_end_of_sig));
182
183         /* calculate the MD5 sig */
184         MD5Final(calc_md5_mac, &md5_ctx);
185 }
186
187 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
188 {
189         uint32_t seqnum;
190
191         if (si->mac_key.length == 0) {
192                 return 0;
193         }
194
195         seqnum = si->seqnum;
196         if (oneway) {
197                 si->seqnum += 1;
198         } else {
199                 si->seqnum += 2;
200         }
201
202         return seqnum;
203 }
204
205 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
206 {
207         if (si->mac_key.length == 0) {
208                 return;
209         }
210
211         if (oneway) {
212                 si->seqnum -= 1;
213         } else {
214                 si->seqnum -= 2;
215         }
216 }
217
218 void smb_signing_sign_pdu(struct smb_signing_state *si,
219                           uint8_t *outbuf, uint32_t seqnum)
220 {
221         uint8_t calc_md5_mac[16];
222         uint8_t com;
223         uint8_t flags;
224         uint8_t *outhdr = outbuf + NBT_HDR_SIZE;
225         size_t len = smb_len_nbt(outbuf);
226
227         if (si->mac_key.length == 0) {
228                 if (!si->negotiated) {
229                         return;
230                 }
231         }
232
233         /* JRA Paranioa test - we should be able to get rid of this... */
234         if (len < (HDR_SS_FIELD + 8)) {
235                 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
236                          "Can't check signature on short packet! smb_len = %u\n",
237                          (unsigned)len));
238                 abort();
239         }
240
241         com = SVAL(outhdr, HDR_COM);
242         flags = SVAL(outhdr, HDR_FLG);
243
244         if (!(flags & FLAG_REPLY)) {
245                 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
246                 /*
247                  * If this is a request, specify what is
248                  * supported or required by the client
249                  */
250                 if (si->negotiated && si->desired) {
251                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
252                 }
253                 if (si->negotiated && si->mandatory) {
254                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
255                 }
256                 SSVAL(outhdr, HDR_FLG2, flags2);
257         }
258
259         if (si->mac_key.length == 0) {
260                 /* I wonder what BSRSPYL stands for - but this is what MS
261                    actually sends! */
262                 if (com == SMBsesssetupX) {
263                         memcpy(calc_md5_mac, "BSRSPYL ", 8);
264                 } else {
265                         memset(calc_md5_mac, 0, 8);
266                 }
267         } else {
268                 smb_signing_md5(&si->mac_key, outhdr, len,
269                                 seqnum, calc_md5_mac);
270         }
271
272         DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
273         dump_data(10, calc_md5_mac, 8);
274
275         memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
276
277 /*      outhdr[HDR_SS_FIELD+2]=0;
278         Uncomment this to test if the remote server actually verifies signatures...*/
279 }
280
281 bool smb_signing_check_pdu(struct smb_signing_state *si,
282                            const uint8_t *inbuf, uint32_t seqnum)
283 {
284         bool good;
285         uint8_t calc_md5_mac[16];
286         const uint8_t *reply_sent_mac;
287         const uint8_t *inhdr = inbuf + NBT_HDR_SIZE;
288         size_t len = smb_len_nbt(inbuf);
289
290         if (si->mac_key.length == 0) {
291                 return true;
292         }
293
294         if (len < (HDR_SS_FIELD + 8)) {
295                 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
296                          "on short packet! smb_len = %u\n",
297                          (unsigned)len));
298                 return false;
299         }
300
301         smb_signing_md5(&si->mac_key, inhdr, len,
302                         seqnum, calc_md5_mac);
303
304         reply_sent_mac = &inhdr[HDR_SS_FIELD];
305         good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
306
307         if (!good) {
308                 int i;
309                 const int sign_range = 5;
310
311                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
312                 dump_data(5, calc_md5_mac, 8);
313
314                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
315                 dump_data(5, reply_sent_mac, 8);
316
317                 for (i = -sign_range; i < sign_range; i++) {
318                         smb_signing_md5(&si->mac_key, inhdr, len,
319                                         seqnum+i, calc_md5_mac);
320                         if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
321                                 DEBUG(0,("smb_signing_check_pdu: "
322                                          "out of seq. seq num %u matches. "
323                                          "We were expecting seq %u\n",
324                                          (unsigned int)seqnum+i,
325                                          (unsigned int)seqnum));
326                                 break;
327                         }
328                 }
329         } else {
330                 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
331                            "got good SMB signature of\n",
332                            (unsigned int)seqnum));
333                 dump_data(10, reply_sent_mac, 8);
334         }
335
336         return smb_signing_good(si, good, seqnum);
337 }
338
339 bool smb_signing_activate(struct smb_signing_state *si,
340                           const DATA_BLOB user_session_key,
341                           const DATA_BLOB response)
342 {
343         size_t len;
344         off_t ofs;
345
346         if (!user_session_key.length) {
347                 return false;
348         }
349
350         if (!si->negotiated) {
351                 return false;
352         }
353
354         if (si->active) {
355                 return false;
356         }
357
358         if (si->mac_key.length > 0) {
359                 return false;
360         }
361
362         smb_signing_reset_info(si);
363
364         len = response.length + user_session_key.length;
365         if (si->alloc_fn) {
366                 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
367                 if (si->mac_key.data == NULL) {
368                         return false;
369                 }
370         } else {
371                 si->mac_key.data = (uint8_t *)talloc_size(si, len);
372                 if (si->mac_key.data == NULL) {
373                         return false;
374                 }
375         }
376         si->mac_key.length = len;
377
378         ofs = 0;
379         memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
380
381         DEBUG(10, ("smb_signing_activate: user_session_key\n"));
382         dump_data(10, user_session_key.data, user_session_key.length);
383
384         if (response.length) {
385                 ofs = user_session_key.length;
386                 memcpy(&si->mac_key.data[ofs], response.data, response.length);
387                 DEBUG(10, ("smb_signing_activate: response_data\n"));
388                 dump_data(10, response.data, response.length);
389         } else {
390                 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
391         }
392
393         dump_data_pw("smb_signing_activate: mac key is:\n",
394                      si->mac_key.data, si->mac_key.length);
395
396         /* Initialise the sequence number */
397         si->seqnum = 2;
398
399         return true;
400 }
401
402 bool smb_signing_is_active(struct smb_signing_state *si)
403 {
404         return si->active;
405 }
406
407 bool smb_signing_is_allowed(struct smb_signing_state *si)
408 {
409         return si->allowed;
410 }
411
412 bool smb_signing_is_mandatory(struct smb_signing_state *si)
413 {
414         return si->mandatory;
415 }
416
417 bool smb_signing_set_negotiated(struct smb_signing_state *si,
418                                 bool allowed, bool mandatory)
419 {
420         if (si->active) {
421                 return true;
422         }
423
424         if (!si->allowed && mandatory) {
425                 return false;
426         }
427
428         if (si->mandatory && !allowed) {
429                 return false;
430         }
431
432         if (si->mandatory) {
433                 si->negotiated = true;
434                 return true;
435         }
436
437         if (mandatory) {
438                 si->negotiated = true;
439                 return true;
440         }
441
442         if (!si->desired) {
443                 si->negotiated = false;
444                 return true;
445         }
446
447         if (si->desired && allowed) {
448                 si->negotiated = true;
449                 return true;
450         }
451
452         si->negotiated = false;
453         return true;
454 }
455
456 bool smb_signing_is_negotiated(struct smb_signing_state *si)
457 {
458         return si->negotiated;
459 }