r1383: sync from 3.0 tree
[Samba.git] / source / libsmb / smb_signing.c
blob8c59e49ebb973f411bca990e89df7193487ecf40
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;
260 * Firstly put the sequence number into the first 4 bytes.
261 * and zero out the next 4 bytes.
263 * We do this here, to avoid modifying the packet.
266 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
268 SIVAL(sequence_buf, 0, seq_number);
269 SIVAL(sequence_buf, 4, 0);
271 /* Calculate the 16 byte MAC - but don't alter the data in the
272 incoming packet.
274 This makes for a bit of fussing about, but it's not too bad.
276 MD5Init(&md5_ctx);
278 /* intialise with the key */
279 MD5Update(&md5_ctx, data->mac_key.data,
280 data->mac_key.length);
282 /* copy in the first bit of the SMB header */
283 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
285 /* copy in the sequence number, instead of the signature */
286 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
288 /* copy in the rest of the packet in, skipping the signature */
289 MD5Update(&md5_ctx, buf + offset_end_of_sig,
290 smb_len(buf) - (offset_end_of_sig - 4));
292 /* calculate the MD5 sig */
293 MD5Final(calc_md5_mac, &md5_ctx);
297 /***********************************************************
298 SMB signing - Client implementation - send the MAC.
299 ************************************************************/
301 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
303 unsigned char calc_md5_mac[16];
304 struct smb_basic_signing_context *data = si->signing_context;
305 uint32 send_seq_num;
307 if (!si->doing_signing)
308 return;
310 /* JRA Paranioa test - we should be able to get rid of this... */
311 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
312 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
313 smb_len(outbuf) ));
314 abort();
317 /* mark the packet as signed - BEFORE we sign it...*/
318 mark_packet_signed(outbuf);
320 if (data->trans_info)
321 send_seq_num = data->trans_info->send_seq_num;
322 else
323 send_seq_num = data->send_seq_num;
325 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
327 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
328 dump_data(10, (const char *)calc_md5_mac, 8);
330 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
332 /* cli->outbuf[smb_ss_field+2]=0;
333 Uncomment this to test if the remote server actually verifies signatures...*/
335 if (data->trans_info)
336 return;
338 data->send_seq_num++;
339 store_sequence_for_reply(&data->outstanding_packet_list,
340 SVAL(outbuf,smb_mid), data->send_seq_num);
341 data->send_seq_num++;
344 /***********************************************************
345 SMB signing - Client implementation - check a MAC sent by server.
346 ************************************************************/
348 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
350 BOOL good;
351 uint32 reply_seq_number;
352 uint32 saved_seq;
353 unsigned char calc_md5_mac[16];
354 unsigned char *server_sent_mac;
356 struct smb_basic_signing_context *data = si->signing_context;
358 if (!si->doing_signing)
359 return True;
361 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
362 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
363 return False;
366 if (data->trans_info) {
367 reply_seq_number = data->trans_info->reply_seq_num;
368 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
369 SVAL(inbuf, smb_mid), &reply_seq_number)) {
370 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
371 (unsigned int) SVAL(inbuf, smb_mid) ));
372 return False;
375 saved_seq = reply_seq_number;
376 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
378 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
379 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
381 if (!good) {
382 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
383 dump_data(5, (const char *)calc_md5_mac, 8);
385 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
386 dump_data(5, (const char *)server_sent_mac, 8);
387 #if 1 /* JRATEST */
389 int i;
390 reply_seq_number -= 5;
391 for (i = 0; i < 10; i++, reply_seq_number++) {
392 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
393 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
394 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
395 We were expecting seq %u\n", reply_seq_number, saved_seq ));
396 break;
400 #endif /* JRATEST */
402 } else {
403 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
404 dump_data(10, (const char *)server_sent_mac, 8);
406 return signing_good(inbuf, si, good, saved_seq, must_be_ok);
409 /***********************************************************
410 SMB signing - Simple implementation - free signing context
411 ************************************************************/
413 static void simple_free_signing_context(struct smb_sign_info *si)
415 struct smb_basic_signing_context *data = si->signing_context;
416 struct outstanding_packet_lookup *list = data->outstanding_packet_list;
418 while (list) {
419 struct outstanding_packet_lookup *old_head = list;
420 DLIST_REMOVE(list, list);
421 SAFE_FREE(old_head);
424 data_blob_free(&data->mac_key);
426 if (data->trans_info)
427 SAFE_FREE(data->trans_info);
429 SAFE_FREE(si->signing_context);
431 return;
434 /***********************************************************
435 SMB signing - Simple implementation - setup the MAC key.
436 ************************************************************/
438 BOOL cli_simple_set_signing(struct cli_state *cli,
439 const DATA_BLOB user_session_key,
440 const DATA_BLOB response)
442 struct smb_basic_signing_context *data;
444 if (!user_session_key.length)
445 return False;
447 if (!cli_set_smb_signing_common(cli)) {
448 return False;
451 if (!set_smb_signing_real_common(&cli->sign_info)) {
452 return False;
455 data = smb_xmalloc(sizeof(*data));
456 memset(data, '\0', sizeof(*data));
458 cli->sign_info.signing_context = data;
460 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
462 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
464 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
465 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
467 if (response.length) {
468 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
469 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
470 dump_data(10, (const char *)response.data, response.length);
471 } else {
472 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
475 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
477 /* Initialise the sequence number */
478 data->send_seq_num = 0;
480 /* Initialise the list of outstanding packets */
481 data->outstanding_packet_list = NULL;
483 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
484 cli->sign_info.check_incoming_message = client_check_incoming_message;
485 cli->sign_info.free_signing_context = simple_free_signing_context;
487 return True;
490 /***********************************************************
491 Tell client code we are in a multiple trans reply state.
492 We call this after the last outgoing trans2 packet (which
493 has incremented the sequence numbers), so we must save the
494 current mid and sequence number -2.
495 ************************************************************/
497 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
499 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
500 uint32 reply_seq_num;
502 if (!cli->sign_info.doing_signing || !data)
503 return;
505 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
506 ZERO_STRUCTP(data->trans_info);
508 /* This ensures the sequence is pulled off the outstanding packet list */
509 if (!get_sequence_for_reply(&data->outstanding_packet_list,
510 mid, &reply_seq_num)) {
511 DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
512 return;
515 data->trans_info->send_seq_num = reply_seq_num - 1;
516 data->trans_info->mid = mid;
517 data->trans_info->reply_seq_num = reply_seq_num;
519 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
520 data->send_seq_num = %u\n",
521 (unsigned int)data->trans_info->mid,
522 (unsigned int)data->trans_info->reply_seq_num,
523 (unsigned int)data->trans_info->send_seq_num,
524 (unsigned int)data->send_seq_num ));
527 /***********************************************************
528 Tell client code we are out of a multiple trans reply state.
529 ************************************************************/
531 void cli_signing_trans_stop(struct cli_state *cli)
533 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
535 if (!cli->sign_info.doing_signing || !data)
536 return;
538 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
539 data->send_seq_num = %u\n",
540 (unsigned int)data->trans_info->mid,
541 (unsigned int)data->trans_info->reply_seq_num,
542 (unsigned int)data->trans_info->send_seq_num,
543 (unsigned int)data->send_seq_num ));
545 SAFE_FREE(data->trans_info);
546 data->trans_info = NULL;
549 /***********************************************************
550 SMB signing - TEMP implementation - calculate a MAC to send.
551 ************************************************************/
553 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
555 /* mark the packet as signed - BEFORE we sign it...*/
556 mark_packet_signed(outbuf);
558 /* I wonder what BSRSPYL stands for - but this is what MS
559 actually sends! */
560 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
561 return;
564 /***********************************************************
565 SMB signing - TEMP implementation - check a MAC sent by server.
566 ************************************************************/
568 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
570 return True;
573 /***********************************************************
574 SMB signing - TEMP implementation - free signing context
575 ************************************************************/
577 static void temp_free_signing_context(struct smb_sign_info *si)
579 return;
582 /***********************************************************
583 SMB signing - NULL implementation - setup the MAC key.
584 ************************************************************/
586 BOOL cli_null_set_signing(struct cli_state *cli)
588 return null_set_signing(&cli->sign_info);
591 /***********************************************************
592 SMB signing - temp implementation - setup the MAC key.
593 ************************************************************/
595 BOOL cli_temp_set_signing(struct cli_state *cli)
597 if (!cli_set_smb_signing_common(cli)) {
598 return False;
601 cli->sign_info.signing_context = NULL;
603 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
604 cli->sign_info.check_incoming_message = temp_check_incoming_message;
605 cli->sign_info.free_signing_context = temp_free_signing_context;
607 return True;
610 void cli_free_signing_context(struct cli_state *cli)
612 free_signing_context(&cli->sign_info);
616 * Sign a packet with the current mechanism
619 void cli_calculate_sign_mac(struct cli_state *cli)
621 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
625 * Check a packet with the current mechanism
626 * @return False if we had an established signing connection
627 * which had a bad checksum, True otherwise.
630 BOOL cli_check_sign_mac(struct cli_state *cli, BOOL must_be_ok)
632 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, must_be_ok)) {
633 free_signing_context(&cli->sign_info);
634 return False;
636 return True;
639 /***********************************************************
640 SMB signing - Server implementation - send the MAC.
641 ************************************************************/
643 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
645 unsigned char calc_md5_mac[16];
646 struct smb_basic_signing_context *data = si->signing_context;
647 uint32 send_seq_number = data->send_seq_num;
648 BOOL was_deferred_packet = False;
649 uint16 mid;
651 if (!si->doing_signing) {
652 return;
655 /* JRA Paranioa test - we should be able to get rid of this... */
656 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
657 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
658 smb_len(outbuf) ));
659 abort();
662 /* mark the packet as signed - BEFORE we sign it...*/
663 mark_packet_signed(outbuf);
665 mid = SVAL(outbuf, smb_mid);
667 /* See if this is a reply for a deferred packet. */
668 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
670 if (data->trans_info && (data->trans_info->mid == mid)) {
671 /* This is a reply in a trans stream. Use the sequence
672 * number associated with the stream mid. */
673 send_seq_number = data->trans_info->send_seq_num;
676 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
678 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
679 dump_data(10, (const char *)calc_md5_mac, 8);
681 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
683 /* cli->outbuf[smb_ss_field+2]=0;
684 Uncomment this to test if the remote client actually verifies signatures...*/
686 /* Don't mess with the sequence number for a deferred packet. */
687 if (was_deferred_packet) {
688 return;
691 if (!data->trans_info) {
692 /* Always increment if not in a trans stream. */
693 data->send_seq_num++;
694 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
695 /* Increment if this is the first reply in a trans stream or a
696 * packet that doesn't belong to this stream (different mid). */
697 data->send_seq_num++;
701 /***********************************************************
702 Is an incoming packet an oplock break reply ?
703 ************************************************************/
705 static BOOL is_oplock_break(char *inbuf)
707 if (CVAL(inbuf,smb_com) != SMBlockingX)
708 return False;
710 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
711 return False;
713 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
714 return True;
717 /***********************************************************
718 SMB signing - Server implementation - check a MAC sent by server.
719 ************************************************************/
721 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
723 BOOL good;
724 struct smb_basic_signing_context *data = si->signing_context;
725 uint32 reply_seq_number = data->send_seq_num;
726 uint32 saved_seq;
727 unsigned char calc_md5_mac[16];
728 unsigned char *server_sent_mac;
729 uint mid;
731 if (!si->doing_signing)
732 return True;
734 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
735 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
736 return False;
739 mid = SVAL(inbuf, smb_mid);
741 /* Is this part of a trans stream ? */
742 if (data->trans_info && (data->trans_info->mid == mid)) {
743 /* If so we don't increment the sequence. */
744 reply_seq_number = data->trans_info->reply_seq_num;
745 } else {
746 /* We always increment the sequence number. */
747 data->send_seq_num++;
749 /* If we get an asynchronous oplock break reply and there
750 * isn't a reply pending we need to re-sync the sequence
751 * number.
753 if (is_oplock_break(inbuf)) {
754 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
755 data->send_seq_num++;
759 saved_seq = reply_seq_number;
760 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
762 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
763 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
765 if (!good) {
767 if (saved_seq) {
768 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
769 (unsigned int)saved_seq));
770 dump_data(5, (const char *)calc_md5_mac, 8);
772 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
773 (unsigned int)reply_seq_number));
774 dump_data(5, (const char *)server_sent_mac, 8);
777 #if 1 /* JRATEST */
779 int i;
780 reply_seq_number -= 5;
781 for (i = 0; i < 10; i++, reply_seq_number++) {
782 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
783 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
784 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
785 We were expecting seq %u\n", reply_seq_number, saved_seq ));
786 break;
790 #endif /* JRATEST */
792 } else {
793 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));
794 dump_data(10, (const char *)server_sent_mac, 8);
797 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
800 /***********************************************************
801 SMB signing - server API's.
802 ************************************************************/
804 static struct smb_sign_info srv_sign_info = {
805 null_sign_outgoing_message,
806 null_check_incoming_message,
807 null_free_signing_context,
808 NULL,
809 False,
810 False,
811 False,
812 False
815 /***********************************************************
816 Turn signing off or on for oplock break code.
817 ************************************************************/
819 BOOL srv_oplock_set_signing(BOOL onoff)
821 BOOL ret = srv_sign_info.doing_signing;
822 srv_sign_info.doing_signing = onoff;
823 return ret;
826 /***********************************************************
827 Called to validate an incoming packet from the client.
828 ************************************************************/
830 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
832 /* Check if it's a session keepalive. */
833 if(CVAL(inbuf,0) == SMBkeepalive)
834 return True;
836 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
839 /***********************************************************
840 Called to sign an outgoing packet to the client.
841 ************************************************************/
843 void srv_calculate_sign_mac(char *outbuf)
845 /* Check if it's a session keepalive. */
846 /* JRA Paranioa test - do we ever generate these in the server ? */
847 if(CVAL(outbuf,0) == SMBkeepalive)
848 return;
850 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
853 /***********************************************************
854 Called by server to defer an outgoing packet.
855 ************************************************************/
857 void srv_defer_sign_response(uint16 mid)
859 struct smb_basic_signing_context *data;
861 if (!srv_sign_info.doing_signing)
862 return;
864 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
866 if (!data)
867 return;
870 * Ensure we only store this mid reply once...
873 if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
874 data->send_seq_num++;
878 /***********************************************************
879 Called to remove sequence records when a deferred packet is
880 cancelled by mid. This should never find one....
881 ************************************************************/
883 void srv_cancel_sign_response(uint16 mid)
885 struct smb_basic_signing_context *data;
886 uint32 dummy_seq;
888 if (!srv_sign_info.doing_signing)
889 return;
891 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
893 if (!data)
894 return;
896 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
898 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
902 /***********************************************************
903 Called by server negprot when signing has been negotiated.
904 ************************************************************/
906 void srv_set_signing_negotiated(void)
908 srv_sign_info.allow_smb_signing = True;
909 srv_sign_info.negotiated_smb_signing = True;
910 if (lp_server_signing() == Required)
911 srv_sign_info.mandatory_signing = True;
913 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
914 srv_sign_info.check_incoming_message = temp_check_incoming_message;
915 srv_sign_info.free_signing_context = temp_free_signing_context;
918 /***********************************************************
919 Returns whether signing is active. We can't use sendfile or raw
920 reads/writes if it is.
921 ************************************************************/
923 BOOL srv_is_signing_active(void)
925 return srv_sign_info.doing_signing;
929 /***********************************************************
930 Returns whether signing is negotiated. We can't use it unless it was
931 in the negprot.
932 ************************************************************/
934 BOOL srv_is_signing_negotiated(void)
936 return srv_sign_info.negotiated_smb_signing;
939 /***********************************************************
940 Returns whether signing is actually happening
941 ************************************************************/
943 BOOL srv_signing_started(void)
945 struct smb_basic_signing_context *data;
947 if (!srv_sign_info.doing_signing) {
948 return False;
951 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
952 if (!data)
953 return False;
955 if (data->send_seq_num == 0) {
956 return False;
959 return True;
963 /***********************************************************
964 Tell server code we are in a multiple trans reply state.
965 ************************************************************/
967 void srv_signing_trans_start(uint16 mid)
969 struct smb_basic_signing_context *data;
971 if (!srv_sign_info.doing_signing)
972 return;
974 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
975 if (!data)
976 return;
978 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
979 ZERO_STRUCTP(data->trans_info);
981 data->trans_info->reply_seq_num = data->send_seq_num-1;
982 data->trans_info->mid = mid;
983 data->trans_info->send_seq_num = data->send_seq_num;
985 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
986 data->send_seq_num = %u\n",
987 (unsigned int)mid,
988 (unsigned int)data->trans_info->reply_seq_num,
989 (unsigned int)data->trans_info->send_seq_num,
990 (unsigned int)data->send_seq_num ));
993 /***********************************************************
994 Tell server code we are out of a multiple trans reply state.
995 ************************************************************/
997 void srv_signing_trans_stop(void)
999 struct smb_basic_signing_context *data;
1001 if (!srv_sign_info.doing_signing)
1002 return;
1004 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1005 if (!data || !data->trans_info)
1006 return;
1008 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1009 data->send_seq_num = %u\n",
1010 (unsigned int)data->trans_info->mid,
1011 (unsigned int)data->trans_info->reply_seq_num,
1012 (unsigned int)data->trans_info->send_seq_num,
1013 (unsigned int)data->send_seq_num ));
1015 SAFE_FREE(data->trans_info);
1016 data->trans_info = NULL;
1019 /***********************************************************
1020 Turn on signing from this packet onwards.
1021 ************************************************************/
1023 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1025 struct smb_basic_signing_context *data;
1027 if (!user_session_key.length)
1028 return;
1030 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1031 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1032 (unsigned int)srv_sign_info.negotiated_smb_signing,
1033 (unsigned int)srv_sign_info.mandatory_signing ));
1034 return;
1037 /* Once we've turned on, ignore any more sessionsetups. */
1038 if (srv_sign_info.doing_signing) {
1039 return;
1042 if (srv_sign_info.free_signing_context)
1043 srv_sign_info.free_signing_context(&srv_sign_info);
1045 srv_sign_info.doing_signing = True;
1047 data = smb_xmalloc(sizeof(*data));
1048 memset(data, '\0', sizeof(*data));
1050 srv_sign_info.signing_context = data;
1052 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1054 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1055 if (response.length)
1056 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1058 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1060 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1061 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1062 BOOLSTR(srv_sign_info.mandatory_signing) ));
1064 /* Initialise the sequence number */
1065 data->send_seq_num = 0;
1067 /* Initialise the list of outstanding packets */
1068 data->outstanding_packet_list = NULL;
1070 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1071 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1072 srv_sign_info.free_signing_context = simple_free_signing_context;