dns: Use new DNS debugclass in DNS server
[kai/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/crypto.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 *outhdr, size_t len,
220                           uint32_t seqnum)
221 {
222         uint8_t calc_md5_mac[16];
223         uint8_t com;
224         uint8_t flags;
225
226         if (si->mac_key.length == 0) {
227                 if (!si->negotiated) {
228                         return;
229                 }
230         }
231
232         /* JRA Paranioa test - we should be able to get rid of this... */
233         if (len < (HDR_SS_FIELD + 8)) {
234                 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
235                          "Can't check signature on short packet! smb_len = %u\n",
236                          (unsigned)len));
237                 abort();
238         }
239
240         com = SVAL(outhdr, HDR_COM);
241         flags = SVAL(outhdr, HDR_FLG);
242
243         if (!(flags & FLAG_REPLY)) {
244                 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
245                 /*
246                  * If this is a request, specify what is
247                  * supported or required by the client
248                  */
249                 if (si->negotiated && si->desired) {
250                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
251                 }
252                 if (si->negotiated && si->mandatory) {
253                         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
254                 }
255                 SSVAL(outhdr, HDR_FLG2, flags2);
256         }
257
258         if (si->mac_key.length == 0) {
259                 /* I wonder what BSRSPYL stands for - but this is what MS
260                    actually sends! */
261                 if (com == SMBsesssetupX) {
262                         memcpy(calc_md5_mac, "BSRSPYL ", 8);
263                 } else {
264                         memset(calc_md5_mac, 0, 8);
265                 }
266         } else {
267                 smb_signing_md5(&si->mac_key, outhdr, len,
268                                 seqnum, calc_md5_mac);
269         }
270
271         DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
272         dump_data(10, calc_md5_mac, 8);
273
274         memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
275
276 /*      outhdr[HDR_SS_FIELD+2]=0;
277         Uncomment this to test if the remote server actually verifies signatures...*/
278 }
279
280 bool smb_signing_check_pdu(struct smb_signing_state *si,
281                            const uint8_t *inhdr, size_t len,
282                            uint32_t seqnum)
283 {
284         bool good;
285         uint8_t calc_md5_mac[16];
286         const uint8_t *reply_sent_mac;
287
288         if (si->mac_key.length == 0) {
289                 return true;
290         }
291
292         if (len < (HDR_SS_FIELD + 8)) {
293                 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
294                          "on short packet! smb_len = %u\n",
295                          (unsigned)len));
296                 return false;
297         }
298
299         smb_signing_md5(&si->mac_key, inhdr, len,
300                         seqnum, calc_md5_mac);
301
302         reply_sent_mac = &inhdr[HDR_SS_FIELD];
303         good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
304
305         if (!good) {
306                 int i;
307                 const int sign_range = 5;
308
309                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
310                 dump_data(5, calc_md5_mac, 8);
311
312                 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
313                 dump_data(5, reply_sent_mac, 8);
314
315                 for (i = -sign_range; i < sign_range; i++) {
316                         smb_signing_md5(&si->mac_key, inhdr, len,
317                                         seqnum+i, calc_md5_mac);
318                         if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
319                                 DEBUG(0,("smb_signing_check_pdu: "
320                                          "out of seq. seq num %u matches. "
321                                          "We were expecting seq %u\n",
322                                          (unsigned int)seqnum+i,
323                                          (unsigned int)seqnum));
324                                 break;
325                         }
326                 }
327         } else {
328                 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
329                            "got good SMB signature of\n",
330                            (unsigned int)seqnum));
331                 dump_data(10, reply_sent_mac, 8);
332         }
333
334         return smb_signing_good(si, good, seqnum);
335 }
336
337 bool smb_signing_activate(struct smb_signing_state *si,
338                           const DATA_BLOB user_session_key,
339                           const DATA_BLOB response)
340 {
341         size_t len;
342         off_t ofs;
343
344         if (!user_session_key.length) {
345                 return false;
346         }
347
348         if (!si->negotiated) {
349                 return false;
350         }
351
352         if (si->active) {
353                 return false;
354         }
355
356         if (si->mac_key.length > 0) {
357                 return false;
358         }
359
360         smb_signing_reset_info(si);
361
362         len = response.length + user_session_key.length;
363         if (si->alloc_fn) {
364                 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
365                 if (si->mac_key.data == NULL) {
366                         return false;
367                 }
368         } else {
369                 si->mac_key.data = (uint8_t *)talloc_size(si, len);
370                 if (si->mac_key.data == NULL) {
371                         return false;
372                 }
373         }
374         si->mac_key.length = len;
375
376         ofs = 0;
377         memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
378
379         DEBUG(10, ("smb_signing_activate: user_session_key\n"));
380         dump_data(10, user_session_key.data, user_session_key.length);
381
382         if (response.length) {
383                 ofs = user_session_key.length;
384                 memcpy(&si->mac_key.data[ofs], response.data, response.length);
385                 DEBUG(10, ("smb_signing_activate: response_data\n"));
386                 dump_data(10, response.data, response.length);
387         } else {
388                 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
389         }
390
391         dump_data_pw("smb_signing_activate: mac key is:\n",
392                      si->mac_key.data, si->mac_key.length);
393
394         /* Initialise the sequence number */
395         si->seqnum = 2;
396
397         return true;
398 }
399
400 bool smb_signing_is_active(struct smb_signing_state *si)
401 {
402         return si->active;
403 }
404
405 bool smb_signing_is_allowed(struct smb_signing_state *si)
406 {
407         return si->allowed;
408 }
409
410 bool smb_signing_is_mandatory(struct smb_signing_state *si)
411 {
412         return si->mandatory;
413 }
414
415 bool smb_signing_set_negotiated(struct smb_signing_state *si,
416                                 bool allowed, bool mandatory)
417 {
418         if (si->active) {
419                 return true;
420         }
421
422         if (!si->allowed && mandatory) {
423                 return false;
424         }
425
426         if (si->mandatory && !allowed) {
427                 return false;
428         }
429
430         if (si->mandatory) {
431                 si->negotiated = true;
432                 return true;
433         }
434
435         if (mandatory) {
436                 si->negotiated = true;
437                 return true;
438         }
439
440         if (!si->desired) {
441                 si->negotiated = false;
442                 return true;
443         }
444
445         if (si->desired && allowed) {
446                 si->negotiated = true;
447                 return true;
448         }
449
450         si->negotiated = false;
451         return true;
452 }
453
454 bool smb_signing_is_negotiated(struct smb_signing_state *si)
455 {
456         return si->negotiated;
457 }
458
459 void smb_key_derivation(const uint8_t *KI, size_t KI_len,
460                         uint8_t KO[16])
461 {
462         static const uint8_t SSKeyHash[256] = {
463                 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
464                 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
465                 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
466                 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
467                 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
468                 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
469                 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
470                 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
471                 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
472                 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
473                 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
474                 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
475                 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
476                 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
477                 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
478                 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
479                 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
480                 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
481                 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
482                 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
483                 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
484                 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
485                 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
486                 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
487                 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
488                 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
489                 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
490                 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
491                 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
492                 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
493                 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
494                 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
495         };
496         HMACMD5Context ctx;
497
498         hmac_md5_init_limK_to_64(KI, KI_len, &ctx);
499         hmac_md5_update(SSKeyHash, sizeof(SSKeyHash), &ctx);
500         hmac_md5_final(KO, &ctx);
501
502         ZERO_STRUCT(ctx);
503 }