r3294: Fix for SMB signing with 56-bit DES session keys. From Nalin Dahyabhai <nalin...
[Samba/nascimento.git] / source3 / libsmb / smb_signing.c
blobb02a13c73e12f73738023c04da787a0696dad441
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
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
25 struct outstanding_packet_lookup {
26 uint16 mid;
27 uint32 reply_seq_num;
28 struct outstanding_packet_lookup *prev, *next;
31 /* Store the data for an ongoing trans/trans2/nttrans operation. */
32 struct trans_info_context {
33 uint16 mid;
34 uint32 send_seq_num;
35 uint32 reply_seq_num;
38 struct smb_basic_signing_context {
39 DATA_BLOB mac_key;
40 uint32 send_seq_num;
41 struct trans_info_context *trans_info;
42 struct outstanding_packet_lookup *outstanding_packet_list;
45 static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list,
46 uint16 mid, uint32 reply_seq_num)
48 struct outstanding_packet_lookup *t;
50 /* Ensure we only add a mid once. */
51 for (t = *list; t; t = t->next) {
52 if (t->mid == mid) {
53 return False;
57 t = smb_xmalloc(sizeof(*t));
58 ZERO_STRUCTP(t);
60 t->mid = mid;
61 t->reply_seq_num = reply_seq_num;
64 * Add to the *start* of the list not the end of the list.
65 * This ensures that the *last* send sequence with this mid
66 * is returned by preference.
67 * This can happen if the mid wraps and one of the early
68 * mid numbers didn't get a reply and is still lurking on
69 * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>.
72 DLIST_ADD(*list, t);
73 DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
74 (unsigned int)reply_seq_num, (unsigned int)mid ));
75 return True;
78 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
79 uint16 mid, uint32 *reply_seq_num)
81 struct outstanding_packet_lookup *t;
83 for (t = *list; t; t = t->next) {
84 if (t->mid == mid) {
85 *reply_seq_num = t->reply_seq_num;
86 DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
87 (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
88 DLIST_REMOVE(*list, t);
89 SAFE_FREE(t);
90 return True;
93 return False;
96 /***********************************************************
97 SMB signing - Common code before we set a new signing implementation
98 ************************************************************/
100 static BOOL cli_set_smb_signing_common(struct cli_state *cli)
102 if (!cli->sign_info.negotiated_smb_signing
103 && !cli->sign_info.mandatory_signing) {
104 return False;
107 if (cli->sign_info.doing_signing) {
108 return False;
111 if (cli->sign_info.free_signing_context)
112 cli->sign_info.free_signing_context(&cli->sign_info);
114 /* These calls are INCOMPATIBLE with SMB signing */
115 cli->readbraw_supported = False;
116 cli->writebraw_supported = False;
118 return True;
121 /***********************************************************
122 SMB signing - Common code for 'real' implementations
123 ************************************************************/
125 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
127 if (si->mandatory_signing) {
128 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
131 si->doing_signing = True;
132 DEBUG(5, ("SMB signing enabled!\n"));
134 return True;
137 static void mark_packet_signed(char *outbuf)
139 uint16 flags2;
140 flags2 = SVAL(outbuf,smb_flg2);
141 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
142 SSVAL(outbuf,smb_flg2, flags2);
145 /***********************************************************
146 SMB signing - NULL implementation - calculate a MAC to send.
147 ************************************************************/
149 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
151 /* we can't zero out the sig, as we might be trying to send a
152 session request - which is NBT-level, not SMB level and doesn't
153 have the field */
154 return;
157 /***********************************************************
158 SMB signing - NULL implementation - check a MAC sent by server.
159 ************************************************************/
161 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
163 return True;
166 /***********************************************************
167 SMB signing - NULL implementation - free signing context
168 ************************************************************/
170 static void null_free_signing_context(struct smb_sign_info *si)
172 return;
176 SMB signing - NULL implementation - setup the MAC key.
178 @note Used as an initialisation only - it will not correctly
179 shut down a real signing mechanism
182 static BOOL null_set_signing(struct smb_sign_info *si)
184 si->signing_context = NULL;
186 si->sign_outgoing_message = null_sign_outgoing_message;
187 si->check_incoming_message = null_check_incoming_message;
188 si->free_signing_context = null_free_signing_context;
190 return True;
194 * Free the signing context
197 static void free_signing_context(struct smb_sign_info *si)
199 if (si->free_signing_context) {
200 si->free_signing_context(si);
201 si->signing_context = NULL;
204 null_set_signing(si);
208 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok)
210 if (good) {
212 if (!si->doing_signing) {
213 si->doing_signing = True;
216 if (!si->seen_valid) {
217 si->seen_valid = True;
220 } else {
221 if (!si->mandatory_signing && !si->seen_valid) {
223 if (!must_be_ok) {
224 return True;
226 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
227 DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n"
228 "isn't sending correct signatures. Turning off.\n"));
229 si->negotiated_smb_signing = False;
230 si->allow_smb_signing = False;
231 si->doing_signing = False;
232 free_signing_context(si);
233 return True;
234 } else if (!must_be_ok) {
235 /* This packet is known to be unsigned */
236 return True;
237 } else {
238 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
239 if (seq)
240 DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
241 return False;
244 return True;
247 /***********************************************************
248 SMB signing - Simple implementation - calculate a MAC on the packet
249 ************************************************************/
251 static void simple_packet_signature(struct smb_basic_signing_context *data,
252 const uchar *buf, uint32 seq_number,
253 unsigned char calc_md5_mac[16])
255 const size_t offset_end_of_sig = (smb_ss_field + 8);
256 unsigned char sequence_buf[8];
257 struct MD5Context md5_ctx;
258 unsigned char key_buf[16];
261 * Firstly put the sequence number into the first 4 bytes.
262 * and zero out the next 4 bytes.
264 * We do this here, to avoid modifying the packet.
267 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
269 SIVAL(sequence_buf, 0, seq_number);
270 SIVAL(sequence_buf, 4, 0);
272 /* Calculate the 16 byte MAC - but don't alter the data in the
273 incoming packet.
275 This makes for a bit of fussing about, but it's not too bad.
277 MD5Init(&md5_ctx);
279 /* intialise with the key */
280 /* NB. When making and verifying SMB signatures, Windows apparently
281 zero-pads the key to 128 bits if it isn't long enough.
282 From Nalin Dahyabhai <nalin@redhat.com> */
283 MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length);
284 if (data->mac_key.length < sizeof(key_buf)) {
285 memset(key_buf, 0, sizeof(key_buf));
286 MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length);
289 /* copy in the first bit of the SMB header */
290 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
292 /* copy in the sequence number, instead of the signature */
293 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
295 /* copy in the rest of the packet in, skipping the signature */
296 MD5Update(&md5_ctx, buf + offset_end_of_sig,
297 smb_len(buf) - (offset_end_of_sig - 4));
299 /* calculate the MD5 sig */
300 MD5Final(calc_md5_mac, &md5_ctx);
304 /***********************************************************
305 SMB signing - Client implementation - send the MAC.
306 ************************************************************/
308 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
310 unsigned char calc_md5_mac[16];
311 struct smb_basic_signing_context *data = si->signing_context;
312 uint32 send_seq_num;
314 if (!si->doing_signing)
315 return;
317 /* JRA Paranioa test - we should be able to get rid of this... */
318 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
319 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
320 smb_len(outbuf) ));
321 abort();
324 /* mark the packet as signed - BEFORE we sign it...*/
325 mark_packet_signed(outbuf);
327 if (data->trans_info)
328 send_seq_num = data->trans_info->send_seq_num;
329 else
330 send_seq_num = data->send_seq_num;
332 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
334 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
335 dump_data(10, (const char *)calc_md5_mac, 8);
337 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
339 /* cli->outbuf[smb_ss_field+2]=0;
340 Uncomment this to test if the remote server actually verifies signatures...*/
342 if (data->trans_info)
343 return;
345 data->send_seq_num++;
346 store_sequence_for_reply(&data->outstanding_packet_list,
347 SVAL(outbuf,smb_mid), data->send_seq_num);
348 data->send_seq_num++;
351 /***********************************************************
352 SMB signing - Client implementation - check a MAC sent by server.
353 ************************************************************/
355 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
357 BOOL good;
358 uint32 reply_seq_number;
359 uint32 saved_seq;
360 unsigned char calc_md5_mac[16];
361 unsigned char *server_sent_mac;
363 struct smb_basic_signing_context *data = si->signing_context;
365 if (!si->doing_signing)
366 return True;
368 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
369 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
370 return False;
373 if (data->trans_info) {
374 reply_seq_number = data->trans_info->reply_seq_num;
375 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
376 SVAL(inbuf, smb_mid), &reply_seq_number)) {
377 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
378 (unsigned int) SVAL(inbuf, smb_mid) ));
379 return False;
382 saved_seq = reply_seq_number;
383 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
385 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
386 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
388 if (!good) {
389 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
390 dump_data(5, (const char *)calc_md5_mac, 8);
392 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
393 dump_data(5, (const char *)server_sent_mac, 8);
394 #if 1 /* JRATEST */
396 int i;
397 reply_seq_number -= 5;
398 for (i = 0; i < 10; i++, reply_seq_number++) {
399 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
400 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
401 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
402 We were expecting seq %u\n", reply_seq_number, saved_seq ));
403 break;
407 #endif /* JRATEST */
409 } else {
410 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
411 dump_data(10, (const char *)server_sent_mac, 8);
413 return signing_good(inbuf, si, good, saved_seq, must_be_ok);
416 /***********************************************************
417 SMB signing - Simple implementation - free signing context
418 ************************************************************/
420 static void simple_free_signing_context(struct smb_sign_info *si)
422 struct smb_basic_signing_context *data = si->signing_context;
423 struct outstanding_packet_lookup *list = data->outstanding_packet_list;
425 while (list) {
426 struct outstanding_packet_lookup *old_head = list;
427 DLIST_REMOVE(list, list);
428 SAFE_FREE(old_head);
431 data_blob_free(&data->mac_key);
433 if (data->trans_info)
434 SAFE_FREE(data->trans_info);
436 SAFE_FREE(si->signing_context);
438 return;
441 /***********************************************************
442 SMB signing - Simple implementation - setup the MAC key.
443 ************************************************************/
445 BOOL cli_simple_set_signing(struct cli_state *cli,
446 const DATA_BLOB user_session_key,
447 const DATA_BLOB response)
449 struct smb_basic_signing_context *data;
451 if (!user_session_key.length)
452 return False;
454 if (!cli_set_smb_signing_common(cli)) {
455 return False;
458 if (!set_smb_signing_real_common(&cli->sign_info)) {
459 return False;
462 data = smb_xmalloc(sizeof(*data));
463 memset(data, '\0', sizeof(*data));
465 cli->sign_info.signing_context = data;
467 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
469 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
471 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
472 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
474 if (response.length) {
475 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
476 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
477 dump_data(10, (const char *)response.data, response.length);
478 } else {
479 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
482 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
484 /* Initialise the sequence number */
485 data->send_seq_num = 0;
487 /* Initialise the list of outstanding packets */
488 data->outstanding_packet_list = NULL;
490 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
491 cli->sign_info.check_incoming_message = client_check_incoming_message;
492 cli->sign_info.free_signing_context = simple_free_signing_context;
494 return True;
497 /***********************************************************
498 Tell client code we are in a multiple trans reply state.
499 We call this after the last outgoing trans2 packet (which
500 has incremented the sequence numbers), so we must save the
501 current mid and sequence number -2.
502 ************************************************************/
504 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
506 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
507 uint32 reply_seq_num;
509 if (!cli->sign_info.doing_signing || !data)
510 return;
512 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
513 ZERO_STRUCTP(data->trans_info);
515 /* This ensures the sequence is pulled off the outstanding packet list */
516 if (!get_sequence_for_reply(&data->outstanding_packet_list,
517 mid, &reply_seq_num)) {
518 DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
519 return;
522 data->trans_info->send_seq_num = reply_seq_num - 1;
523 data->trans_info->mid = mid;
524 data->trans_info->reply_seq_num = reply_seq_num;
526 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
527 data->send_seq_num = %u\n",
528 (unsigned int)data->trans_info->mid,
529 (unsigned int)data->trans_info->reply_seq_num,
530 (unsigned int)data->trans_info->send_seq_num,
531 (unsigned int)data->send_seq_num ));
534 /***********************************************************
535 Tell client code we are out of a multiple trans reply state.
536 ************************************************************/
538 void cli_signing_trans_stop(struct cli_state *cli)
540 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
542 if (!cli->sign_info.doing_signing || !data)
543 return;
545 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
546 data->send_seq_num = %u\n",
547 (unsigned int)data->trans_info->mid,
548 (unsigned int)data->trans_info->reply_seq_num,
549 (unsigned int)data->trans_info->send_seq_num,
550 (unsigned int)data->send_seq_num ));
552 SAFE_FREE(data->trans_info);
553 data->trans_info = NULL;
556 /***********************************************************
557 SMB signing - TEMP implementation - calculate a MAC to send.
558 ************************************************************/
560 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
562 /* mark the packet as signed - BEFORE we sign it...*/
563 mark_packet_signed(outbuf);
565 /* I wonder what BSRSPYL stands for - but this is what MS
566 actually sends! */
567 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
568 return;
571 /***********************************************************
572 SMB signing - TEMP implementation - check a MAC sent by server.
573 ************************************************************/
575 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
577 return True;
580 /***********************************************************
581 SMB signing - TEMP implementation - free signing context
582 ************************************************************/
584 static void temp_free_signing_context(struct smb_sign_info *si)
586 return;
589 /***********************************************************
590 SMB signing - NULL implementation - setup the MAC key.
591 ************************************************************/
593 BOOL cli_null_set_signing(struct cli_state *cli)
595 return null_set_signing(&cli->sign_info);
598 /***********************************************************
599 SMB signing - temp implementation - setup the MAC key.
600 ************************************************************/
602 BOOL cli_temp_set_signing(struct cli_state *cli)
604 if (!cli_set_smb_signing_common(cli)) {
605 return False;
608 cli->sign_info.signing_context = NULL;
610 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
611 cli->sign_info.check_incoming_message = temp_check_incoming_message;
612 cli->sign_info.free_signing_context = temp_free_signing_context;
614 return True;
617 void cli_free_signing_context(struct cli_state *cli)
619 free_signing_context(&cli->sign_info);
623 * Sign a packet with the current mechanism
626 void cli_calculate_sign_mac(struct cli_state *cli)
628 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
632 * Check a packet with the current mechanism
633 * @return False if we had an established signing connection
634 * which had a bad checksum, True otherwise.
637 BOOL cli_check_sign_mac(struct cli_state *cli)
639 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
640 free_signing_context(&cli->sign_info);
641 return False;
643 return True;
646 /***********************************************************
647 SMB signing - Server implementation - send the MAC.
648 ************************************************************/
650 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
652 unsigned char calc_md5_mac[16];
653 struct smb_basic_signing_context *data = si->signing_context;
654 uint32 send_seq_number = data->send_seq_num;
655 BOOL was_deferred_packet = False;
656 uint16 mid;
658 if (!si->doing_signing) {
659 return;
662 /* JRA Paranioa test - we should be able to get rid of this... */
663 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
664 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
665 smb_len(outbuf) ));
666 abort();
669 /* mark the packet as signed - BEFORE we sign it...*/
670 mark_packet_signed(outbuf);
672 mid = SVAL(outbuf, smb_mid);
674 /* See if this is a reply for a deferred packet. */
675 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
677 if (data->trans_info && (data->trans_info->mid == mid)) {
678 /* This is a reply in a trans stream. Use the sequence
679 * number associated with the stream mid. */
680 send_seq_number = data->trans_info->send_seq_num;
683 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
685 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
686 dump_data(10, (const char *)calc_md5_mac, 8);
688 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
690 /* cli->outbuf[smb_ss_field+2]=0;
691 Uncomment this to test if the remote client actually verifies signatures...*/
693 /* Don't mess with the sequence number for a deferred packet. */
694 if (was_deferred_packet) {
695 return;
698 if (!data->trans_info) {
699 /* Always increment if not in a trans stream. */
700 data->send_seq_num++;
701 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
702 /* Increment if this is the first reply in a trans stream or a
703 * packet that doesn't belong to this stream (different mid). */
704 data->send_seq_num++;
708 /***********************************************************
709 Is an incoming packet an oplock break reply ?
710 ************************************************************/
712 static BOOL is_oplock_break(char *inbuf)
714 if (CVAL(inbuf,smb_com) != SMBlockingX)
715 return False;
717 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
718 return False;
720 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
721 return True;
724 /***********************************************************
725 SMB signing - Server implementation - check a MAC sent by server.
726 ************************************************************/
728 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
730 BOOL good;
731 struct smb_basic_signing_context *data = si->signing_context;
732 uint32 reply_seq_number = data->send_seq_num;
733 uint32 saved_seq;
734 unsigned char calc_md5_mac[16];
735 unsigned char *server_sent_mac;
736 uint mid;
738 if (!si->doing_signing)
739 return True;
741 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
742 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
743 return False;
746 mid = SVAL(inbuf, smb_mid);
748 /* Is this part of a trans stream ? */
749 if (data->trans_info && (data->trans_info->mid == mid)) {
750 /* If so we don't increment the sequence. */
751 reply_seq_number = data->trans_info->reply_seq_num;
752 } else {
753 /* We always increment the sequence number. */
754 data->send_seq_num++;
756 /* If we get an asynchronous oplock break reply and there
757 * isn't a reply pending we need to re-sync the sequence
758 * number.
760 if (is_oplock_break(inbuf)) {
761 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
762 data->send_seq_num++;
766 saved_seq = reply_seq_number;
767 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
769 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
770 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
772 if (!good) {
774 if (saved_seq) {
775 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
776 (unsigned int)saved_seq));
777 dump_data(5, (const char *)calc_md5_mac, 8);
779 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
780 (unsigned int)reply_seq_number));
781 dump_data(5, (const char *)server_sent_mac, 8);
784 #if 1 /* JRATEST */
786 int i;
787 reply_seq_number -= 5;
788 for (i = 0; i < 10; i++, reply_seq_number++) {
789 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
790 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
791 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
792 We were expecting seq %u\n", reply_seq_number, saved_seq ));
793 break;
797 #endif /* JRATEST */
799 } else {
800 DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num));
801 dump_data(10, (const char *)server_sent_mac, 8);
804 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
807 /***********************************************************
808 SMB signing - server API's.
809 ************************************************************/
811 static struct smb_sign_info srv_sign_info = {
812 null_sign_outgoing_message,
813 null_check_incoming_message,
814 null_free_signing_context,
815 NULL,
816 False,
817 False,
818 False,
819 False
822 /***********************************************************
823 Turn signing off or on for oplock break code.
824 ************************************************************/
826 BOOL srv_oplock_set_signing(BOOL onoff)
828 BOOL ret = srv_sign_info.doing_signing;
829 srv_sign_info.doing_signing = onoff;
830 return ret;
833 /***********************************************************
834 Called to validate an incoming packet from the client.
835 ************************************************************/
837 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
839 /* Check if it's a session keepalive. */
840 if(CVAL(inbuf,0) == SMBkeepalive)
841 return True;
843 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
846 /***********************************************************
847 Called to sign an outgoing packet to the client.
848 ************************************************************/
850 void srv_calculate_sign_mac(char *outbuf)
852 /* Check if it's a session keepalive. */
853 /* JRA Paranioa test - do we ever generate these in the server ? */
854 if(CVAL(outbuf,0) == SMBkeepalive)
855 return;
857 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
860 /***********************************************************
861 Called by server to defer an outgoing packet.
862 ************************************************************/
864 void srv_defer_sign_response(uint16 mid)
866 struct smb_basic_signing_context *data;
868 if (!srv_sign_info.doing_signing)
869 return;
871 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
873 if (!data)
874 return;
877 * Ensure we only store this mid reply once...
880 if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
881 data->send_seq_num++;
885 /***********************************************************
886 Called to remove sequence records when a deferred packet is
887 cancelled by mid. This should never find one....
888 ************************************************************/
890 void srv_cancel_sign_response(uint16 mid)
892 struct smb_basic_signing_context *data;
893 uint32 dummy_seq;
895 if (!srv_sign_info.doing_signing)
896 return;
898 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
900 if (!data)
901 return;
903 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
905 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
909 /***********************************************************
910 Called by server negprot when signing has been negotiated.
911 ************************************************************/
913 void srv_set_signing_negotiated(void)
915 srv_sign_info.allow_smb_signing = True;
916 srv_sign_info.negotiated_smb_signing = True;
917 if (lp_server_signing() == Required)
918 srv_sign_info.mandatory_signing = True;
920 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
921 srv_sign_info.check_incoming_message = temp_check_incoming_message;
922 srv_sign_info.free_signing_context = temp_free_signing_context;
925 /***********************************************************
926 Returns whether signing is active. We can't use sendfile or raw
927 reads/writes if it is.
928 ************************************************************/
930 BOOL srv_is_signing_active(void)
932 return srv_sign_info.doing_signing;
936 /***********************************************************
937 Returns whether signing is negotiated. We can't use it unless it was
938 in the negprot.
939 ************************************************************/
941 BOOL srv_is_signing_negotiated(void)
943 return srv_sign_info.negotiated_smb_signing;
946 /***********************************************************
947 Returns whether signing is actually happening
948 ************************************************************/
950 BOOL srv_signing_started(void)
952 struct smb_basic_signing_context *data;
954 if (!srv_sign_info.doing_signing) {
955 return False;
958 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
959 if (!data)
960 return False;
962 if (data->send_seq_num == 0) {
963 return False;
966 return True;
970 /***********************************************************
971 Tell server code we are in a multiple trans reply state.
972 ************************************************************/
974 void srv_signing_trans_start(uint16 mid)
976 struct smb_basic_signing_context *data;
978 if (!srv_sign_info.doing_signing)
979 return;
981 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
982 if (!data)
983 return;
985 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
986 ZERO_STRUCTP(data->trans_info);
988 data->trans_info->reply_seq_num = data->send_seq_num-1;
989 data->trans_info->mid = mid;
990 data->trans_info->send_seq_num = data->send_seq_num;
992 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
993 data->send_seq_num = %u\n",
994 (unsigned int)mid,
995 (unsigned int)data->trans_info->reply_seq_num,
996 (unsigned int)data->trans_info->send_seq_num,
997 (unsigned int)data->send_seq_num ));
1000 /***********************************************************
1001 Tell server code we are out of a multiple trans reply state.
1002 ************************************************************/
1004 void srv_signing_trans_stop(void)
1006 struct smb_basic_signing_context *data;
1008 if (!srv_sign_info.doing_signing)
1009 return;
1011 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1012 if (!data || !data->trans_info)
1013 return;
1015 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1016 data->send_seq_num = %u\n",
1017 (unsigned int)data->trans_info->mid,
1018 (unsigned int)data->trans_info->reply_seq_num,
1019 (unsigned int)data->trans_info->send_seq_num,
1020 (unsigned int)data->send_seq_num ));
1022 SAFE_FREE(data->trans_info);
1023 data->trans_info = NULL;
1026 /***********************************************************
1027 Turn on signing from this packet onwards.
1028 ************************************************************/
1030 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1032 struct smb_basic_signing_context *data;
1034 if (!user_session_key.length)
1035 return;
1037 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1038 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1039 (unsigned int)srv_sign_info.negotiated_smb_signing,
1040 (unsigned int)srv_sign_info.mandatory_signing ));
1041 return;
1044 /* Once we've turned on, ignore any more sessionsetups. */
1045 if (srv_sign_info.doing_signing) {
1046 return;
1049 if (srv_sign_info.free_signing_context)
1050 srv_sign_info.free_signing_context(&srv_sign_info);
1052 srv_sign_info.doing_signing = True;
1054 data = smb_xmalloc(sizeof(*data));
1055 memset(data, '\0', sizeof(*data));
1057 srv_sign_info.signing_context = data;
1059 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1061 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1062 if (response.length)
1063 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1065 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1067 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1068 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1069 BOOLSTR(srv_sign_info.mandatory_signing) ));
1071 /* Initialise the sequence number */
1072 data->send_seq_num = 0;
1074 /* Initialise the list of outstanding packets */
1075 data->outstanding_packet_list = NULL;
1077 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1078 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1079 srv_sign_info.free_signing_context = simple_free_signing_context;