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 <gnutls/gnutls.h>
27 #include <gnutls/crypto.h>
29 /* Used by the SMB signing functions. */
31 struct smb_signing_state {
32 /* is signing localy allowed */
35 /* is signing localy desired */
38 /* is signing localy mandatory */
41 /* is signing negotiated by the peer */
44 bool active; /* Have I ever seen a validly signed packet? */
46 /* mac_key.length > 0 means signing is started */
49 /* the next expected seqnum */
53 void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
54 void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
57 static void smb_signing_reset_info(struct smb_signing_state *si)
63 si->free_fn(si->mem_ctx, si->mac_key.data);
65 talloc_free(si->mac_key.data);
67 si->mac_key.data = NULL;
68 si->mac_key.length = 0;
71 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
75 void *(*alloc_fn)(TALLOC_CTX *, size_t),
76 void (*free_fn)(TALLOC_CTX *, void *))
78 struct smb_signing_state *si;
81 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
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;
91 si = talloc_zero(mem_ctx, struct smb_signing_state);
105 si->allowed = allowed;
106 si->desired = desired;
107 si->mandatory = mandatory;
112 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
117 return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
121 static bool smb_signing_good(struct smb_signing_state *si,
122 bool good, uint32_t seq)
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);
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));
144 static NTSTATUS smb_signing_md5(const DATA_BLOB *mac_key,
145 const uint8_t *hdr, size_t len,
147 uint8_t calc_md5_mac[16])
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;
155 * Firstly put the sequence number into the first 4 bytes.
156 * and zero out the next 4 bytes.
158 * We do this here, to avoid modifying the packet.
161 DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number ));
163 SIVAL(sequence_buf, 0, seq_number);
164 SIVAL(sequence_buf, 4, 0);
167 * Calculate the 16 byte MAC - but don't alter the data in the
170 * This makes for a bit of fussing about, but it's not too bad.
172 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
174 if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
175 return NT_STATUS_HASH_NOT_SUPPORTED;
177 return NT_STATUS_NO_MEMORY;
179 /* Initialise with the key. */
180 rc = gnutls_hash(hash_hnd, mac_key->data, mac_key->length);
182 gnutls_hash_deinit(hash_hnd, NULL);
183 return NT_STATUS_INTERNAL_ERROR;
185 /* Copy in the first bit of the SMB header. */
186 rc = gnutls_hash(hash_hnd, hdr, HDR_SS_FIELD);
188 gnutls_hash_deinit(hash_hnd, NULL);
189 return NT_STATUS_INTERNAL_ERROR;
191 /* Copy in the sequence number, instead of the signature. */
192 rc = gnutls_hash(hash_hnd, sequence_buf, sizeof(sequence_buf));
194 gnutls_hash_deinit(hash_hnd, NULL);
195 return NT_STATUS_INTERNAL_ERROR;
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);
200 gnutls_hash_deinit(hash_hnd, NULL);
201 return NT_STATUS_INTERNAL_ERROR;
204 gnutls_hash_deinit(hash_hnd, calc_md5_mac);
209 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
213 if (si->mac_key.length == 0) {
227 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
229 if (si->mac_key.length == 0) {
240 void smb_signing_sign_pdu(struct smb_signing_state *si,
241 uint8_t *outhdr, size_t len,
244 uint8_t calc_md5_mac[16];
248 if (si->mac_key.length == 0) {
249 if (!si->negotiated) {
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",
262 com = SVAL(outhdr, HDR_COM);
263 flags = SVAL(outhdr, HDR_FLG);
265 if (!(flags & FLAG_REPLY)) {
266 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
268 * If this is a request, specify what is
269 * supported or required by the client
271 if (si->negotiated && si->desired) {
272 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
274 if (si->negotiated && si->mandatory) {
275 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
277 SSVAL(outhdr, HDR_FLG2, flags2);
280 if (si->mac_key.length == 0) {
281 /* I wonder what BSRSPYL stands for - but this is what MS
283 if (com == SMBsesssetupX) {
284 memcpy(calc_md5_mac, "BSRSPYL ", 8);
286 memset(calc_md5_mac, 0, 8);
291 status = smb_signing_md5(&si->mac_key,
296 if (!NT_STATUS_IS_OK(status)) {
301 DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
302 dump_data(10, calc_md5_mac, 8);
304 memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
306 /* outhdr[HDR_SS_FIELD+2]=0;
307 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;
318 if (si->mac_key.length == 0) {
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",
329 smb_signing_md5(&si->mac_key, inhdr, len,
330 seqnum, calc_md5_mac);
332 reply_sent_mac = &inhdr[HDR_SS_FIELD];
333 good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
337 const int sign_range = 5;
339 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
340 dump_data(5, calc_md5_mac, 8);
342 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
343 dump_data(5, reply_sent_mac, 8);
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));
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);
364 return smb_signing_good(si, good, seqnum);
367 bool smb_signing_activate(struct smb_signing_state *si,
368 const DATA_BLOB user_session_key,
369 const DATA_BLOB response)
374 if (!user_session_key.length) {
378 if (!si->negotiated) {
386 if (si->mac_key.length > 0) {
390 smb_signing_reset_info(si);
392 len = response.length + user_session_key.length;
394 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
395 if (si->mac_key.data == NULL) {
399 si->mac_key.data = (uint8_t *)talloc_size(si, len);
400 if (si->mac_key.data == NULL) {
404 si->mac_key.length = len;
407 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
409 DEBUG(10, ("smb_signing_activate: user_session_key\n"));
410 dump_data(10, user_session_key.data, user_session_key.length);
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);
418 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
421 dump_data_pw("smb_signing_activate: mac key is:\n",
422 si->mac_key.data, si->mac_key.length);
424 /* Initialise the sequence number */
430 bool smb_signing_is_active(struct smb_signing_state *si)
435 bool smb_signing_is_allowed(struct smb_signing_state *si)
440 bool smb_signing_is_desired(struct smb_signing_state *si)
445 bool smb_signing_is_mandatory(struct smb_signing_state *si)
447 return si->mandatory;
450 bool smb_signing_set_negotiated(struct smb_signing_state *si,
451 bool allowed, bool mandatory)
461 if (!si->allowed && mandatory) {
465 if (si->mandatory && !allowed) {
470 si->negotiated = true;
475 si->negotiated = true;
480 si->negotiated = false;
484 if (si->desired && allowed) {
485 si->negotiated = true;
489 si->negotiated = false;
493 bool smb_signing_is_negotiated(struct smb_signing_state *si)
495 return si->negotiated;
498 void smb_key_derivation(const uint8_t *KI, size_t KI_len,
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
536 /* The callers passing down KI_len of 16 so no need to limit to 64 */
537 gnutls_hmac_fast(GNUTLS_MAC_MD5,