2 Unix SMB/CIFS implementation.
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/>.
23 #include "smb_common.h"
24 #include "smb_signing.h"
26 #include "libcli/util/gnutls_error.h"
27 #include <gnutls/gnutls.h>
28 #include <gnutls/crypto.h>
30 /* Used by the SMB signing functions. */
32 struct smb_signing_state {
33 /* is signing localy allowed */
36 /* is signing localy desired */
39 /* is signing localy mandatory */
42 /* is signing negotiated by the peer */
45 bool active; /* Have I ever seen a validly signed packet? */
47 /* mac_key.length > 0 means signing is started */
50 /* the next expected seqnum */
54 void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
55 void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
58 static void smb_signing_reset_info(struct smb_signing_state *si)
64 si->free_fn(si->mem_ctx, si->mac_key.data);
66 talloc_free(si->mac_key.data);
68 si->mac_key.data = NULL;
69 si->mac_key.length = 0;
72 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
76 void *(*alloc_fn)(TALLOC_CTX *, size_t),
77 void (*free_fn)(TALLOC_CTX *, void *))
79 struct smb_signing_state *si;
82 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
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;
92 si = talloc_zero(mem_ctx, struct smb_signing_state);
106 si->allowed = allowed;
107 si->desired = desired;
108 si->mandatory = mandatory;
113 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
118 return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
122 static bool smb_signing_good(struct smb_signing_state *si,
123 bool good, uint32_t seq)
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);
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));
145 static NTSTATUS smb_signing_md5(const DATA_BLOB *mac_key,
146 const uint8_t *hdr, size_t len,
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;
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 DEBUG(10,("smb_signing_md5: 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
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);
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);
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);
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));
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);
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);
207 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
211 if (si->mac_key.length == 0) {
225 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
227 if (si->mac_key.length == 0) {
238 NTSTATUS smb_signing_sign_pdu(struct smb_signing_state *si,
239 uint8_t *outhdr, size_t len,
242 uint8_t calc_md5_mac[16];
246 if (si->mac_key.length == 0) {
247 if (!si->negotiated) {
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",
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
281 if (com == SMBsesssetupX) {
282 memcpy(calc_md5_mac, "BSRSPYL ", 8);
284 memset(calc_md5_mac, 0, 8);
289 status = smb_signing_md5(&si->mac_key,
294 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(10, ("smb_signing_sign_pdu: 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...*/
310 bool smb_signing_check_pdu(struct smb_signing_state *si,
311 const uint8_t *inhdr, size_t len,
315 uint8_t calc_md5_mac[16];
316 const uint8_t *reply_sent_mac;
319 if (si->mac_key.length == 0) {
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",
330 status = smb_signing_md5(&si->mac_key,
335 if (!NT_STATUS_IS_OK(status)) {
336 DBG_ERR("Failed to calculate signing mac: %s\n",
341 reply_sent_mac = &inhdr[HDR_SS_FIELD];
342 good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
346 const int sign_range = 5;
348 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
349 dump_data(5, calc_md5_mac, 8);
351 DEBUG(5, ("smb_signing_check_pdu: 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 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));
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);
373 return smb_signing_good(si, good, seqnum);
376 bool smb_signing_activate(struct smb_signing_state *si,
377 const DATA_BLOB user_session_key,
378 const DATA_BLOB response)
383 if (!user_session_key.length) {
387 if (!si->negotiated) {
395 if (si->mac_key.length > 0) {
399 smb_signing_reset_info(si);
401 len = response.length + user_session_key.length;
403 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
404 if (si->mac_key.data == NULL) {
408 si->mac_key.data = (uint8_t *)talloc_size(si, len);
409 if (si->mac_key.data == NULL) {
413 si->mac_key.length = len;
416 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
418 DEBUG(10, ("smb_signing_activate: user_session_key\n"));
419 dump_data(10, user_session_key.data, user_session_key.length);
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);
427 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
430 dump_data_pw("smb_signing_activate: mac key is:\n",
431 si->mac_key.data, si->mac_key.length);
433 /* Initialise the sequence number */
439 bool smb_signing_is_active(struct smb_signing_state *si)
444 bool smb_signing_is_allowed(struct smb_signing_state *si)
449 bool smb_signing_is_desired(struct smb_signing_state *si)
454 bool smb_signing_is_mandatory(struct smb_signing_state *si)
456 return si->mandatory;
459 bool smb_signing_set_negotiated(struct smb_signing_state *si,
460 bool allowed, bool mandatory)
470 if (!si->allowed && mandatory) {
474 if (si->mandatory && !allowed) {
479 si->negotiated = true;
484 si->negotiated = true;
489 si->negotiated = false;
493 if (si->desired && allowed) {
494 si->negotiated = true;
498 si->negotiated = false;
502 bool smb_signing_is_negotiated(struct smb_signing_state *si)
504 return si->negotiated;
507 NTSTATUS smb_key_derivation(const uint8_t *KI,
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
547 /* The callers passing down KI_len of 16 so no need to limit to 64 */
548 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
555 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);