34e6dc0fe58d51b7d7c05c85b48be453d84ad62b
[garming/samba-autobuild/.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 "smb_common.h"
24 #include "smb_signing.h"
25
26 #include <gnutls/gnutls.h>
27 #include <gnutls/crypto.h>
28
29 /* Used by the SMB signing functions. */
30
31 struct smb_signing_state {
32         /* is signing localy allowed */
33         bool allowed;
34
35         /* is signing localy desired */
36         bool desired;
37
38         /* is signing localy mandatory */
39         bool mandatory;
40
41         /* is signing negotiated by the peer */
42         bool negotiated;
43
44         bool active; /* Have I ever seen a validly signed packet? */
45
46         /* mac_key.length > 0 means signing is started */
47         DATA_BLOB mac_key;
48
49         /* the next expected seqnum */
50         uint32_t seqnum;
51
52         TALLOC_CTX *mem_ctx;
53         void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
54         void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
55 };
56
57 static void smb_signing_reset_info(struct smb_signing_state *si)
58 {
59         si->active = false;
60         si->seqnum = 0;
61
62         if (si->free_fn) {
63                 si->free_fn(si->mem_ctx, si->mac_key.data);
64         } else {
65                 talloc_free(si->mac_key.data);
66         }
67         si->mac_key.data = NULL;
68         si->mac_key.length = 0;
69 }
70
71 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
72                                               bool allowed,
73                                               bool desired,
74                                               bool mandatory,
75                                               void *(*alloc_fn)(TALLOC_CTX *, size_t),
76                                               void (*free_fn)(TALLOC_CTX *, void *))
77 {
78         struct smb_signing_state *si;
79
80         if (alloc_fn) {
81                 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
82                 if (p == NULL) {
83                         return NULL;
84                 }
85                 memset(p, 0, sizeof(struct smb_signing_state));
86                 si = (struct smb_signing_state *)p;
87                 si->mem_ctx = mem_ctx;
88                 si->alloc_fn = alloc_fn;
89                 si->free_fn = free_fn;
90         } else {
91                 si = talloc_zero(mem_ctx, struct smb_signing_state);
92                 if (si == NULL) {
93                         return NULL;
94                 }
95         }
96
97         if (mandatory) {
98                 desired = true;
99         }
100
101         if (desired) {
102                 allowed = true;
103         }
104
105         si->allowed = allowed;
106         si->desired = desired;
107         si->mandatory = mandatory;
108
109         return si;
110 }
111
112 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
113                                            bool allowed,
114                                            bool desired,
115                                            bool mandatory)
116 {
117         return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
118                                    NULL, NULL);
119 }
120
121 static bool smb_signing_good(struct smb_signing_state *si,
122                              bool good, uint32_t seq)
123 {
124         if (good) {
125                 if (!si->active) {
126                         si->active = true;
127                 }
128                 return true;
129         }
130
131         if (!si->mandatory && !si->active) {
132                 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
133                 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n"
134                           "isn't sending correct signatures. Turning off.\n"));
135                 smb_signing_reset_info(si);
136                 return true;
137         }
138
139         /* Mandatory signing or bad packet after signing started - fail and disconnect. */
140         DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
141         return false;
142 }
143
144 static NTSTATUS smb_signing_md5(const DATA_BLOB *mac_key,
145                                 const uint8_t *hdr, size_t len,
146                                 uint32_t seq_number,
147                                 uint8_t calc_md5_mac[16])
148 {
149         const size_t offset_end_of_sig = (HDR_SS_FIELD + 8);
150         uint8_t sequence_buf[8];
151         gnutls_hash_hd_t hash_hnd = NULL;
152         int rc;
153
154         /*
155          * Firstly put the sequence number into the first 4 bytes.
156          * and zero out the next 4 bytes.
157          *
158          * We do this here, to avoid modifying the packet.
159          */
160
161         DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number ));
162
163         SIVAL(sequence_buf, 0, seq_number);
164         SIVAL(sequence_buf, 4, 0);
165
166         /*
167          * Calculate the 16 byte MAC - but don't alter the data in the
168          * incoming packet.
169          *
170          * This makes for a bit of fussing about, but it's not too bad.
171          */
172         rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
173         if (rc < 0) {
174                 if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
175                         return NT_STATUS_HASH_NOT_SUPPORTED;
176                 }
177                 return NT_STATUS_NO_MEMORY;
178         }
179         /* Initialise with the key. */
180         rc = gnutls_hash(hash_hnd, mac_key->data, mac_key->length);
181         if (rc < 0) {
182                 gnutls_hash_deinit(hash_hnd, NULL);
183                 return NT_STATUS_INTERNAL_ERROR;
184         }
185         /* Copy in the first bit of the SMB header. */
186         rc = gnutls_hash(hash_hnd, hdr, HDR_SS_FIELD);
187         if (rc < 0) {
188                 gnutls_hash_deinit(hash_hnd, NULL);
189                 return NT_STATUS_INTERNAL_ERROR;
190         }
191         /* Copy in the sequence number, instead of the signature. */
192         rc = gnutls_hash(hash_hnd, sequence_buf, sizeof(sequence_buf));
193         if (rc < 0) {
194                 gnutls_hash_deinit(hash_hnd, NULL);
195                 return NT_STATUS_INTERNAL_ERROR;
196         }
197         /* Copy in the rest of the packet in, skipping the signature. */
198         rc = gnutls_hash(hash_hnd, hdr + offset_end_of_sig, len - offset_end_of_sig);
199         if (rc < 0) {
200                 gnutls_hash_deinit(hash_hnd, NULL);
201                 return NT_STATUS_INTERNAL_ERROR;
202         }
203
204         gnutls_hash_deinit(hash_hnd, calc_md5_mac);
205
206         return NT_STATUS_OK;
207 }
208
209 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
210 {
211         uint32_t seqnum;
212
213         if (si->mac_key.length == 0) {
214                 return 0;
215         }
216
217         seqnum = si->seqnum;
218         if (oneway) {
219                 si->seqnum += 1;
220         } else {
221                 si->seqnum += 2;
222         }
223
224         return seqnum;
225 }
226
227 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
228 {
229         if (si->mac_key.length == 0) {
230                 return;
231         }
232
233         if (oneway) {
234                 si->seqnum -= 1;
235         } else {
236                 si->seqnum -= 2;
237         }
238 }
239
240 void smb_signing_sign_pdu(struct smb_signing_state *si,
241                           uint8_t *outhdr, size_t len,
242                           uint32_t seqnum)
243 {
244         uint8_t calc_md5_mac[16];
245         uint8_t com;
246         uint8_t flags;
247
248         if (si->mac_key.length == 0) {
249                 if (!si->negotiated) {
250                         return;
251                 }
252         }
253
254         /* JRA Paranioa test - we should be able to get rid of this... */
255         if (len < (HDR_SS_FIELD + 8)) {
256                 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
257                          "Can't check signature on short packet! smb_len = %u\n",
258                          (unsigned)len));
259                 abort();
260         }
261
262         com = SVAL(outhdr, HDR_COM);
263         flags = SVAL(outhdr, HDR_FLG);
264
265         if (!(flags & FLAG_REPLY)) {
266                 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
267                 /*
268                  * If this is a request, specify what is
269                  * supported or required by the client
270                  */
271                 if (si->negotiated && si->desired) {
272                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
273                 }
274                 if (si->negotiated && si->mandatory) {
275                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
276                 }
277                 SSVAL(outhdr, HDR_FLG2, flags2);
278         }
279
280         if (si->mac_key.length == 0) {
281                 /* I wonder what BSRSPYL stands for - but this is what MS
282                    actually sends! */
283                 if (com == SMBsesssetupX) {
284                         memcpy(calc_md5_mac, "BSRSPYL ", 8);
285                 } else {
286                         memset(calc_md5_mac, 0, 8);
287                 }
288         } else {
289                 NTSTATUS status;
290
291                 status = smb_signing_md5(&si->mac_key,
292                                          outhdr,
293                                          len,
294                                          seqnum,
295                                          calc_md5_mac);
296                 if (!NT_STATUS_IS_OK(status)) {
297                         return;
298                 }
299         }
300
301         DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
302         dump_data(10, calc_md5_mac, 8);
303
304         memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
305
306 /*      outhdr[HDR_SS_FIELD+2]=0;
307         Uncomment this to test if the remote server actually verifies signatures...*/
308 }
309
310 bool smb_signing_check_pdu(struct smb_signing_state *si,
311                            const uint8_t *inhdr, size_t len,
312                            uint32_t seqnum)
313 {
314         bool good;
315         uint8_t calc_md5_mac[16];
316         const uint8_t *reply_sent_mac;
317
318         if (si->mac_key.length == 0) {
319                 return true;
320         }
321
322         if (len < (HDR_SS_FIELD + 8)) {
323                 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
324                          "on short packet! smb_len = %u\n",
325                          (unsigned)len));
326                 return false;
327         }
328
329         smb_signing_md5(&si->mac_key, inhdr, len,
330                         seqnum, calc_md5_mac);
331
332         reply_sent_mac = &inhdr[HDR_SS_FIELD];
333         good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
334
335         if (!good) {
336                 int i;
337                 const int sign_range = 5;
338
339                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
340                 dump_data(5, calc_md5_mac, 8);
341
342                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
343                 dump_data(5, reply_sent_mac, 8);
344
345                 for (i = -sign_range; i < sign_range; i++) {
346                         smb_signing_md5(&si->mac_key, inhdr, len,
347                                         seqnum+i, calc_md5_mac);
348                         if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
349                                 DEBUG(0,("smb_signing_check_pdu: "
350                                          "out of seq. seq num %u matches. "
351                                          "We were expecting seq %u\n",
352                                          (unsigned int)seqnum+i,
353                                          (unsigned int)seqnum));
354                                 break;
355                         }
356                 }
357         } else {
358                 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
359                            "got good SMB signature of\n",
360                            (unsigned int)seqnum));
361                 dump_data(10, reply_sent_mac, 8);
362         }
363
364         return smb_signing_good(si, good, seqnum);
365 }
366
367 bool smb_signing_activate(struct smb_signing_state *si,
368                           const DATA_BLOB user_session_key,
369                           const DATA_BLOB response)
370 {
371         size_t len;
372         off_t ofs;
373
374         if (!user_session_key.length) {
375                 return false;
376         }
377
378         if (!si->negotiated) {
379                 return false;
380         }
381
382         if (si->active) {
383                 return false;
384         }
385
386         if (si->mac_key.length > 0) {
387                 return false;
388         }
389
390         smb_signing_reset_info(si);
391
392         len = response.length + user_session_key.length;
393         if (si->alloc_fn) {
394                 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
395                 if (si->mac_key.data == NULL) {
396                         return false;
397                 }
398         } else {
399                 si->mac_key.data = (uint8_t *)talloc_size(si, len);
400                 if (si->mac_key.data == NULL) {
401                         return false;
402                 }
403         }
404         si->mac_key.length = len;
405
406         ofs = 0;
407         memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
408
409         DEBUG(10, ("smb_signing_activate: user_session_key\n"));
410         dump_data(10, user_session_key.data, user_session_key.length);
411
412         if (response.length) {
413                 ofs = user_session_key.length;
414                 memcpy(&si->mac_key.data[ofs], response.data, response.length);
415                 DEBUG(10, ("smb_signing_activate: response_data\n"));
416                 dump_data(10, response.data, response.length);
417         } else {
418                 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
419         }
420
421         dump_data_pw("smb_signing_activate: mac key is:\n",
422                      si->mac_key.data, si->mac_key.length);
423
424         /* Initialise the sequence number */
425         si->seqnum = 2;
426
427         return true;
428 }
429
430 bool smb_signing_is_active(struct smb_signing_state *si)
431 {
432         return si->active;
433 }
434
435 bool smb_signing_is_allowed(struct smb_signing_state *si)
436 {
437         return si->allowed;
438 }
439
440 bool smb_signing_is_desired(struct smb_signing_state *si)
441 {
442         return si->desired;
443 }
444
445 bool smb_signing_is_mandatory(struct smb_signing_state *si)
446 {
447         return si->mandatory;
448 }
449
450 bool smb_signing_set_negotiated(struct smb_signing_state *si,
451                                 bool allowed, bool mandatory)
452 {
453         if (si->active) {
454                 return true;
455         }
456
457         if (mandatory) {
458                 allowed = true;
459         }
460
461         if (!si->allowed && mandatory) {
462                 return false;
463         }
464
465         if (si->mandatory && !allowed) {
466                 return false;
467         }
468
469         if (si->mandatory) {
470                 si->negotiated = true;
471                 return true;
472         }
473
474         if (mandatory) {
475                 si->negotiated = true;
476                 return true;
477         }
478
479         if (!si->desired) {
480                 si->negotiated = false;
481                 return true;
482         }
483
484         if (si->desired && allowed) {
485                 si->negotiated = true;
486                 return true;
487         }
488
489         si->negotiated = false;
490         return true;
491 }
492
493 bool smb_signing_is_negotiated(struct smb_signing_state *si)
494 {
495         return si->negotiated;
496 }
497
498 void smb_key_derivation(const uint8_t *KI, size_t KI_len,
499                         uint8_t KO[16])
500 {
501         static const uint8_t SSKeyHash[256] = {
502                 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
503                 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
504                 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
505                 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
506                 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
507                 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
508                 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
509                 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
510                 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
511                 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
512                 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
513                 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
514                 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
515                 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
516                 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
517                 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
518                 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
519                 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
520                 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
521                 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
522                 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
523                 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
524                 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
525                 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
526                 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
527                 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
528                 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
529                 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
530                 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
531                 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
532                 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
533                 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
534         };
535
536         /* The callers passing down KI_len of 16 so no need to limit to 64 */
537         gnutls_hmac_fast(GNUTLS_MAC_MD5,
538                          KI,
539                          KI_len,
540                          SSKeyHash,
541                          sizeof(SSKeyHash),
542                          KO);
543 }