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