smbd: check for previous versions in check_any_access_fsp()
[Samba.git] / libcli / smb / smb_signing.c
blobd50c96383809540b4bd4a25851aafc84b86f0c66
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
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.
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.
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/>.
22 #include "includes.h"
23 #include "smb_common.h"
24 #include "smb_signing.h"
26 #include "lib/crypto/gnutls_helpers.h"
27 #include <gnutls/gnutls.h>
28 #include <gnutls/crypto.h>
30 /* Used by the SMB1 signing functions. */
32 struct smb1_signing_state {
33 /* is signing locally allowed */
34 bool allowed;
36 /* is signing locally desired */
37 bool desired;
39 /* is signing locally mandatory */
40 bool mandatory;
42 /* is signing negotiated by the peer */
43 bool negotiated;
45 bool active; /* Have I ever seen a validly signed packet? */
47 /* mac_key.length > 0 means signing is started */
48 DATA_BLOB mac_key;
50 /* the next expected seqnum */
51 uint32_t seqnum;
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);
58 static void smb1_signing_reset_info(struct smb1_signing_state *si)
60 si->active = false;
61 si->seqnum = 0;
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);
68 si->mac_key.data = NULL;
69 si->mac_key.length = 0;
72 struct smb1_signing_state *smb1_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 *))
79 struct smb1_signing_state *si;
81 if (alloc_fn) {
82 void *p = alloc_fn(mem_ctx, sizeof(struct smb1_signing_state));
83 if (p == NULL) {
84 return NULL;
86 memset(p, 0, sizeof(struct smb1_signing_state));
87 si = (struct smb1_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 smb1_signing_state);
93 if (si == NULL) {
94 return NULL;
98 if (mandatory) {
99 desired = true;
102 if (desired) {
103 allowed = true;
106 si->allowed = allowed;
107 si->desired = desired;
108 si->mandatory = mandatory;
110 return si;
113 struct smb1_signing_state *smb1_signing_init(TALLOC_CTX *mem_ctx,
114 bool allowed,
115 bool desired,
116 bool mandatory)
118 return smb1_signing_init_ex(mem_ctx, allowed, desired, mandatory,
119 NULL, NULL);
122 static bool smb1_signing_good(struct smb1_signing_state *si,
123 bool good, uint32_t seq)
125 if (good) {
126 if (!si->active) {
127 si->active = true;
129 return true;
132 if (!si->mandatory && !si->active) {
133 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
134 DBG_INFO("signing negotiated but not required and peer\n"
135 "isn't sending correct signatures. Turning off.\n");
136 smb1_signing_reset_info(si);
137 return true;
140 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
141 DBG_ERR("BAD SIG: seq %u\n", (unsigned int)seq);
142 return false;
145 static NTSTATUS smb1_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])
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;
156 * Firstly put the sequence number into the first 4 bytes.
157 * and zero out the next 4 bytes.
159 * We do this here, to avoid modifying the packet.
162 DBG_DEBUG("sequence number %u\n", seq_number );
164 SIVAL(sequence_buf, 0, seq_number);
165 SIVAL(sequence_buf, 4, 0);
168 * Calculate the 16 byte MAC - but don't alter the data in the
169 * incoming packet.
171 * This makes for a bit of fussing about, but it's not too bad.
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);
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);
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);
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);
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);
202 gnutls_hash_deinit(hash_hnd, calc_md5_mac);
204 return NT_STATUS_OK;
207 uint32_t smb1_signing_next_seqnum(struct smb1_signing_state *si, bool oneway)
209 uint32_t seqnum;
211 if (si->mac_key.length == 0) {
212 return 0;
215 seqnum = si->seqnum;
216 if (oneway) {
217 si->seqnum += 1;
218 } else {
219 si->seqnum += 2;
222 return seqnum;
225 void smb1_signing_cancel_reply(struct smb1_signing_state *si, bool oneway)
227 if (si->mac_key.length == 0) {
228 return;
231 if (oneway) {
232 si->seqnum -= 1;
233 } else {
234 si->seqnum -= 2;
238 NTSTATUS smb1_signing_sign_pdu(struct smb1_signing_state *si,
239 uint8_t *outhdr, size_t len,
240 uint32_t seqnum)
242 uint8_t calc_md5_mac[16];
243 uint8_t com;
244 uint8_t flags;
246 if (si->mac_key.length == 0) {
247 if (!si->negotiated) {
248 return NT_STATUS_OK;
252 /* JRA Paranioa test - we should be able to get rid of this... */
253 if (len < (HDR_SS_FIELD + 8)) {
254 DBG_WARNING("Logic error. "
255 "Can't check signature on short packet! smb_len = %u\n",
256 (unsigned)len);
257 abort();
260 com = SVAL(outhdr, HDR_COM);
261 flags = SVAL(outhdr, HDR_FLG);
263 if (!(flags & FLAG_REPLY)) {
264 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
266 * If this is a request, specify what is
267 * supported or required by the client
269 if (si->negotiated && si->desired) {
270 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
272 if (si->negotiated && si->mandatory) {
273 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
275 SSVAL(outhdr, HDR_FLG2, flags2);
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);
286 } else {
287 NTSTATUS status;
289 status = smb1_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;
299 DBG_DEBUG("sent SMB signature of\n");
300 dump_data(10, calc_md5_mac, 8);
302 memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
304 /* outhdr[HDR_SS_FIELD+2]=0;
305 Uncomment this to test if the remote server actually verifies signatures...*/
307 return NT_STATUS_OK;
310 bool smb1_signing_check_pdu(struct smb1_signing_state *si,
311 const uint8_t *inhdr, size_t len,
312 uint32_t seqnum)
314 bool good;
315 uint8_t calc_md5_mac[16];
316 const uint8_t *reply_sent_mac;
317 NTSTATUS status;
319 if (si->mac_key.length == 0) {
320 return true;
323 if (len < (HDR_SS_FIELD + 8)) {
324 DBG_WARNING("Can't check signature "
325 "on short packet! smb_len = %u\n",
326 (unsigned)len);
327 return false;
330 status = smb1_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;
341 reply_sent_mac = &inhdr[HDR_SS_FIELD];
342 good = mem_equal_const_time(reply_sent_mac, calc_md5_mac, 8);
344 if (!good) {
345 int i;
346 const int sign_range = 5;
348 DBG_INFO("BAD SIG: wanted SMB signature of\n");
349 dump_data(5, calc_md5_mac, 8);
351 DBG_INFO("BAD SIG: got SMB signature of\n");
352 dump_data(5, reply_sent_mac, 8);
354 for (i = -sign_range; i < sign_range; i++) {
355 smb1_signing_md5(&si->mac_key, inhdr, len,
356 seqnum+i, calc_md5_mac);
357 if (mem_equal_const_time(reply_sent_mac, calc_md5_mac, 8)) {
358 DBG_ERR("out of seq. seq num %u matches. "
359 "We were expecting seq %u\n",
360 (unsigned int)seqnum+i,
361 (unsigned int)seqnum);
362 break;
365 } else {
366 DBG_DEBUG("seq %u: got good SMB signature of\n",
367 (unsigned int)seqnum);
368 dump_data(10, reply_sent_mac, 8);
371 return smb1_signing_good(si, good, seqnum);
374 bool smb1_signing_activate(struct smb1_signing_state *si,
375 const DATA_BLOB user_session_key,
376 const DATA_BLOB response)
378 size_t len;
379 off_t ofs;
381 if (!user_session_key.length) {
382 return false;
385 if (!si->negotiated) {
386 return false;
389 if (si->active) {
390 return false;
393 if (si->mac_key.length > 0) {
394 return false;
397 smb1_signing_reset_info(si);
399 len = response.length + user_session_key.length;
400 if (si->alloc_fn) {
401 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
402 if (si->mac_key.data == NULL) {
403 return false;
405 } else {
406 si->mac_key.data = (uint8_t *)talloc_size(si, len);
407 if (si->mac_key.data == NULL) {
408 return false;
411 si->mac_key.length = len;
413 ofs = 0;
414 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
416 DBG_DEBUG("user_session_key\n");
417 dump_data(10, user_session_key.data, user_session_key.length);
419 if (response.length) {
420 ofs = user_session_key.length;
421 memcpy(&si->mac_key.data[ofs], response.data, response.length);
422 DBG_DEBUG("response_data\n");
423 dump_data(10, response.data, response.length);
424 } else {
425 DBG_DEBUG("NULL response_data\n");
428 dump_data_pw("smb1_signing_activate: mac key is:\n",
429 si->mac_key.data, si->mac_key.length);
431 /* Initialise the sequence number */
432 si->seqnum = 2;
434 return true;
437 bool smb1_signing_is_active(struct smb1_signing_state *si)
439 return si->active;
442 bool smb1_signing_is_desired(struct smb1_signing_state *si)
444 return si->desired;
447 bool smb1_signing_is_mandatory(struct smb1_signing_state *si)
449 return si->mandatory;
452 bool smb1_signing_set_negotiated(struct smb1_signing_state *si,
453 bool allowed, bool mandatory)
455 if (si->active) {
456 return true;
459 if (mandatory) {
460 allowed = true;
463 if (!si->allowed && mandatory) {
464 return false;
467 if (si->mandatory && !allowed) {
468 return false;
471 if (si->mandatory) {
472 si->negotiated = true;
473 return true;
476 if (mandatory) {
477 si->negotiated = true;
478 return true;
481 if (!si->desired) {
482 si->negotiated = false;
483 return true;
486 if (si->desired && allowed) {
487 si->negotiated = true;
488 return true;
491 si->negotiated = false;
492 return true;
495 bool smb1_signing_is_negotiated(struct smb1_signing_state *si)
497 return si->negotiated;
500 NTSTATUS smb1_key_derivation(const uint8_t *KI,
501 size_t KI_len,
502 uint8_t KO[16])
504 int rc;
505 static const uint8_t SSKeyHash[256] = {
506 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
507 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
508 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
509 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
510 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
511 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
512 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
513 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
514 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
515 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
516 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
517 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
518 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
519 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
520 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
521 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
522 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
523 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
524 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
525 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
526 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
527 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
528 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
529 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
530 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
531 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
532 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
533 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
534 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
535 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
536 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
537 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
540 /* The callers passing down KI_len of 16 so no need to limit to 64 */
541 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
543 KI_len,
544 SSKeyHash,
545 sizeof(SSKeyHash),
546 KO);
547 if (rc < 0) {
548 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
551 return NT_STATUS_OK;